diff options
| -rw-r--r-- | classic/ext_player_list.go | 30 | ||||
| -rw-r--r-- | classic/packets.go | 4 | ||||
| -rw-r--r-- | server/player.go | 28 | ||||
| -rw-r--r-- | server/server.go | 55 |
4 files changed, 107 insertions, 10 deletions
diff --git a/classic/ext_player_list.go b/classic/ext_player_list.go new file mode 100644 index 0000000..f01d550 --- /dev/null +++ b/classic/ext_player_list.go @@ -0,0 +1,30 @@ +package classic + +type AddPlayerName struct { + NameId int16 + PlayerName String + ListName String + GroupName String + GroupRank byte +} +func (p *AddPlayerName) PacketId() byte { + return 0x16 +} + +type RemovePlayerName struct { + NameId int16 +} +func (p *RemovePlayerName) PacketId() byte { + return 0x18 +} + +type AddEntity2 struct { + EntityId byte + InGameName String + SkinName String + X, Y, Z Fixed + Yaw, Pitch byte +} +func (p *AddEntity2) PacketId() byte { + return 0x21 +} diff --git a/classic/packets.go b/classic/packets.go index 0e55429..40f659c 100644 --- a/classic/packets.go +++ b/classic/packets.go @@ -201,6 +201,10 @@ func createPacketType(packetId byte, client bool, ext map[string]bool) Packet { case 0x10: return &ExtInfo {} case 0x11: return &ExtEntry {} case 0x13: return &CustomBlocksSupportLevel {} + case 0x16: return &AddPlayerName {} + case 0x18: return &RemovePlayerName {} + case 0x21: return &AddEntity2 {} + case 0x29: return &SetMapEnvProperty {} default: return nil } } diff --git a/server/player.go b/server/player.go index 86a32fa..e436714 100644 --- a/server/player.go +++ b/server/player.go @@ -284,9 +284,10 @@ func (p *player) OnLevelData(from *level, info levelInfo, data io.ReadCloser) { TexturePackUrl: classic.PadDString(info.TexturePack), }) }) - p.client.SendPacket(p, &classic.SpawnPlayerExt { - PlayerId: -1, - Username: classic.PadString(p.name), + p.client.SendPacket(p, &classic.AddEntity2 { + EntityId: 255, + InGameName: classic.PadString(p.name), + SkinName: classic.PadString(p.name), X: classic.Fixed(p.state.Pos.X), Y: classic.Fixed(p.state.Pos.Y), Z: classic.Fixed(p.state.Pos.Z), @@ -312,9 +313,10 @@ func (p *player) OnLevelError(from *level, message string, info levelInfo) { func (p *player) OnPlayer( from *level, id levelPlayerId, name string, pos entityPos) { p.Act(from, func() { - p.client.SendPacket(p, &classic.SpawnPlayerExt { - PlayerId: int8(id), - Username: classic.PadString(name), + p.client.SendPacket(p, &classic.AddEntity2 { + EntityId: byte(id), + InGameName: classic.PadString(name), + SkinName: classic.PadString(name), X: classic.Fixed(pos.X), Y: classic.Fixed(pos.Y), Z: classic.Fixed(pos.Z), @@ -328,6 +330,20 @@ func (p *player) OnRemovePlayer(from *level, id levelPlayerId) { }) } +func (p *player) OnAddListEntry(from *Server, entry listEntry) { + p.client.SendPacket(p, &classic.AddPlayerName { + NameId: int16(entry.id), + PlayerName: classic.PadString(entry.playerName), + ListName: classic.PadString(entry.listName), + }) +} + +func (p *player) OnRemoveListEntry(from *Server, id listId) { + p.client.SendPacket(p, &classic.RemovePlayerName { + NameId: int16(id), + }) +} + func (p *player) OnMovePlayer( from *level, id levelPlayerId, pos entityPos, facing entityFacing) { p.Act(from, func() { diff --git a/server/server.go b/server/server.go index 29aa66f..213bd64 100644 --- a/server/server.go +++ b/server/server.go @@ -21,11 +21,13 @@ var supportedExtensions = []string { "LongerMessages", "FullCP437", "CustomBlocks", + "ExtPlayerList.2", } var requiredExtensions = []string { "ExtEntityPositions", "EnvMapAspect.2", "CustomBlocks", + "ExtPlayerList.2", } type ServerInfo struct { @@ -40,11 +42,14 @@ type Server struct { info ServerInfo clients map[*client]bool players map[string]*player + listIds map[listId]string + playerList map[string]listEntry levels map[levelId]*level listener net.Listener stopping bool stopped chan struct{} } + type worldState struct { LastId levelId SpawnLevel levelId @@ -52,11 +57,21 @@ type worldState struct { Banned map[string]string } +type listId int16 +type listEntry struct { + id listId + playerName string + listName string + player *player +} + func NewServer(info ServerInfo) *Server { s := &Server { info: info, clients: make(map[*client]bool), players: make(map[string]*player), + listIds: make(map[listId]string), + playerList: make(map[string]listEntry), levels: make(map[levelId]*level), stopped: make(chan struct{}), } @@ -202,10 +217,13 @@ func (s *Server) OnDisconnect(cl *client) { } func (s *Server) OnLeave(pl *player, username string) { - s.Broadcast(nil, fmt.Sprintf("&e%s has left", username)) - if s.players[username] == pl { - delete(s.players, username) - } + s.Act(pl, func() { + s.Broadcast(nil, fmt.Sprintf("&e%s has left", username)) + if s.players[username] == pl { + delete(s.players, username) + s.removeListEntry(username) + } + }) } func (s *Server) OnPlayerMessage(from *player, name string, message string) { @@ -248,6 +266,9 @@ func (s *Server) newPlayer( cl *client, name string, ext map[string]bool) *player { pl := newPlayer(s, cl, name, ext) s.players[name] = pl + for _, entry := range s.playerList { + pl.OnAddListEntry(s, entry) + } return pl } @@ -320,9 +341,35 @@ func (s *Server) NewPlayer( s.newPlayer(cl, name, ext) s.GetPlayer(from, name, reply) } + s.addListEntry(name) }) } +func (s *Server) addListEntry(name string) { + var id listId + for s.listIds[id] != "" { + id++ + } + s.listIds[id] = name + s.playerList[name] = listEntry { + id: id, + playerName: name, + listName: name, + } + for _, player := range s.players { + player.OnAddListEntry(s, s.playerList[name]) + } +} + +func (s *Server) removeListEntry(name string) { + id := s.playerList[name].id + delete(s.playerList, name) + delete(s.listIds, id) + for _, player := range s.players { + player.OnRemoveListEntry(s, id) + } +} + func (s *Server) getLevel(lvl levelId) *level { if s.levels[lvl] == nil { s.levels[lvl] = loadLevel(s, lvl, lvl == s.SpawnLevel) |
