GlobalChat component

This commit is contained in:
Tnze
2021-12-24 02:01:23 +08:00
parent 51cbe4c648
commit 322188d254
3 changed files with 124 additions and 1 deletions

114
server/chat.go Normal file
View 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)
}
}
}

View File

@ -26,7 +26,8 @@ type Game struct {
eid int32
Dim Level
*PlayerList
KeepAlive KeepAlive
KeepAlive KeepAlive
GlobalChat GlobalChat
}
//go:embed DimensionCodec.snbt
@ -40,11 +41,13 @@ func NewGame(dim Level, playerList *PlayerList) *Game {
Dim: dim,
PlayerList: playerList,
KeepAlive: NewKeepAlive(),
GlobalChat: NewGlobalChat(),
}
}
func (g *Game) Run(ctx context.Context) {
go g.KeepAlive.Run(ctx)
go g.GlobalChat.Run(ctx)
}
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()
p := &Player{
Conn: conn,
Name: name,
UUID: id,
EntityID: g.newEID(),
Gamemode: 1,
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)
defer g.KeepAlive.RemovePlayer(p)
g.GlobalChat.AddPlayer(p)
defer g.GlobalChat.RemovePlayer(p)
var packet pk.Packet
for {
err := p.ReadPacket(&packet)

View File

@ -13,6 +13,7 @@ type Player struct {
*net.Conn
writeLock sync.Mutex
Name string
uuid.UUID
EntityID int32
Gamemode byte