2013-07-30 19:31:23 -04:00
2013-07-27 16:31:42 -04:00
2013-07-26 15:37:18 -04:00
2013-07-26 09:54:50 -04:00
2013-05-05 23:50:15 -04:00
2013-06-08 16:43:37 -04:00
2013-05-05 23:00:43 -04:00
2013-07-30 19:31:23 -04:00

GarageServer.IO

A simple, lightweight, HTML multiplayer game server (and client) for Node.js

Features

  • Authoritative Game Server
  • Client Side / Input Prediciton
  • Client Side Smooting
  • Entity Interpolation
  • Server State History
  • Server and Client Messaging

Quick Start

Create a quick game whereby players simply move squares along the x-axis. I know, it's boring, but it keeps things simple and to the point. For a more thorough demonstration of how GarageServer.IO works, look at the example included in the source code.

Server

1. Create instance of GarageServer.IO - pass in a Socket.IO instance and GarageServer.IO options.

var garageServer = require('garageserver.io'),

var server = garageServer.createGarageServer(sockets, 
    {
        interpolation: true,
        clientSidePrediction: true,
        worldState: { width: '400px', height: '400px'; }
    });

2. Start GarageServer.IO instance prior to starting physics loop. This starts the clock that is used for broadcasting state and storing state history.

server.start();

3. Inside physics loop, process inputs for players, process entites and update states. Note that state is an object literal effectively offering up any grab bag of properties that pertain to your game's state.

var players = server.getPlayers(),
    entities = server.getEntities();

players.forEach(function (player) {
    var newState = {};
    if (!player.state.x) {
       player.state.x = 0;
    }
    for (i = 0; i < player.inputs.length; i ++) {
        if (player.inputs[i].input === 'left') {
            newState.x = player.state.x - (50 * deltaTime);
        } else if (inputs[i].input === 'right') {
            newState.x = player.state.x + (50 * deltaTime);
        }
    }
    server.updatePlayerState(player.id, newState);
});
entities.forEach(function (entity) {
    // Calculate new state from entity.state and send GarageServer.IO new state
    server.updateEntityState(entity.id, newState);
});

Client

1. Initialize GarageServer.IO.

GarageServerIO.initializeGarageServer('http://insertmygameurlhere.com', {
    onReady: function () {
        // Call your game loop
    },
    onUpdatePlayerPrediction: function (state, inputs, deltaTime) {
        var newState = {};
        if (!player.state.x) {
        player.state.x = 0;
        }
        for (i = 0; i < player.inputs.length; i ++) {
            if (player.inputs[i].input === 'left') {
                newState.x = player.state.x - (50 * deltaTime);
            } else if (inputs[i].input === 'right') {
                newState.x = player.state.x + (50 * deltaTime);
            }
        }
        return newState;
    },
    onInterpolation: function (previousState, targetState, amount) {
        return { x: (previousState.x + amount * (targetState.x - previousState.x)) };
    },
    onWorldState: function (state) {
        document.getElementById('gameCanvas').style.width = state.width;
        document.getElementById('gameCanvas').style.height = state.height;
    }
};

2. Inside physics loop, capture and send input via GarageServer.IO.

GarageServerIO.addInput(myInput);

3. Inside render loop, extract player and entity states.

var playerStates = GarageServerIO.getPlayerStates(),
    entityStates = GarageServerIO.getEntityStates();  
    playerStates.forEach(function (player) {
        ctxCanvas.fillRect(player.state.x, 0, 5, 5);
    });
    entityStates.forEach(function (entity) {
        ctxCanvas.fillRect(entity.state.x, 0, 5, 5);
    });

API

Client

initializeGarageServer


GarageServerIO.initializeGarageServer(path, options)

Establish connection to GarageServer.IO on the server via Socket.IO and register events.
path string
The URL that points to where GarageServer.IO is running at on the server.
options object literal
Configure the different options, events, callbacks that you would like to consume on the client.

Client Options


options.onPlayerConnect(callback)  

Once the client has made a connection to the server, this event will fire.
callback function
Function to be invoked upon event firing.


options.onPlayerDisconnect(callback)  

If client disconnects from the server, this event will fire.
callback function
Function to be invoked upon event firing.


options.onPlayerReconnect(callback)  

If client disconnects and reconnects to the server, this event will fire.
callback function
Function to be invoked upon event firing.


options.onPlayerUpdate(callback(state))  

Event fired each time state has been received to the client for a player.
callback function
Function to be invoked upon event firing.
state object literal
Object containing all of the properties pertaining to a player for your game - x, y, z, time, etc., whatever you want to add to it.


options.onEntityUpdate(callback(state))  

Event fired each time state has been received to the client for an entity.
callback function
Function to be invoked upon event firing.

state object literal
Object containing all of the properties pertaining to an entity for your game - x, y, z, time, etc., whatever you want to add to it.


options.onPlayerRemove(callback(id))  

Event fired when a player has been removed from GarageServer.IO.
callback function
Function to be invoked upon event firing.

id string
Id of the player who has been removed from GarageServer.IO.


options.onEntityRemove(callback(id))  

Event fired when an entity has been removed from GarageServer.IO.
callback function
Function to be invoked upon event firing.

id string
Id of the entity who has been removed from GarageServer.IO.


options.onEvent(callback(data))  

Event fired for custom event calling.
callback function
Function to be invoked upon event firing.

data object literal
Object containing all of the properties pertaining to a custom event for your game - a, b, c, etc., whatever you want to add to it.


options.onWorldState(callback(state))  

Event fired once world state has been received to the client from the server.
callback function
Function to be invoked upon event firing.

state object literal
Object containing all of the properties pertaining to world state for your game - f, u, n, etc., whatever you want to add to it.


options.onPing(callback(pingDelay))  

Event fired upon receiving ping delay on the client - determined by the 'pingInterval' option from the server.
callback function
Function to be invoked upon event firing.

pingDelay number
The current ping in milliseconds.


options.onUpdatePlayerPrediction(callback(state, inputs, deltaTime) : newState)  

If using client side prediction, this callback should return the new state based on the current state, inputs to be processed, and the delta time.
Returns: object literal

callback function
Function to be invoked upon event firing.

state object literal
The current state of the player.

inputs array
List of all the inputs to be processed.

deltaTime number
The amount, in milliseconds, between physics processing.


options.onInterpolation(callback(previousState, targetState, amount) : newState)  

If using interpolation, this callback should return the new state, based on the previous state, target state, and percent between.
Returns: object literal

callback function
Function to be invoked upon event firing.

previousState object literal
Object containing all of the properties pertaining to a player for your game - x, y, z, time, etc., whatever you want to add to it.

targetState object literal
Object containing all of the properties pertaining to a player for your game - x, y, z, time, etc., whatever you want to add to it.

amount number
The "rough" percentage between frames to be used in conjuction with interpolation - client side smoothing is considered during the calculation of this number.


options.onReady(callback)  

Event fired once client has succesfully connected to the server and received the world state.
callback function
Function to be invoked upon event firing.


options.logging: true  

This will enabling console logging of all the events occuring within the GarageServer.IO client.
logging boolean

addInput


GarageServerIO.addInput(input)

Notify the server of client inputs. These will be used to determine state from the physics processing.
input object literal
This can be anything as it pertains to your game - 1, 'left', 'right', etc., whatever you want to make it.

getPlayerStates


GarageServerIO.getPlayerStates() : [, {id, state}]

Returns a list of current player states from the most recent broadcast depending on interpolation settings.
Returns: array

id string
The id of the player.
state object literal
Object containing all properties pertaining to an entity state in your game.

getEntityStates


GarageServerIO.getEntityStates() : [, {id, state}]

Returns a list of current entity states from the most recent broadcast depending on interpolation settings.
Returns: array

id string
The id of the entity.
state object literal
Object containing all properties pertaining to an entity state in your game.

getId


GarageServerIO.getId() : playerid

Gets the id of the client's player.
Returns: string

playerid string
Id of the client's player.

sendServerEvent


GarageServerIO.sendServerEvent(data)

Send a custom event to the server.
data object literal
Object containing all properties pertaining to the custom event.

Server

createGarageServer


require('garageserver.io').createGarageServer(io, options) : GarageServerIO

io Socket.IO instance

options object literal

Server Options


options.stateInterval

number


options.logging

boolean


options.clientSidePrediction

boolean


options.interpolation

boolean


options.interpolationDelay

number


options.smoothingFactor

number


options.pingInterval

number


options.maxUpdateBuffer

number


options.maxHistorySecondBuffer

number


options.worldState

object literal


options.onPlayerConnect(callback(socket))

callback function

socket Socket


options.onPlayerInput(callback(socket, input))

callback function

socket Socket

input object literal


options.onPlayerDisconnect(callback(socket))

callback function

socket Socket


options.onPing(callback(socket, data))

callback function

socket Socket

data object literal


options.onEvent(callback(data))

callback function

data object literal

start


GarageServerIO.start()

stop


GarageServerIO.stop()

getPlayers


GarageServerIO.getPlayers() : [, {id, state, [, inputs], [, {states, executionTimes}]}]

Returns: array

id string

state object literal

inputs array of object literals

stateHistory array of object literals

getEntities


GarageServerIO.getEntities() : [,{id, state, [, {state, executionTime }]}]

Returns: array

id string

state object literal

stateHistory array of object literals

updatePlayerState


GarageServerIO.updatePlayerState(id, state)

id string

state object literal

updateEntityState


GarageServerIO.updateEntityState(id, state)

id string

state object literal

addEntity


GarageServerIO.addEntity(id)

id string

removeEntity


GarageServerIO.removeEntity(id)

id string

sendPlayerEvent


GarageServerIO.sendPlayerEvent(id, data)

id string

data object literal

sendPlayersEvent


GarageServerIO.sendPlayersEvent(data)

data object literal

License

MIT License

S
Description
A simple, lightweight, HTML multiplayer game server (and client) for Node.js
Readme 593 KiB
Languages
JavaScript 97.7%
Pug 1.5%
CSS 0.8%