laneya2

cave exploration game
git clone https://git.ce9e.org/laneya2.git

commit
570ae983fe02f3bfd0c9a1855ec058016dc9124f
parent
b423166e746fe9db5c359027d4add2d678f1e5b6
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-09-29 08:25
send response in a single transaction

Diffstat

M game.go 102 +++++++++++++++++++++++++++++--------------------------------
M monster.go 18 +++++++-----------
M player.go 81 ++++++++++++++++++++++++++++++-------------------------------
M server.go 5 +++--

4 files changed, 98 insertions, 108 deletions


diff --git a/game.go b/game.go

@@ -63,9 +63,15 @@ func getGame(id string) *Game {
   63    63 	return game
   64    64 }
   65    65 
   66    -1 func (game *Game) broadcast(msgs []Message) {
   -1    66 func (game *Game) Enqueue(msg Message) {
   67    67 	for player, _ := range game.Players {
   68    -1 		player.Send <- msgs
   -1    68 		player.Enqueue(msg)
   -1    69 	}
   -1    70 }
   -1    71 
   -1    72 func (game *Game) Flush() {
   -1    73 	for player, _ := range game.Players {
   -1    74 		player.Flush()
   69    75 	}
   70    76 }
   71    77 
@@ -131,16 +137,14 @@ func (game *Game) MaybeNextLevel() {
  131   137 	}
  132   138 
  133   139 	game.generateMap()
  134    -1 	msgs := []Message{
  135    -1 		Message{
  136    -1 			"action": "setLevel",
  137    -1 			"rects":  game.Rects,
  138    -1 			"ladder": game.Ladder,
  139    -1 		},
  140    -1 	}
   -1   140 	game.Enqueue(Message{
   -1   141 		"action": "setLevel",
   -1   142 		"rects":  game.Rects,
   -1   143 		"ladder": game.Ladder,
   -1   144 	})
  141   145 
  142   146 	for monster := range game.Monsters {
  143    -1 		msgs = append(msgs, Message{
   -1   147 		game.Enqueue(Message{
  144   148 			"action": "create",
  145   149 			"type":   "monster",
  146   150 			"rune":   string(monster.Rune),
@@ -151,14 +155,12 @@ func (game *Game) MaybeNextLevel() {
  151   155 
  152   156 	for player := range game.Players {
  153   157 		player.Pos = Point{0, 0}
  154    -1 		msgs = append(msgs, Message{
   -1   158 		game.Enqueue(Message{
  155   159 			"action": "setPosition",
  156   160 			"id":     player.Id,
  157   161 			"pos":    player.Pos,
  158   162 		})
  159   163 	}
  160    -1 
  161    -1 	game.broadcast(msgs)
  162   164 }
  163   165 
  164   166 func (game *Game) getMonsterAt(pos Point) *Monster {
@@ -194,14 +196,12 @@ func (game *Game) addToPile(pos Point, item string) {
  194   196 		pile.Items[item] = value + 1
  195   197 	} else {
  196   198 		pile.Items[item] = 1
  197    -1 		game.broadcast([]Message{
  198    -1 			Message{
  199    -1 				"action": "create",
  200    -1 				"type":   "pile",
  201    -1 				"id":     pile.Id,
  202    -1 				"rune":   "%",
  203    -1 				"pos":    pos,
  204    -1 			},
   -1   199 		game.Enqueue(Message{
   -1   200 			"action": "create",
   -1   201 			"type":   "pile",
   -1   202 			"id":     pile.Id,
   -1   203 			"rune":   "%",
   -1   204 			"pos":    pos,
  205   205 		})
  206   206 	}
  207   207 }
@@ -213,24 +213,22 @@ func (game *Game) run() {
  213   213 			if verbose {
  214   214 				log.Println("create player", game.Id, player.Id)
  215   215 			}
  216    -1 			setup := []Message{
  217    -1 				Message{
  218    -1 					"action": "setId",
  219    -1 					"id":     player.Id,
  220    -1 				},
  221    -1 				Message{
  222    -1 					"action":      "setHealth",
  223    -1 					"health":      player.Health,
  224    -1 					"healthTotal": player.HealthTotal,
  225    -1 				},
  226    -1 				Message{
  227    -1 					"action": "setLevel",
  228    -1 					"rects":  game.Rects,
  229    -1 					"ladder": game.Ladder,
  230    -1 				},
  231    -1 			}
   -1   216 			player.Enqueue(Message{
   -1   217 				"action": "setId",
   -1   218 				"id":     player.Id,
   -1   219 			})
   -1   220 			player.Enqueue(Message{
   -1   221 				"action":      "setHealth",
   -1   222 				"health":      player.Health,
   -1   223 				"healthTotal": player.HealthTotal,
   -1   224 			})
   -1   225 			player.Enqueue(Message{
   -1   226 				"action": "setLevel",
   -1   227 				"rects":  game.Rects,
   -1   228 				"ladder": game.Ladder,
   -1   229 			})
  232   230 			for monster := range game.Monsters {
  233    -1 				setup = append(setup, Message{
   -1   231 				player.Enqueue(Message{
  234   232 					"action": "create",
  235   233 					"type":   "monster",
  236   234 					"rune":   string(monster.Rune),
@@ -239,7 +237,7 @@ func (game *Game) run() {
  239   237 				})
  240   238 			}
  241   239 			for pos, pile := range game.Piles {
  242    -1 				setup = append(setup, Message{
   -1   240 				player.Enqueue(Message{
  243   241 					"action": "create",
  244   242 					"type":   "pile",
  245   243 					"rune":   "%",
@@ -248,7 +246,7 @@ func (game *Game) run() {
  248   246 				})
  249   247 			}
  250   248 			for p := range game.Players {
  251    -1 				setup = append(setup, Message{
   -1   249 				player.Enqueue(Message{
  252   250 					"action": "create",
  253   251 					"type":   "player",
  254   252 					"rune":   "@",
@@ -256,18 +254,15 @@ func (game *Game) run() {
  256   254 					"pos":    p.Pos,
  257   255 				})
  258   256 			}
  259    -1 			player.Send <- setup
  260   257 
  261   258 			game.Players[player] = true
  262   259 
  263    -1 			game.broadcast([]Message{
  264    -1 				Message{
  265    -1 					"action": "create",
  266    -1 					"type":   "player",
  267    -1 					"rune":   "@",
  268    -1 					"id":     player.Id,
  269    -1 					"pos":    player.Pos,
  270    -1 				},
   -1   260 			game.Enqueue(Message{
   -1   261 				"action": "create",
   -1   262 				"type":   "player",
   -1   263 				"rune":   "@",
   -1   264 				"id":     player.Id,
   -1   265 				"pos":    player.Pos,
  271   266 			})
  272   267 		case player := <-game.unregister:
  273   268 			if verbose {
@@ -282,11 +277,9 @@ func (game *Game) run() {
  282   277 				delete(games, game.Id)
  283   278 				mux.Unlock()
  284   279 			} else {
  285    -1 				game.broadcast([]Message{
  286    -1 					Message{
  287    -1 						"action": "remove",
  288    -1 						"id":     player.Id,
  289    -1 					},
   -1   280 				game.Enqueue(Message{
   -1   281 					"action": "remove",
   -1   282 					"id":     player.Id,
  290   283 				})
  291   284 			}
  292   285 		case pmsg := <-game.Msg:
@@ -318,5 +311,6 @@ func (game *Game) run() {
  318   311 				}
  319   312 			}
  320   313 		}
   -1   314 		game.Flush()
  321   315 	}
  322   316 }

diff --git a/monster.go b/monster.go

@@ -75,11 +75,9 @@ func (monster *Monster) TakeDamage(amount int) {
   75    75 		monster.quit <- true
   76    76 		delete(monster.Game.Monsters, monster)
   77    77 		monster.Game.addToPile(monster.Pos, "potion")
   78    -1 		monster.Game.broadcast([]Message{
   79    -1 			Message{
   80    -1 				"action": "remove",
   81    -1 				"id":     monster.Id,
   82    -1 			},
   -1    78 		monster.Game.Enqueue(Message{
   -1    79 			"action": "remove",
   -1    80 			"id":     monster.Id,
   83    81 		})
   84    82 	}
   85    83 }
@@ -92,12 +90,10 @@ func (monster *Monster) Move(dir string) {
   92    90 		player.TakeDamage(2)
   93    91 	} else if game.getMonsterAt(pos) == nil && game.IsFree(pos) {
   94    92 		monster.Pos = pos
   95    -1 		game.broadcast([]Message{
   96    -1 			Message{
   97    -1 				"action": "setPosition",
   98    -1 				"id":     monster.Id,
   99    -1 				"pos":    monster.Pos,
  100    -1 			},
   -1    93 		game.Enqueue(Message{
   -1    94 			"action": "setPosition",
   -1    95 			"id":     monster.Id,
   -1    96 			"pos":    monster.Pos,
  101    97 		})
  102    98 	}
  103    99 }

diff --git a/player.go b/player.go

@@ -4,7 +4,8 @@ import "github.com/gorilla/websocket"
    4     4 
    5     5 type Player struct {
    6     6 	Game        *Game
    7    -1 	Send        chan []Message
   -1     7 	send        chan []Message
   -1     8 	queue       []Message
    8     9 	conn        *websocket.Conn
    9    10 	alive       bool
   10    11 	Id          int
@@ -20,16 +21,25 @@ type PlayerMessage struct {
   20    21 	Msg    Message
   21    22 }
   22    23 
   -1    24 func (player *Player) Enqueue(msg Message) {
   -1    25 	player.queue = append(player.queue, msg)
   -1    26 }
   -1    27 
   -1    28 func (player *Player) Flush() {
   -1    29 	if len(player.queue) > 0 {
   -1    30 		player.send <- player.queue
   -1    31 		player.queue = []Message{}
   -1    32 	}
   -1    33 }
   -1    34 
   23    35 func (player *Player) TakeDamage(amount uint) {
   24    36 	// TODO: death if amount >= player.Health
   25    37 	player.Health -= amount
   26    -1 	player.Send <- []Message{
   27    -1 		Message{
   28    -1 			"action":      "setHealth",
   29    -1 			"health":      player.Health,
   30    -1 			"healthTotal": player.HealthTotal,
   31    -1 		},
   32    -1 	}
   -1    38 	player.Enqueue(Message{
   -1    39 		"action":      "setHealth",
   -1    40 		"health":      player.Health,
   -1    41 		"healthTotal": player.HealthTotal,
   -1    42 	})
   33    43 }
   34    44 
   35    45 func (player *Player) Heal(amount uint) {
@@ -37,13 +47,11 @@ func (player *Player) Heal(amount uint) {
   37    47 	if player.Health > player.HealthTotal {
   38    48 		player.Health = player.HealthTotal
   39    49 	}
   40    -1 	player.Send <- []Message{
   41    -1 		Message{
   42    -1 			"action":      "setHealth",
   43    -1 			"health":      player.Health,
   44    -1 			"healthTotal": player.HealthTotal,
   45    -1 		},
   46    -1 	}
   -1    50 	player.Enqueue(Message{
   -1    51 		"action":      "setHealth",
   -1    52 		"health":      player.Health,
   -1    53 		"healthTotal": player.HealthTotal,
   -1    54 	})
   47    55 }
   48    56 
   49    57 func (player *Player) AddItem(item string, amount uint) {
@@ -55,13 +63,11 @@ func (player *Player) AddItem(item string, amount uint) {
   55    63 	}
   56    64 	player.Inventory[item] = value
   57    65 
   58    -1 	player.Send <- []Message{
   59    -1 		Message{
   60    -1 			"action": "setInventory",
   61    -1 			"item":   item,
   62    -1 			"amount": value,
   63    -1 		},
   64    -1 	}
   -1    66 	player.Enqueue(Message{
   -1    67 		"action": "setInventory",
   -1    68 		"item":   item,
   -1    69 		"amount": value,
   -1    70 	})
   65    71 }
   66    72 
   67    73 func (player *Player) RemoveItem(item string, amount uint) bool {
@@ -78,13 +84,11 @@ func (player *Player) RemoveItem(item string, amount uint) bool {
   78    84 		success = true
   79    85 	}
   80    86 
   81    -1 	player.Send <- []Message{
   82    -1 		Message{
   83    -1 			"action": "setInventory",
   84    -1 			"item":   item,
   85    -1 			"amount": value,
   86    -1 		},
   87    -1 	}
   -1    87 	player.Enqueue(Message{
   -1    88 		"action": "setInventory",
   -1    89 		"item":   item,
   -1    90 		"amount": value,
   -1    91 	})
   88    92 
   89    93 	return success
   90    94 }
@@ -97,12 +101,10 @@ func (player *Player) Move(dir string) {
   97   101 		monster.TakeDamage(5)
   98   102 	} else if game.IsFree(pos) {
   99   103 		player.Pos = pos
  100    -1 		game.broadcast([]Message{
  101    -1 			Message{
  102    -1 				"action": "setPosition",
  103    -1 				"id":     player.Id,
  104    -1 				"pos":    player.Pos,
  105    -1 			},
   -1   104 		game.Enqueue(Message{
   -1   105 			"action": "setPosition",
   -1   106 			"id":     player.Id,
   -1   107 			"pos":    player.Pos,
  106   108 		})
  107   109 
  108   110 		game.MaybeNextLevel()
@@ -117,11 +119,9 @@ func (player *Player) PickupItems() {
  117   119 		for item, amount := range pile.Items {
  118   120 			player.AddItem(item, amount)
  119   121 		}
  120    -1 		game.broadcast([]Message{
  121    -1 			Message{
  122    -1 				"action": "remove",
  123    -1 				"id":     pile.Id,
  124    -1 			},
   -1   122 		game.Enqueue(Message{
   -1   123 			"action": "remove",
   -1   124 			"id":     pile.Id,
  125   125 		})
  126   126 	}
  127   127 }
@@ -133,7 +133,6 @@ func (player *Player) DropItem(item string) {
  133   133 }
  134   134 
  135   135 func (player *Player) UseItem(item string) {
  136    -1 	// TODO: send result in a single transaction
  137   136 	if item == "potion" {
  138   137 		if player.Health < player.HealthTotal {
  139   138 			if player.RemoveItem(item, 1) {

diff --git a/server.go b/server.go

@@ -58,7 +58,7 @@ func (player *Player) writePump() {
   58    58 
   59    59 	for {
   60    60 		select {
   61    -1 		case data := <-player.Send:
   -1    61 		case data := <-player.send:
   62    62 			err := player.conn.WriteJSON(data)
   63    63 			if err != nil {
   64    64 				if verbose {
@@ -95,7 +95,8 @@ func serveWs(w http.ResponseWriter, r *http.Request) {
   95    95 
   96    96 	player := &Player{
   97    97 		Game:        game,
   98    -1 		Send:        make(chan []Message),
   -1    98 		send:        make(chan []Message),
   -1    99 		queue:       []Message{},
   99   100 		conn:        conn,
  100   101 		alive:       true,
  101   102 		Id:          game.createId(),