🔧 Simple API for building games using WebSockets.
MIT License
🔧 Simple API for building games using WebSockets.
$ npm install websocket-game-lobby
The following example starts a WebSocket server and a single page HTTP server using http-single-serve.
Without any additional code, this server can be connected to, and then a game can be created
, joined
, started
, left
, and ended
. This can be done using either the websocket-game-lobby-client package or the React hook websocket-game-lobby-client-hooks package.
const http = require('http-single-serve');
const { WebSocketGameLobbyServer } = require('websocket-game-lobby');
const gameLobby = new WebSocketGameLobbyServer({
server: http({
port: 5000
})
});
Custom events can be added by using event listeners on either the server or the datastore.
For example, a custom event can be added to the server to set a property when a game is created. In the following example, a custom property with the key of color
will be added with a value of purple
when a game is created.
const http = require('http-single-serve');
const { WebSocketGameLobbyServer } = require('websocket-game-lobby');
const gameLobby = new WebSocketGameLobbyServer({
server: http({
port: 5000
})
});
gameLobby.addEventListener(
'create',
async ({ gameId, playerId }, datastore) => {
await datastore.editGame(gameId, async game => {
game.custom.color = 'purple';
return game;
});
}
);
You can also create custom events, in addition to the built-in events, that can be called in the same way from the client.
const http = require('http-single-serve');
const { WebSocketGameLobbyServer } = require('websocket-game-lobby');
const gameLobby = new WebSocketGameLobbyServer({
server: http({
port: 5000
})
});
gameLobby.addEventListener(
'card-played',
async ({ gameId, playerId, turnId, playedCard }, datastore) => {
await datastore.editTurn(gameId, turnId, async turn => {
if (!turn.custom.playedCards) {
turn.custom.playedCards = [];
}
turn.custom.playedCards.push({
playerId,
playedCard
});
return turn;
});
}
);
You can even set custom events directly on the datastore. In this example, we are manually creating a datastore and attaching an event. When a game is created, a custom property with the key of createdDate
will be added with a value of Date.now()
.
const http = require('http-single-serve');
const {
WebSocketGameLobbyServer,
EphemeralDataStore
} = require('websocket-game-lobby');
const datastore = new EphemeralDataStore();
datastore.addEventListener('createGame', async (game, datastore) => {
game.custom.createdDate = Date.now();
return game;
});
const gameLobby = new WebSocketGameLobbyServer({
server: http({
port: 5000
}),
datastore
});
Event types for use with the WebSocketGameLobbyServer are as follows:
Name | Description |
---|---|
create |
Event fired when a game is created. |
join |
Event fired when a game is joined. |
leave |
Event fired when a game is left. |
start |
Event fired when a game is started. |
end |
Event fired when a game is ended. |
Each event uses the same callback signature of ({gameId, playerId, ...rest}, datastore)
. The rest
refers to all other key-value pairs recieved from client, including custom ones.
Add a new event callback method for an existing or new event type.
const createHandler = async ({ gameId, playerId }, datastore) => {};
gameLobby.addEventListener('create', createHandler);
Remove an existing event callback method. Callback must be a reference to the original added method.
const createHandler = async ({ gameId, playerId }, datastore) => {};
gameLobby.removeEventListener('create', createHandler);
Remove all existing event callback methods.
gameLobby.removeAllEventListeners();
There are two kinds of DataStore objects you can use; the default is EphemeralDataStore
, which stores data in a temporary JavaScript object, and the other is PostgresDataStore
.
const { EphemeralDataStore } = require('websocket-game-lobby');
const datastore = new EphemeralDataStore();
To connect to your database, add the following into an .env
file in your project and setup the ENV variables on your server.
WARNING: Make sure an add
.env
to your.gitignore
file to prevent committing passwords to your git repository.
PGHOST=localhost
PGPORT=5432
PGUSER=postgres
PGPASSWORD=password
PGDATABASE=travis_ci_test
Then install dotenv and import it into your project. This will parse the variables in your .env
file and expose them to your project for reading via the process.env
object.
require('dotenv').config();
const { PostgresDataStore } = require('websocket-game-lobby');
const datastore = new PostgresDataStore();
Event types for use with the DataStore are as follows:
Name | Description |
---|---|
createGame |
Event fired when a game is created. |
leaveGame |
Event fired when a game is left. |
startGame |
Event fired when a game is started. |
createPlayer |
Event fired when a player is created. |
createSpectator |
Event fired when a spectator is created. |
createTurn |
Event fired when a turn is created. |
endCurrentTurn |
Event fired when a turn is ended. |
Each event uses the same callback signature of (data, datastore)
. The data
refers to the type of object is being modified, as referenced in the event name.
Add a new event callback method for an existing or new event type.
const gameCreatedHandler = async (game, datastore) => {};
datastore.addEventListener('gameCreated', gameCreatedHandler);
Remove an existing event callback method. Callback must be a reference to the original added method.
const gameCreatedHandler = async (game, datastore) => {};
datastore.removeEventListener('gameCreated', gameCreatedHandler);
Remove all existing event callback methods.
datastore.removeAllEventListeners();
Find a game using a UUID.
const game = await datastore.findGame('8ca2ad81-093d-4352-8b96-780899e09d69');
Find a game using a game code.
const game = await datastore.findGameWithCode('ABCD');
Edit game data.
const editedGame = await datastore.editGame(gameId, async game => {
return game;
});
Find player in a game using a UUID.
const player = await datastore.findPlayer(gameId, playerId);
Edit player data.
const editedPlayer = await datastore.editPlayer(
gameId,
playerId,
async player => {
return player;
}
);
Find spectator in a game using a UUID.
const spectator = await datastore.findSpectator(gameId, spectatorId);
Edit spectator data.
const editedSpectator = await datastore.editSpectator(
gameId,
spectatorId,
async spectator => {
return spectator;
}
);
Find turn in a game using a UUID.
const turn = await datastore.findTurn(gameId, turnId);
Find the current turn in a game using a UUID.
const turn = await datastore.findCurrentTurn(gameId);
Edit turn data.
const editedTurn = await datastore.editTurn(gameId, turnId, async turn => {
return turn;
});
Edit current turn data.
const editedTurn = await datastore.editCurrentTurn(gameId, async turn => {
return turn;
});
Ends current turn and then creates a new turn in a game.
await datastore.endCurrentTurn(gameId);
Package | Description | Version |
---|---|---|
websocket-game-lobby-client | Simple API for building games using WebSockets. | |
websocket-game-lobby-client-hooks | React hooks for use with websocket-game-lobby
|
|
websocket-game-lobby-template | Template built with websocket-game-lobby
|