- commit
- 41275417806b970637afb2b06761bef9fc7f0c5c
- parent
- 1c1de7135ef83ea992f5ca574f044af9a3b65b20
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2024-10-05 22:39
fix concurrency: remove player immediately on death before: - (Game.run) send message to player.quit - (Player.writePump) quit and close connection - (Player.readPump) quit and send message to game.unregister - (Game.run) remove player, and maybe close game after: - (Game.run) remove player and close player.send - (Player.writePump) quit and close connection - (Player.readPump) quit and send message to game.unregister - (Game.run) remove player (noop), and maybe close game So the only difference is that player is removed immediately. Game will no longer send messages to player.
Diffstat
| M | game.go | 33 | +++++++++++++++++++++------------ |
| M | player.go | 3 | +-- |
| M | server.go | 8 | ++++---- |
3 files changed, 26 insertions, 18 deletions
diff --git a/game.go b/game.go
@@ -82,6 +82,26 @@ func (game *Game) createId() int {
82 82 return game.lastId
83 83 }
84 84
-1 85 func (game *Game) removePlayer(player *Player) {
-1 86 if _, ok := game.Players[player]; !ok {
-1 87 return
-1 88 }
-1 89
-1 90 if verbose {
-1 91 log.Println("remove player", game.Id, player.Id)
-1 92 }
-1 93 delete(game.Players, player)
-1 94 close(player.send)
-1 95
-1 96 game.Enqueue(Message{
-1 97 "action": "remove",
-1 98 "id": player.Id,
-1 99 })
-1 100 for item, amount := range player.Inventory {
-1 101 game.addToPile(player.Pos, item, amount)
-1 102 }
-1 103 }
-1 104
85 105 func (game *Game) generateMap() {
86 106 for monster := range game.Monsters {
87 107 monster.quit <- true
@@ -273,10 +293,7 @@ func (game *Game) run() {
273 293 "pos": player.Pos,
274 294 })
275 295 case player := <-game.unregister:
276 -1 if verbose {
277 -1 log.Println("remove player", game.Id, player.Id)
278 -1 }
279 -1 delete(game.Players, player)
-1 296 game.removePlayer(player)
280 297 if len(game.Players) == 0 {
281 298 if verbose {
282 299 log.Println("remove game", game.Id)
@@ -284,14 +301,6 @@ func (game *Game) run() {
284 301 mux.Lock()
285 302 delete(games, game.Id)
286 303 mux.Unlock()
287 -1 } else {
288 -1 game.Enqueue(Message{
289 -1 "action": "remove",
290 -1 "id": player.Id,
291 -1 })
292 -1 for item, amount := range player.Inventory {
293 -1 game.addToPile(player.Pos, item, amount)
294 -1 }
295 304 }
296 305 case pmsg := <-game.Msg:
297 306 if pmsg.Msg["action"] == "move" {
diff --git a/player.go b/player.go
@@ -8,7 +8,6 @@ import ( 8 8 9 9 type Player struct { 10 10 Game *Game11 -1 quit chan bool12 11 send chan []Message 13 12 queue []Message 14 13 conn *websocket.Conn @@ -45,7 +44,7 @@ func (player *Player) Flush() { 45 44 func (player *Player) TakeDamage(attack float64) { 46 45 amount := uint(math.Round(attack * attack / (attack + player.Defense))) 47 46 if amount > player.Health {48 -1 player.quit <- true-1 47 player.Game.removePlayer(player) 49 48 } else { 50 49 player.Health -= amount 51 50 player.CommitStats()
diff --git a/server.go b/server.go
@@ -61,7 +61,10 @@ func (player *Player) writePump() {
61 61
62 62 for {
63 63 select {
64 -1 case data := <-player.send:
-1 64 case data, ok := <-player.send:
-1 65 if !ok {
-1 66 return
-1 67 }
65 68 err := player.conn.WriteJSON(data)
66 69 if err != nil {
67 70 if verbose {
@@ -69,8 +72,6 @@ func (player *Player) writePump() {
69 72 }
70 73 return
71 74 }
72 -1 case <-player.quit:
73 -1 return
74 75 case <-ticker.C:
75 76 if !player.alive {
76 77 return
@@ -100,7 +101,6 @@ func serveWs(w http.ResponseWriter, r *http.Request) {
100 101
101 102 player := &Player{
102 103 Game: game,
103 -1 quit: make(chan bool),
104 104 send: make(chan []Message),
105 105 queue: []Message{},
106 106 conn: conn,