Asobi - turn-based game framework - server
A multiplayer turn-based game server for Node.js.
Installation
npm install @basementuniverse/asobi-server
Setup
See jsonpad-schema.md for instructions on setting up JSONPad.
Usage
import { AsobiServer, Game } from '@basementuniverse/asobi-server';
const server = new AsobiServer({
jsonpadServerToken: '<YOUR JSONPAD TOKEN>',
jsonpadGamesList: '<YOUR JSONPAD LIST PATHNAME>',
jsonpadPlayersList: '<YOUR JSONPAD LIST PATHNAME>',
jsonpadRateLimit: 150,
mode: 'turns',
minPlayers: 2,
maxPlayers: 2,
joinTimeLimit: null,
turnTimeLimit: null,
roundTimeLimit: null,
gameTimeLimit: null,
gameSchema: {
type: 'object',
},
playerSchema: {
type: 'object',
},
moveSchema: {
type: 'object',
},
hooks: {
setup: (api: Express): void => {
},
createGame: async (game: Game): Promise<Game> => {
return game;
},
joinGame: async (game: Game, player: Player): Promise<Game> => {
return game;
},
move: async (game: Game, player: Player, move: Move): Promise<Game> => {
return game;
},
round: async (game: Game): Promise<Game> => {
return game;
},
finishGame: async (game: Game): Promise<Game> => {
return game;
},
},
});
server.start();
Types
type Game = {
id: string;
status: GameStatus;
startedAt: Date | null;
finishedAt: Date | null;
lastEventType:
| 'game-created'
| 'player-joined'
| 'player-moved'
| 'timed-out'
| 'game-finished';
lastEventData: any;
numPlayers: number;
players: Player[];
moves: Move[];
round: number;
state: any;
startsAt?: Date | null;
finishesAt?: Date | null;
turnFinishesAt?: Date | null;
roundFinishesAt?: Date | null;
[key: string]: any;
};
type Player = {
id: string;
name: string;
status: PlayerStatus;
state?: any;
hiddenState?: any;
[key: string]: any;
};
type Move = {
playerId: string;
movedAt: Date;
data?: any;
};
enum GameStatus {
WAITING_TO_START = 'waiting_to_start',
STARTED = 'started',
FINISHED = 'finished',
}
enum PlayerStatus {
WAITING_FOR_TURN = 'waiting_for_turn',
TAKING_TURN = 'taking_turn',
FINISHED = 'finished',
}
A note about hidden player state
For some games, we might want to hide certain parts of a player's state data from other players. For example, in a card game, we might want to hide a player's hand from their opponents.
To achieve this, in the createGame
, joinGame
, and move
hooks, for each player in the game's players
array we can include a hiddenState
property in the player object.
If this property is present in the game data when the hook returns, it will be removed.
The current player (the player who is starting the game, joining the game, or currently taking their turn) will still be able to see their own hidden state in responses.
Note that all hidden player state will be hidden from event handler parameters, so if you need to access or modify hidden state when handling a realtime event, you will need to re-fetch the game state using the client's fetchState()
method. This method takes a player token as an argument, which ensures that a player's hidden state can only be viewed by that player.