GlobalChat component
This commit is contained in:
114
server/chat.go
Normal file
114
server/chat.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/chat"
|
||||||
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
|
"github.com/Tnze/go-mc/nbt"
|
||||||
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GlobalChat struct {
|
||||||
|
msg chan chatItem
|
||||||
|
join chan *Player
|
||||||
|
quit chan *Player
|
||||||
|
|
||||||
|
players map[uuid.UUID]*Player
|
||||||
|
}
|
||||||
|
|
||||||
|
type chatItem struct {
|
||||||
|
p *Player
|
||||||
|
text string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGlobalChat() GlobalChat {
|
||||||
|
return GlobalChat{
|
||||||
|
msg: make(chan chatItem),
|
||||||
|
join: make(chan *Player),
|
||||||
|
quit: make(chan *Player),
|
||||||
|
players: make(map[uuid.UUID]*Player),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GlobalChat) AddPlayer(p *Player) {
|
||||||
|
g.join <- p
|
||||||
|
p.Add(PacketHandler{
|
||||||
|
ID: packetid.ServerboundChat,
|
||||||
|
F: func(packet Packet757) error {
|
||||||
|
var msg pk.String
|
||||||
|
if err := pk.Packet(packet).Scan(&msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
text, _ := chat.TransCtrlSeq(string(msg), false)
|
||||||
|
g.msg <- chatItem{p: p, text: text}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GlobalChat) RemovePlayer(p *Player) {
|
||||||
|
g.quit <- p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c chatItem) ToMessage() chat.Message {
|
||||||
|
return chat.TranslateMsg(
|
||||||
|
"chat.type.text",
|
||||||
|
chat.Message{
|
||||||
|
Text: c.p.Name,
|
||||||
|
ClickEvent: chat.SuggestCommand("/msg " + c.p.Name),
|
||||||
|
HoverEvent: chat.ShowEntity(playerToSNBT(c.p)),
|
||||||
|
},
|
||||||
|
chat.Text(c.text),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func playerToSNBT(p *Player) string {
|
||||||
|
var s nbt.StringifiedMessage
|
||||||
|
entity := struct {
|
||||||
|
ID string `nbt:"id"`
|
||||||
|
Name string `nbt:"name"`
|
||||||
|
}{
|
||||||
|
ID: p.UUID.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := nbt.Marshal(entity)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nbt.Unmarshal(data, &s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GlobalChat) Run(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case item := <-g.msg:
|
||||||
|
packet := Packet757(pk.Marshal(
|
||||||
|
packetid.ClientboundChat,
|
||||||
|
item.ToMessage(),
|
||||||
|
pk.Byte(0),
|
||||||
|
pk.UUID(item.p.UUID),
|
||||||
|
))
|
||||||
|
for _, p := range g.players {
|
||||||
|
err := p.WritePacket(packet)
|
||||||
|
if err != nil {
|
||||||
|
p.PutErr(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case p := <-g.join:
|
||||||
|
g.players[p.UUID] = p
|
||||||
|
case p := <-g.quit:
|
||||||
|
delete(g.players, p.UUID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,7 @@ type Game struct {
|
|||||||
Dim Level
|
Dim Level
|
||||||
*PlayerList
|
*PlayerList
|
||||||
KeepAlive KeepAlive
|
KeepAlive KeepAlive
|
||||||
|
GlobalChat GlobalChat
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed DimensionCodec.snbt
|
//go:embed DimensionCodec.snbt
|
||||||
@ -40,11 +41,13 @@ func NewGame(dim Level, playerList *PlayerList) *Game {
|
|||||||
Dim: dim,
|
Dim: dim,
|
||||||
PlayerList: playerList,
|
PlayerList: playerList,
|
||||||
KeepAlive: NewKeepAlive(),
|
KeepAlive: NewKeepAlive(),
|
||||||
|
GlobalChat: NewGlobalChat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) Run(ctx context.Context) {
|
func (g *Game) Run(ctx context.Context) {
|
||||||
go g.KeepAlive.Run(ctx)
|
go g.KeepAlive.Run(ctx)
|
||||||
|
go g.GlobalChat.Run(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) {
|
func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) {
|
||||||
@ -59,6 +62,8 @@ func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net
|
|||||||
defer remove()
|
defer remove()
|
||||||
p := &Player{
|
p := &Player{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
|
Name: name,
|
||||||
|
UUID: id,
|
||||||
EntityID: g.newEID(),
|
EntityID: g.newEID(),
|
||||||
Gamemode: 1,
|
Gamemode: 1,
|
||||||
handlers: make(map[int32][]packetHandlerFunc),
|
handlers: make(map[int32][]packetHandlerFunc),
|
||||||
@ -92,6 +97,9 @@ func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net
|
|||||||
g.KeepAlive.AddPlayer(p)
|
g.KeepAlive.AddPlayer(p)
|
||||||
defer g.KeepAlive.RemovePlayer(p)
|
defer g.KeepAlive.RemovePlayer(p)
|
||||||
|
|
||||||
|
g.GlobalChat.AddPlayer(p)
|
||||||
|
defer g.GlobalChat.RemovePlayer(p)
|
||||||
|
|
||||||
var packet pk.Packet
|
var packet pk.Packet
|
||||||
for {
|
for {
|
||||||
err := p.ReadPacket(&packet)
|
err := p.ReadPacket(&packet)
|
||||||
|
@ -13,6 +13,7 @@ type Player struct {
|
|||||||
*net.Conn
|
*net.Conn
|
||||||
writeLock sync.Mutex
|
writeLock sync.Mutex
|
||||||
|
|
||||||
|
Name string
|
||||||
uuid.UUID
|
uuid.UUID
|
||||||
EntityID int32
|
EntityID int32
|
||||||
Gamemode byte
|
Gamemode byte
|
||||||
|
Reference in New Issue
Block a user