142 lines
3.0 KiB
Go
142 lines
3.0 KiB
Go
package playerlist
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/Tnze/go-mc/bot"
|
|
"github.com/Tnze/go-mc/chat"
|
|
"github.com/Tnze/go-mc/chat/sign"
|
|
"github.com/Tnze/go-mc/data/packetid"
|
|
pk "github.com/Tnze/go-mc/net/packet"
|
|
"github.com/Tnze/go-mc/yggdrasil/user"
|
|
)
|
|
|
|
type PlayerList struct {
|
|
PlayerInfos map[uuid.UUID]*PlayerInfo
|
|
}
|
|
|
|
func New(c *bot.Client) *PlayerList {
|
|
pl := PlayerList{
|
|
PlayerInfos: make(map[uuid.UUID]*PlayerInfo),
|
|
}
|
|
c.Events.AddListener(
|
|
bot.PacketHandler{
|
|
Priority: 64, ID: packetid.ClientboundPlayerInfoUpdate,
|
|
F: pl.handlePlayerInfoUpdatePacket,
|
|
},
|
|
bot.PacketHandler{
|
|
Priority: 64, ID: packetid.ClientboundPlayerInfoRemove,
|
|
F: pl.handlePlayerInfoRemovePacket,
|
|
},
|
|
)
|
|
return &pl
|
|
}
|
|
|
|
func (pl *PlayerList) handlePlayerInfoUpdatePacket(p pk.Packet) error {
|
|
r := bytes.NewReader(p.Data)
|
|
|
|
action := pk.NewFixedBitSet(6)
|
|
if _, err := action.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
|
|
var length pk.VarInt
|
|
if _, err := length.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
|
|
for i := 0; i < int(length); i++ {
|
|
var id pk.UUID
|
|
if _, err := id.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
|
|
player, ok := pl.PlayerInfos[uuid.UUID(id)]
|
|
if !ok { // create new player info if not exist
|
|
player = new(PlayerInfo)
|
|
pl.PlayerInfos[uuid.UUID(id)] = player
|
|
}
|
|
|
|
// add player
|
|
if action.Get(0) {
|
|
var name pk.String
|
|
var properties []user.Property
|
|
if _, err := (pk.Tuple{&name, pk.Array(&properties)}).ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
player.GameProfile = GameProfile{
|
|
ID: uuid.UUID(id),
|
|
Name: string(name),
|
|
Properties: properties,
|
|
}
|
|
}
|
|
// initialize chat
|
|
if action.Get(1) {
|
|
var chatSession pk.Option[sign.Session, *sign.Session]
|
|
if _, err := chatSession.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
player.ChatSession = chatSession.Pointer()
|
|
}
|
|
// update gamemode
|
|
if action.Get(2) {
|
|
var gamemode pk.VarInt
|
|
if _, err := gamemode.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
player.Gamemode = int32(gamemode)
|
|
}
|
|
// update listed
|
|
if action.Get(3) {
|
|
var listed pk.Boolean
|
|
if _, err := listed.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
player.Listed = bool(listed)
|
|
}
|
|
// update latency
|
|
if action.Get(4) {
|
|
var latency pk.VarInt
|
|
if _, err := latency.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
player.Latency = int32(latency)
|
|
}
|
|
// display name
|
|
if action.Get(5) {
|
|
var displayName pk.Option[chat.Message, *chat.Message]
|
|
if _, err := displayName.ReadFrom(r); err != nil {
|
|
return err
|
|
}
|
|
if displayName.Has {
|
|
player.DisplayName = &displayName.Val
|
|
} else {
|
|
player.DisplayName = nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (pl *PlayerList) handlePlayerInfoRemovePacket(p pk.Packet) error {
|
|
return nil
|
|
}
|
|
|
|
type PlayerInfo struct {
|
|
GameProfile
|
|
ChatSession *sign.Session
|
|
Gamemode int32
|
|
Latency int32
|
|
Listed bool
|
|
DisplayName *chat.Message
|
|
}
|
|
|
|
type GameProfile struct {
|
|
ID uuid.UUID
|
|
Name string
|
|
Properties []user.Property
|
|
}
|