boardgame.io
boardgame.io copied to clipboard
Refactor lobby / state initialisation code
Currently the game state is initialised at game creation. This has a number of consequences:
- the number of players must be known exactly before the game is created (no "open" public lobbies")
- players can start making moves before all players have joined, however the game will most likely get stuck when an empty slot is reached (or if it is never filled)
- the server has no way to know if a player is not present, and cannot take their turn (i.e. to timeout disconnected players)
- EDIT: another potential use case is deleting "abandoned" games after a set period of time.
Ideally the game state would be initialised as a separate step, i.e.
- The game is created with min / max player counts
- Players connect and claim slots
- When the server or a nominated player believes the game is "ready" the game "starts" and the state is initialised
Future enhancements could include onConnect
/onDisconnect
handlers for players so that the server can apply custom logic for these cases (e.g. timeout players)
Possible implementation:
Too many changes to the lobby API could break a lot of existing games. One way to resolve these issues would be to use the existing state and game definition to handle lobbies. For instance:
- When a game is created through the API it could also return a special "host" token,
- Games could define a special
lobby
phase (a basic one could be supplied with boardgame.io) - If a lobby phase is present in the game definition then the state is not initialised when the game is created. If a lobby state is not present then nothing changes in the game creation logic.
- in the lobby phase, a number of predefined moves are available such as
claimSlot
,setName
,setReadyState
etc. - A custom 'isReady` function could be defined on the phase, which can be checked after each "claimSlot" / "setReadyState" move. When this returns true, the game "starts" and state is initialised in the usual way.
'isReady' could be defined a number of ways, for instance when all players setReadyState(true)
, or if somebody calls setLobbyReady(host_token)
supplying the host token returned during game creation.
I'm happy to start looking at this in a couple of days, but I know there are a number of "lobby" related issues open at the minute (and a design document somewhere?) so I'm not sure how this fits in with this other work.
@will-hart Sorry, I missed this. Will take some time to digest this and get back to you.
As a corollary to/variation on this request, some games can handle players coming and going while the game is in play.
The original description talks about timing out players, presumably to skip them in the play order. This would be the best mode if the player may return, and may be the only mode for some games. But many card games would allow a player to permanently leave by "turning in their cards". This would imply that they aren't coming back and the return of the cards allows the game to preserve resources. A typical result (which can be left to the game to implement, but just for an example) would involve taking all of the players cards and putting them into the global discard pile or shuffling them into the draw pile. For this reason, it might be good to distinguish between a player being unavailable during play and a player that physically left the game.
Additionally, many card games can deal with a player entering after the game has gone a few rounds by simply dealing them a fresh hand. They may be at a disadvantage in terms of game progress, but it is sometimes a preferable solution to waiting for the game to end or abandoning the game and starting a new one.