summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--classic/ext_player_list.go30
-rw-r--r--classic/packets.go4
-rw-r--r--server/player.go28
-rw-r--r--server/server.go55
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)