mirror of
https://github.com/wassname/GarageServer.IO.git
synced 2026-09-14 11:14:21 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
735f8e7253 | ||
|
|
d05fd58480 | ||
|
|
f28dee8927 | ||
|
|
fbdcfe3da5 | ||
|
|
21d8fb2884 | ||
|
|
e96adda2c2 | ||
|
|
bd341f5f0c | ||
|
|
bb8d5a8b95 | ||
|
|
50a6a1b094 | ||
|
|
2c2a258718 | ||
|
|
4b99023ce1 | ||
|
|
4f8088871a | ||
|
|
ac4bc7be48 | ||
|
|
06ecaacb91 | ||
|
|
34c3d07852 | ||
|
|
7bb18d3c3f | ||
|
|
ff67b5e945 | ||
|
|
3e869e6d9b | ||
|
|
5c01c26530 | ||
|
|
56ca345989 | ||
|
|
191ebe0bef | ||
|
|
b5ae81e936 | ||
|
|
aa8eec72f2 | ||
|
|
15d7670705 | ||
|
|
710f56555f | ||
|
|
f42847f0ac | ||
|
|
7fa638c940 | ||
|
|
790c69305a | ||
|
|
e805c2d991 | ||
|
|
80c5b28d85 | ||
|
|
c670fdf909 | ||
|
|
14a8efd70b | ||
|
|
f7c901ac4b | ||
|
|
878ce0458f | ||
|
|
d3cac4ced2 | ||
|
|
2564f3492f | ||
|
|
0eef87e5a9 | ||
|
|
88b3c80d2b | ||
|
|
32d6a15f19 | ||
|
|
b74ae6820a | ||
|
|
3834200c5a | ||
|
|
779154d861 | ||
|
|
6ebc6ad84c | ||
|
|
a622b12c7e | ||
|
|
6e5d29b058 | ||
|
|
347b399523 | ||
|
|
cd6c7b9d83 | ||
|
|
55d26e51e7 | ||
|
|
486bf65403 | ||
|
|
6afb03a3a5 | ||
|
|
621a4edf17 | ||
|
|
0abca095c5 | ||
|
|
f31ee7e529 |
@@ -1,6 +1,8 @@
|
||||
.idea
|
||||
node_modules
|
||||
.c9revisions
|
||||
.c9
|
||||
.settings
|
||||
lib-cov
|
||||
*.seed
|
||||
*.log
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
# GarageServer.IO
|
||||
A simple, lightweight, HTML multiplayer game server (and client) for Node.js
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
- Authoritative Game Server
|
||||
- Client Side / Input Prediciton
|
||||
- Authoritative Node.js game server and JavaScript client
|
||||
- Client Side / Input Prediction
|
||||
- Client Side Smoothing
|
||||
- Entity Interpolation
|
||||
- Server State History
|
||||
- Server and Client Messaging
|
||||
- Server Reconciliation
|
||||
- Works with any Rendering and/or Physics Engine
|
||||
- Region Broadcasting
|
||||
- Works with any rendering and/or physics engine
|
||||
|
||||
## Install
|
||||
|
||||
### Demo
|
||||
|
||||
A playable [demo](http://garageserverio.jit.su/) of the [example](https://github.com/jbillmann/GarageServer.IO/tree/master/example) using GarageServer.IO.
|
||||
|
||||
### Server
|
||||
|
||||
`$ npm install garageserver.io`
|
||||
@@ -33,4 +40,4 @@ After server install, copy the client from `/node_modules/garageserver.io/client
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](https://github.com/jbillmann/GarageServer.IO/blob/master/LICENSE.md)
|
||||
[MIT License](https://github.com/jbillmann/GarageServer.IO/blob/master/LICENSE.md)
|
||||
+103
-41
@@ -10,7 +10,7 @@ options = {
|
||||
onEvent(callback(data)),
|
||||
onWorldState(callback(state)),
|
||||
onPing(callback(pingDelay)),
|
||||
onUpdatePlayerPrediction(callback(currentState, inputs, deltaTime) : newState),
|
||||
onUpdateClientPredictionReady(callback(playerId, playerCurrentState, entityCurrentStates, inputs, deltaTime)),
|
||||
onInterpolation(callback(previousState, targetState, amount) : newState),
|
||||
onReady(callback),
|
||||
logging: true
|
||||
@@ -20,6 +20,10 @@ api methods
|
||||
addInput(input)
|
||||
getPlayerStates : [, playerState]
|
||||
getEntityStates : [, entityState]
|
||||
updatePlayerState(id, state)
|
||||
addEntity(id, state)
|
||||
updateEntityState(id, state)
|
||||
removeEntity(id)
|
||||
getId() : playerid
|
||||
sendServerEvent(data)
|
||||
*/
|
||||
@@ -84,10 +88,12 @@ var GarageServerIO = (function (socketio) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
function Entity(id, maxUpdateBuffer) {
|
||||
function Entity(id, referrerId, referrerSeq, maxUpdateBuffer) {
|
||||
this.updates = [];
|
||||
this.maxUpdateBuffer = maxUpdateBuffer;
|
||||
this.id = id;
|
||||
this.referrerId = referrerId;
|
||||
this.referrerSeq = referrerSeq;
|
||||
this.state = {};
|
||||
this.inputController = new InputController();
|
||||
}
|
||||
@@ -138,7 +144,7 @@ var GarageServerIO = (function (socketio) {
|
||||
};
|
||||
|
||||
function Player(id, maxUpdateBuffer) {
|
||||
Entity.call(this, id, maxUpdateBuffer);
|
||||
Entity.call(this, id, null, null, maxUpdateBuffer);
|
||||
}
|
||||
Player.prototype = Object.create(Entity.prototype);
|
||||
|
||||
@@ -147,8 +153,9 @@ var GarageServerIO = (function (socketio) {
|
||||
this.maxUpdateBuffer = maxUpdateBuffer;
|
||||
}
|
||||
EntityController.prototype = {
|
||||
add: function (id) {
|
||||
var entity = new Entity(id, this.maxUpdateBuffer);
|
||||
add: function (id, referrerId) {
|
||||
var referrerSeq = this.entities.filter(function (value) { return value.referrerId === referrerId; }).length;
|
||||
var entity = new Entity(id, referrerId, referrerSeq, this.maxUpdateBuffer);
|
||||
this.entities.push(entity);
|
||||
return entity;
|
||||
},
|
||||
@@ -181,13 +188,16 @@ var GarageServerIO = (function (socketio) {
|
||||
|
||||
initializeGarageServer = function (path, options) {
|
||||
_options = options;
|
||||
if(path == null || path.length <= 0) {
|
||||
throw new Error('GarageServer.IO client is missing the server path - please verify the path argument passed to GarageServerIO.initializeGarageServer.');
|
||||
}
|
||||
_socket = _io.connect(path + '/garageserver.io');
|
||||
registerSocketEvents();
|
||||
},
|
||||
|
||||
registerSocketEvents = function () {
|
||||
_socket.on('connect', function () {
|
||||
_stateController.id = _socket.socket.sessionid;
|
||||
_stateController.id = _socket.io.engine.id;
|
||||
if (_options.logging) {
|
||||
console.log('garageserver.io:: socket connect');
|
||||
}
|
||||
@@ -197,7 +207,7 @@ var GarageServerIO = (function (socketio) {
|
||||
}
|
||||
});
|
||||
|
||||
_socket.on('state', function (data) {
|
||||
_socket.on('s', function (data) {
|
||||
if (_options.onWorldState) {
|
||||
_options.onWorldState(data.worldState);
|
||||
}
|
||||
@@ -219,7 +229,7 @@ var GarageServerIO = (function (socketio) {
|
||||
}
|
||||
|
||||
setInterval(function (){
|
||||
_socket.emit('ping', new Date().getTime());
|
||||
_socket.emit('p', new Date().getTime());
|
||||
}, _stateController.pingInterval);
|
||||
});
|
||||
|
||||
@@ -241,11 +251,11 @@ var GarageServerIO = (function (socketio) {
|
||||
}
|
||||
});
|
||||
|
||||
_socket.on('update', function (data) {
|
||||
_socket.on('u', function (data) {
|
||||
update(data);
|
||||
});
|
||||
|
||||
_socket.on('ping', function (data) {
|
||||
_socket.on('p', function (data) {
|
||||
_stateController.pingDelay = new Date().getTime() - data;
|
||||
if (_options.logging) {
|
||||
console.log('garageserver.io:: socket ping delay ' + _stateController.pingDelay);
|
||||
@@ -255,7 +265,7 @@ var GarageServerIO = (function (socketio) {
|
||||
}
|
||||
});
|
||||
|
||||
_socket.on('removePlayer', function (id) {
|
||||
_socket.on('rp', function (id) {
|
||||
removePlayer(id);
|
||||
if (_options.logging) {
|
||||
console.log('garageserver.io:: socket removePlayer ' + id);
|
||||
@@ -265,17 +275,27 @@ var GarageServerIO = (function (socketio) {
|
||||
}
|
||||
});
|
||||
|
||||
_socket.on('removeEntity', function (id) {
|
||||
removeEntity(id);
|
||||
_socket.on('re', function (data) {
|
||||
if (_stateController.clientSidePrediction) {
|
||||
_entityController.entities.forEach(function (entity) {
|
||||
if (entity.referrerId === data.id && entity.referrerSeq === data.seq) {
|
||||
removeEntity(entity.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
removeEntity(data.id);
|
||||
}
|
||||
|
||||
if (_options.logging) {
|
||||
console.log('garageserver.io:: socket removeEntity ' + id);
|
||||
console.log('garageserver.io:: socket removeEntity ' + data.id);
|
||||
}
|
||||
if (_options.onEntityRemove) {
|
||||
_options.onEntityRemove(id);
|
||||
_options.onEntityRemove(data.id);
|
||||
}
|
||||
});
|
||||
|
||||
_socket.on('event', function(data) {
|
||||
_socket.on('e', function(data) {
|
||||
if (_options.logging) {
|
||||
console.log('garageserver.io:: socket event ' + data);
|
||||
}
|
||||
@@ -290,17 +310,24 @@ var GarageServerIO = (function (socketio) {
|
||||
},
|
||||
|
||||
sendServerEvent = function (data) {
|
||||
_socket.emit('event', data);
|
||||
_socket.emit('e', data);
|
||||
},
|
||||
|
||||
addInput = function (clientInput) {
|
||||
_playerController.entities.some(function (player) {
|
||||
if (player.id === _stateController.id) {
|
||||
if (_stateController.clientSidePrediction && _options.onUpdatePlayerPrediction) {
|
||||
if (_stateController.clientSidePrediction && _options.onUpdateClientPredictionReady) {
|
||||
var entityCurrentStates = [];
|
||||
_entityController.entities.forEach(function(entity) {
|
||||
if (entity.referrerId === player.id) {
|
||||
entityCurrentStates.push({ id: entity.id, state: entity.state });
|
||||
}
|
||||
});
|
||||
|
||||
player.inputController.add(clientInput);
|
||||
player.state = _options.onUpdatePlayerPrediction(player.state, [{ input: clientInput }], _stateController.physicsDelta);
|
||||
_options.onUpdateClientPredictionReady(player.id, player.state, entityCurrentStates, [{ input: clientInput }], _stateController.physicsDelta);
|
||||
}
|
||||
_socket.emit('input', [ clientInput, player.inputController.sequenceNumber, _stateController.renderTime ]);
|
||||
_socket.emit('i', [ clientInput, player.inputController.sequenceNumber, _stateController.renderTime ]);
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -336,25 +363,59 @@ var GarageServerIO = (function (socketio) {
|
||||
|
||||
return entityStates;
|
||||
},
|
||||
|
||||
updatePlayerState = function (id, state) {
|
||||
_playerController.entities.some(function(player) {
|
||||
if (player.id === id) {
|
||||
player.state = state;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removePlayer = function (id) {
|
||||
_playerController.remove(id);
|
||||
},
|
||||
|
||||
addEntity = function (id) {
|
||||
_entityController.add(id, _stateController.id);
|
||||
},
|
||||
|
||||
updateEntityState = function (id, state) {
|
||||
_entityController.entities.some(function(entity) {
|
||||
if (entity.id === id) {
|
||||
entity.state = state;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeEntity = function (id) {
|
||||
_entityController.remove(id);
|
||||
},
|
||||
|
||||
update = function (data) {
|
||||
_stateController.setTime(data.time);
|
||||
_stateController.setTime(data.t);
|
||||
|
||||
updatePlayers(data);
|
||||
updateEntities(data);
|
||||
},
|
||||
|
||||
updatePlayers = function (data) {
|
||||
data.playerStates.forEach(function (playerState) {
|
||||
updateEntity(_playerController, playerState, data.time);
|
||||
data.ps.forEach(function (playerState) {
|
||||
var playerFound = false;
|
||||
_playerController.entities.some(function (player) {
|
||||
if (player.id === playerState[0]) {
|
||||
playerFound = true;
|
||||
player.updateState(playerState[1], playerState[2], data.t);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!playerFound) {
|
||||
var newPlayer = _playerController.add(playerState[0]);
|
||||
newPlayer.addUpdate(playerState[1], playerState[2], data.t);
|
||||
}
|
||||
|
||||
if (_options.onPlayerUpdate) {
|
||||
_options.onPlayerUpdate(playerState[1]);
|
||||
@@ -363,8 +424,20 @@ var GarageServerIO = (function (socketio) {
|
||||
},
|
||||
|
||||
updateEntities = function (data) {
|
||||
data.entityStates.forEach(function (entityState) {
|
||||
updateEntity(_entityController, entityState, data.time);
|
||||
data.es.forEach(function (entityState) {
|
||||
var entityFound = false;
|
||||
_entityController.entities.some(function (entity) {
|
||||
if (entity.id === entityState[0] || (entity.referrerId === entityState[3] && entity.referrerSeq === entityState[4])) {
|
||||
entityFound = true;
|
||||
entity.updateState(entityState[1], entityState[2], data.t);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!entityFound) {
|
||||
var newEntity = _entityController.add(entityState[0]);
|
||||
newEntity.addUpdate(entityState[1], entityState[2], data.t);
|
||||
}
|
||||
|
||||
if (_options.onEntityUpdate) {
|
||||
_options.onEntityUpdate(entityState[1]);
|
||||
@@ -372,21 +445,6 @@ var GarageServerIO = (function (socketio) {
|
||||
});
|
||||
},
|
||||
|
||||
updateEntity = function (entityController, entityState, time) {
|
||||
var entityFound = false;
|
||||
entityController.entities.some(function (entity) {
|
||||
if (entity.id === entityState[0]) {
|
||||
entityFound = true;
|
||||
entity.updateState(entityState[1], entityState[2], time);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!entityFound) {
|
||||
var newEntity = entityController.add(entityState[0]);
|
||||
newEntity.addUpdate(entityState[1], entityState[2], time);
|
||||
}
|
||||
},
|
||||
|
||||
processEntityStatesCurrent = function (entityController) {
|
||||
entityController.entities.forEach(function (entity) {
|
||||
if (entity.anyUpdates() && !entity.inputController.any()) {
|
||||
@@ -405,7 +463,7 @@ var GarageServerIO = (function (socketio) {
|
||||
newState = _options.onInterpolation(positions.previous.state, positions.target.state, amount);
|
||||
entity.state = newState = _options.onInterpolation(entity.state, newState, _stateController.smoothingFactor);
|
||||
}
|
||||
else {
|
||||
else if (entity.inputController.sequenceNumber === 1) {
|
||||
entity.state = entity.latestUpdate().state;
|
||||
}
|
||||
}
|
||||
@@ -425,6 +483,10 @@ var GarageServerIO = (function (socketio) {
|
||||
addInput: addInput,
|
||||
getPlayerStates: getPlayerStates,
|
||||
getEntityStates: getEntityStates,
|
||||
updatePlayerState: updatePlayerState,
|
||||
addEntity: addEntity,
|
||||
updateEntityState: updateEntityState,
|
||||
removeEntity: removeEntity,
|
||||
getId: getId,
|
||||
sendServerEvent: sendServerEvent
|
||||
};
|
||||
|
||||
@@ -113,18 +113,22 @@ The current ping in milliseconds.
|
||||
|
||||
---
|
||||
```js
|
||||
options.onUpdatePlayerPrediction(callback(currentState, inputs, deltaTime) : newState)
|
||||
options.onUpdateClientPredictionReady(callback(playerId, playerCurrentState, entityCurrentStates: [, {id, state}], inputs, deltaTime))
|
||||
```
|
||||
**_Returns:_ object literal**
|
||||
|
||||
If using client side prediction, this callback should return the new state, `newState`, based on the current state, inputs to be processed, and the delta time.
|
||||
If using client side prediction, this callback will fire when you should update player and entity states, based on the current states for player and entities, inputs to be processed, and the delta time.
|
||||
|
||||
`callback` **function**
|
||||
Function to be invoked upon event firing.
|
||||
|
||||
`currentState` **object literal**
|
||||
`playerId` **string**
|
||||
The id of the player.
|
||||
|
||||
`playerCurrentState` **object literal**
|
||||
The current state of the player.
|
||||
|
||||
`entityCurrentStates` **array**
|
||||
The list of all entities and their current state that were invoked by the player.
|
||||
|
||||
`inputs` **array**
|
||||
List of all the inputs to be processed.
|
||||
|
||||
@@ -200,6 +204,53 @@ Returns a list of current entity states from the most recent broadcast depending
|
||||
The id of the entity.
|
||||
`state` **object literal**
|
||||
Object containing all properties specific to entity state in your game.
|
||||
|
||||
#### updatePlayerState
|
||||
---
|
||||
```js
|
||||
GarageServerIO.updatePlayerState(id, state)
|
||||
```
|
||||
Notify the GarageServer.IO client of the new player state - this is intended to be used with client side prediction.
|
||||
|
||||
`id` **string**
|
||||
The id of the player.
|
||||
`state` **object literal**
|
||||
Object containing all properties specific to the new player state in your game.
|
||||
|
||||
#### addEntity
|
||||
---
|
||||
```js
|
||||
GarageServerIO.addEntity(id, state)
|
||||
```
|
||||
Notify the GarageServer.IO client of a new entity with an initial state - this is intended to be used with client side prediction.
|
||||
|
||||
`id` **string**
|
||||
The id of the entity.
|
||||
`state` **object literal**
|
||||
Object containing all properties specific to new entity state in your game.
|
||||
|
||||
#### updateEntityState
|
||||
---
|
||||
```js
|
||||
GarageServerIO.updateEntityState(id, state)
|
||||
```
|
||||
Notify the GarageServer.IO client of the new entity state - this is intended to be used with client side prediction.
|
||||
|
||||
`id` **string**
|
||||
The id of the entity.
|
||||
`state` **object literal**
|
||||
Object containing all properties specific to the new entity state in your game.
|
||||
|
||||
#### removeEntity
|
||||
---
|
||||
```js
|
||||
GarageServerIO.removeEntity(id)
|
||||
```
|
||||
Notify the GarageServer.IO client that an entity has been removed from the game - this is intended to be used with client side prediction.
|
||||
|
||||
`id` **string**
|
||||
The id of the entity.
|
||||
|
||||
#### getId
|
||||
---
|
||||
```js
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
+14
-13
@@ -15,11 +15,11 @@ var server = garageServer.createGarageServer(sockets,
|
||||
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.
|
||||
**2.** Start GarageServer.IO instance prior to starting your physics loop. This starts the clock that is used for broadcasting state and storing state history.
|
||||
```js
|
||||
server.start();
|
||||
```
|
||||
**3.** Inside physics loop, process inputs for players, process entites and update their states. Note that state is an object literal effectively offering up any grab bag of properties that are specific to your game's state.
|
||||
**3.** Inside your physics loop, process the inputs for players, process entites and update their states. Note that state is an object literal effectively offering up any grab bag of properties that are specific to your game's state.
|
||||
```js
|
||||
var players = server.getPlayers(),
|
||||
entities = server.getEntities();
|
||||
@@ -48,23 +48,24 @@ entities.forEach(function (entity) {
|
||||
|
||||
**1.** Initialize GarageServer.IO.
|
||||
```js
|
||||
GarageServerIO.initializeGarageServer('http://insertmygameurlhere.com', {
|
||||
GarageServerIO.initializeGarageServer('http://insertmygameserverurlhere.com', {
|
||||
onReady: function () {
|
||||
// Call your game loop
|
||||
},
|
||||
onUpdatePlayerPrediction: function (state, inputs, deltaTime) {
|
||||
onUpdateClientPredictionReady: function (playerId, playerCurrentState, entityCurrentStates, inputs, deltaTime) {
|
||||
var newState = {};
|
||||
if (!player.state.x) {
|
||||
player.state.x = 0;
|
||||
if (!playerCurrentState.x) {
|
||||
playerCurrentState.x = 0;
|
||||
}
|
||||
for (i = 0; i < player.inputs.length; i ++) {
|
||||
if (player.inputs[i].input === 'left') {
|
||||
newState.x = player.state.x - (50 * deltaTime);
|
||||
|
||||
for (i = 0; i < inputs.length; i ++) {
|
||||
if (inputs[i].input === 'left') {
|
||||
newState.x = playerCurrentState.x - (50 * deltaTime);
|
||||
} else if (inputs[i].input === 'right') {
|
||||
newState.x = player.state.x + (50 * deltaTime);
|
||||
newState.x = playerCurrentState.x + (50 * deltaTime);
|
||||
}
|
||||
}
|
||||
return newState;
|
||||
GarageServerIO.updatePlayerState(playerid, newState);
|
||||
},
|
||||
onInterpolation: function (previousState, targetState, amount) {
|
||||
return { x: (previousState.x + amount * (targetState.x - previousState.x)) };
|
||||
@@ -75,11 +76,11 @@ GarageServerIO.initializeGarageServer('http://insertmygameurlhere.com', {
|
||||
}
|
||||
};
|
||||
```
|
||||
**2.** Inside physics loop, capture and send input via GarageServer.IO. Similar to state, input offers up any grab bag of properties specific to your game's input.
|
||||
**2.** Inside your physics loop, capture and send input via GarageServer.IO. Similar to state, input offers up any grab bag of properties specific to your game's input.
|
||||
```js
|
||||
GarageServerIO.addInput(myInput);
|
||||
```
|
||||
**3.** Inside render loop, extract player and entity states - this will retrieve the current states based on your interpolation, prediction and smoothing settings. Players are effectively clients connected to GarageServer.IO whereas entities are determined by players inputs and controlled by the server.
|
||||
**3.** Inside your render loop, extract player and entity states - this will retrieve the current states based on your interpolation, prediction and smoothing settings. Players are effectively clients connected to GarageServer.IO whereas entities are determined by players inputs and controlled by the server.
|
||||
```js
|
||||
var playerStates = GarageServerIO.getPlayerStates(),
|
||||
entityStates = GarageServerIO.getEntityStates();
|
||||
|
||||
@@ -181,7 +181,7 @@ List of all previous states and their execution times up to `options.maxHistoryS
|
||||
GarageServerIO.updatePlayerState(id, state)
|
||||
```
|
||||
|
||||
Notify GargeServer.IO of a new state with an id of the player to be updated. The idea here is that this call is made during each pass of the physics loop on the server.
|
||||
Notify GarageServer.IO of a new state with an id of the player to be updated. The idea here is that this call is made during each pass of the physics loop on the server.
|
||||
|
||||
`id` **string**
|
||||
Id of the player whose state should be updated.
|
||||
@@ -193,7 +193,7 @@ New state of the entity containing all of the properties specific to a player fo
|
||||
GarageServerIO.updateEntityState(id, state)
|
||||
```
|
||||
|
||||
Notify GargeServer.IO of a new state with an id of the entity to be updated. The idea here is that this call is made during each pass of the physics loop on the server.
|
||||
Notify GarageServer.IO of a new state with an id of the entity to be updated. The idea here is that this call is made during each pass of the physics loop on the server.
|
||||
|
||||
`id` **string**
|
||||
Id of the entity whose state should be updated.
|
||||
@@ -202,13 +202,15 @@ New state of the entity containing all of the properties specific to an entity f
|
||||
#### addEntity
|
||||
---
|
||||
```js
|
||||
GarageServerIO.addEntity(id)
|
||||
GarageServerIO.addEntity(id, referrerId)
|
||||
```
|
||||
|
||||
Notify GarageServer.IO that a new entity has been added to the game.
|
||||
|
||||
`id` **string**
|
||||
Id of the entity to be added.
|
||||
`referrerId` **string**
|
||||
Id of the player who invoked/create the entity - optional and used primarily for client side prediction.
|
||||
#### removeEntity
|
||||
---
|
||||
```js
|
||||
@@ -236,4 +238,30 @@ GarageServerIO.sendPlayersEvent(data)
|
||||
```
|
||||
Allows server to broadcast events to all players. Use this to make custom calls to GarageServer.IO clients for your game.
|
||||
`data` **object literal**
|
||||
Object containing all properties specific to the custom event.
|
||||
Object containing all properties specific to the custom event.
|
||||
#### setPlayerRegion
|
||||
---
|
||||
```js
|
||||
GarageServerIO.setPlayerRegion(id, region)
|
||||
```
|
||||
Sets the player region. GarageServer.IO will broadcast the state of players and entities who share the same region. NOTE: This will implicitly enable GarageServer.IO region broadcasting - only those players and entities with regions with be notified of state. Use `clearRegions` to revert region broadcasting.
|
||||
`id` **string**
|
||||
Id of the player to receive event.
|
||||
`region` **string**
|
||||
Name of the region.
|
||||
#### setEntityRegion
|
||||
---
|
||||
```js
|
||||
GarageServerIO.setEntityRegion(id, region)
|
||||
```
|
||||
Sets the entity region. GarageServer.IO will broadcast the state of players and entities who share the same region. NOTE: This will implicitly enable GarageServer.IO region broadcasting - only those players and entities with regions with be notified of state. Use `clearRegions` to revert region broadcasting.
|
||||
`id` **string**
|
||||
Id of the entity to receive event.
|
||||
`region` **string**
|
||||
Name of the region.
|
||||
#### clearRegions
|
||||
---
|
||||
```js
|
||||
GarageServerIO.clearRegions()
|
||||
```
|
||||
Clears all regions associated with players and entities. GarageServer.IO will default back to broadcasting state to all players.
|
||||
@@ -0,0 +1,15 @@
|
||||
# GarageServer.IO Example
|
||||
A sample application using GarageServer.IO
|
||||
|
||||
### Demo
|
||||
|
||||
A playable [demo](http://garageserverio.jit.su/) of this example using GarageServer.IO.
|
||||
|
||||
## Install
|
||||
|
||||
Change the `path` parameter of `GarageServerIO.initializeGarageServer` that is found in file, `/public/javascripts/game.js`, to point to the URL where your Node app runs. I.e. `http://127.0.0.1:3000`. Note that the example app uses a default port of `process.env.PORT || 3000`. This can be changed in `app.js`.
|
||||
|
||||
|
||||
Execute `$ npm install` in the `example/` root directory and `$ node app.js` to run the application.
|
||||
|
||||
NOTE: The example has `options.clientSidePrediction` and `options.interpolation` enabled on the server. If you're running it locally (no ping), you may want to disable these (`false`).
|
||||
+1
-1
@@ -7,7 +7,7 @@ var express = require('express'),
|
||||
app = express();
|
||||
|
||||
app.configure(function () {
|
||||
app.set('port', process.env.PORT || 2121);
|
||||
app.set('port', process.env.PORT || 3000);
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade');
|
||||
app.use(express.favicon());
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ Game.prototype.update = function () {
|
||||
self = this;
|
||||
|
||||
players.forEach(function (player) {
|
||||
var newState = gamePhysics.getNewPlayerState(player.state, player.inputs, self.physicsDelta, self.server);
|
||||
var newState = gamePhysics.getNewPlayerState(player.id, player.state, player.inputs, self.physicsDelta, self.server);
|
||||
self.server.updatePlayerState(player.id, newState);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "garageserver.io.example",
|
||||
"subdomain": "garageserverio",
|
||||
"description": "A sample application using garageserver.io",
|
||||
"author": {
|
||||
"name": "Jeremiah Billmann",
|
||||
"email": "jcbillmann@yahoo.com"
|
||||
},
|
||||
"version": "0.6.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"express": "^3.1.0",
|
||||
"jade": "*",
|
||||
"socket.io": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app.js"
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,15 @@ $(function () {
|
||||
|
||||
window.addEventListener('resize', resizeCanvas, false);
|
||||
|
||||
GarageServerIO.initializeGarageServer('http://garageserver_io.jbillmann.c9.io', {
|
||||
GarageServerIO.initializeGarageServer('', {
|
||||
logging: true,
|
||||
onReady: startGame,
|
||||
onUpdatePlayerPrediction: GamePhysics.getNewPlayerState,
|
||||
onUpdateClientPredictionReady: function (playerId, playerCurrentState, entityCurrentStates, inputs, deltaTime) {
|
||||
entityCurrentStates.forEach(function (entity) {
|
||||
GarageServerIO.updateEntityState(entity.id, GamePhysics.getNewEntityState(entity.state, deltaTime));
|
||||
});
|
||||
GarageServerIO.updatePlayerState(playerId, GamePhysics.getNewPlayerState(playerId, playerCurrentState, inputs, deltaTime, GarageServerIO));
|
||||
},
|
||||
onInterpolation: GamePhysics.getInterpolatedState
|
||||
});
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
+31
-21
@@ -1,37 +1,44 @@
|
||||
(function(exports){
|
||||
|
||||
exports.getNewPlayerState = function (state, inputs, deltaTime, garageServer) {
|
||||
var i = 0, distance = 0;
|
||||
|
||||
exports.getNewPlayerState = function (id, state, inputs, deltaTime, garageServer) {
|
||||
var i = 0, distance = 0, newState = {};
|
||||
|
||||
if (!state.ang && state.ang !== 0) {
|
||||
state.ang = 0;
|
||||
state.x = 0;
|
||||
state.y = 0;
|
||||
state.ship = Math.floor(Math.random() * 9) + 1;
|
||||
state.lastFire = new Date().getTime();
|
||||
newState.ang = 0;
|
||||
newState.x = 0;
|
||||
newState.y = 0;
|
||||
newState.ship = Math.floor(Math.random() * 9) + 1;
|
||||
newState.lastFire = new Date().getTime();
|
||||
}
|
||||
else {
|
||||
newState.ang = state.ang;
|
||||
newState.x = state.x;
|
||||
newState.y = state.y;
|
||||
newState.ship = state.ship;
|
||||
newState.lastFire = state.lastFire;
|
||||
}
|
||||
|
||||
for (i = 0; i < inputs.length; i ++) {
|
||||
if (inputs[i].input === 'left') {
|
||||
state.ang -= (125 * deltaTime);
|
||||
newState.ang -= (125 * deltaTime);
|
||||
} else if (inputs[i].input === 'right') {
|
||||
state.ang += (125 * deltaTime);
|
||||
newState.ang += (125 * deltaTime);
|
||||
} else if (inputs[i].input === 'up') {
|
||||
distance += (125 * deltaTime);
|
||||
} else if (inputs[i].input === 'space') {
|
||||
if (garageServer && (new Date().getTime() - state.lastFire) > 1000) {
|
||||
if ((new Date().getTime() - newState.lastFire) > 1000) {
|
||||
var newId = guid();
|
||||
garageServer.addEntity(newId);
|
||||
garageServer.updateEntityState(newId, { x: state.x, y: state.y, ang: state.ang } );
|
||||
state.lastFire = new Date().getTime();
|
||||
garageServer.addEntity(newId, id);
|
||||
garageServer.updateEntityState(newId, { x: newState.x, y: newState.y, ang: newState.ang } );
|
||||
newState.lastFire = new Date().getTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
var newPoint = getPoint(state.ang, distance, state.x, state.y);
|
||||
state.x = newPoint.x;
|
||||
state.y = newPoint.y;
|
||||
var newPoint = getPoint(newState.ang, distance, newState.x, newState.y);
|
||||
newState.x = newPoint.x;
|
||||
newState.y = newPoint.y;
|
||||
|
||||
return state;
|
||||
return newState;
|
||||
};
|
||||
|
||||
function getPoint(angle, distance, oldX, oldY) {
|
||||
@@ -43,12 +50,15 @@
|
||||
}
|
||||
|
||||
exports.getNewEntityState = function (state, deltaTime) {
|
||||
var newState = {};
|
||||
var distance = 300 * deltaTime;
|
||||
var newPoint = getPoint(state.ang, distance, state.x, state.y);
|
||||
state.x = newPoint.x;
|
||||
state.y = newPoint.y;
|
||||
|
||||
newState.ang = state.ang;
|
||||
newState.x = newPoint.x;
|
||||
newState.y = newPoint.y;
|
||||
|
||||
return state;
|
||||
return newState;
|
||||
};
|
||||
|
||||
exports.getInterpolatedState = function (previousState, targetState, amount) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
doctype 5
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
title= title
|
||||
|
||||
@@ -8,7 +8,7 @@ function EntityController (maxHistorySecondBuffer) {
|
||||
}
|
||||
|
||||
EntityController.prototype = {
|
||||
add: function (id) {
|
||||
add: function (id, referrerId) {
|
||||
var newEntity, entityFound = false;
|
||||
|
||||
this.entities.some(function (entity) {
|
||||
@@ -20,7 +20,8 @@ EntityController.prototype = {
|
||||
});
|
||||
|
||||
if (!entityFound) {
|
||||
newEntity = new entity(id, this.maxHistorySecondBuffer);
|
||||
var referrerSeq = this.entities.filter(function (value) { return value.referrerId === referrerId; }).length;
|
||||
newEntity = new entity(id, referrerId, referrerSeq, this.maxHistorySecondBuffer);
|
||||
this.entities.push(newEntity);
|
||||
}
|
||||
return newEntity;
|
||||
@@ -32,5 +33,10 @@ EntityController.prototype = {
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
clearRegions: function () {
|
||||
for (var i = 0; i < this.entities.length; i ++) {
|
||||
this.entities[i].setRegion('');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -9,11 +9,11 @@ function PlayerController (maxHistorySecondBuffer) {
|
||||
|
||||
PlayerController.prototype = Object.create(entityController.prototype);
|
||||
|
||||
PlayerController.prototype.add = function (client) {
|
||||
PlayerController.prototype.add = function (socket) {
|
||||
var newPlayer, playerFound = false;
|
||||
|
||||
this.entities.some(function (player) {
|
||||
if (player.client.id === client.id) {
|
||||
if (player.id === socket.id) {
|
||||
newPlayer = player;
|
||||
playerFound = true;
|
||||
return true;
|
||||
@@ -21,7 +21,7 @@ PlayerController.prototype.add = function (client) {
|
||||
});
|
||||
|
||||
if (!playerFound) {
|
||||
newPlayer = new player(client, this.maxHistorySecondBuffer);
|
||||
newPlayer = new player(socket, this.maxHistorySecondBuffer);
|
||||
this.entities.push(newPlayer);
|
||||
}
|
||||
return newPlayer;
|
||||
@@ -29,7 +29,7 @@ PlayerController.prototype.add = function (client) {
|
||||
|
||||
PlayerController.prototype.addInput = function (id, input, sequence, time) {
|
||||
this.entities.some(function (player) {
|
||||
if (player.client.id === id) {
|
||||
if (player.id === id) {
|
||||
player.inputs.push({ input: input, seq: sequence, time: time });
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@ var history = require('./history');
|
||||
|
||||
exports = module.exports = Entity;
|
||||
|
||||
function Entity (id, maxHistorySecondBuffer) {
|
||||
function Entity (id, referrerId, referrerSeq, maxHistorySecondBuffer) {
|
||||
this.state = {};
|
||||
this.sequence = 1;
|
||||
this.id = id;
|
||||
this.referrerId = referrerId;
|
||||
this.referrerSeq = referrerSeq;
|
||||
this.maxHistorySecondBuffer = maxHistorySecondBuffer;
|
||||
this.stateHistory = [];
|
||||
this.region = '';
|
||||
}
|
||||
|
||||
Entity.prototype = {
|
||||
@@ -31,5 +34,8 @@ Entity.prototype = {
|
||||
if (spliceTo > 0) {
|
||||
this.stateHistory.splice(0, spliceTo);
|
||||
}
|
||||
},
|
||||
setRegion: function (region) {
|
||||
this.region = region;
|
||||
}
|
||||
};
|
||||
+10
-3
@@ -2,16 +2,23 @@ var entity = require('./entity');
|
||||
|
||||
exports = module.exports = Player;
|
||||
|
||||
function Player (client, maxHistorySecondBuffer) {
|
||||
entity.call(this, client.id, maxHistorySecondBuffer);
|
||||
this.client = client;
|
||||
function Player (socket, maxHistorySecondBuffer) {
|
||||
entity.call(this, socket.id, null, null, maxHistorySecondBuffer);
|
||||
this.socket = socket;
|
||||
this.inputs = [];
|
||||
}
|
||||
|
||||
Player.prototype = Object.create(entity.prototype);
|
||||
|
||||
Player.prototype.setRegion = function (region) {
|
||||
this.socket.join(region);
|
||||
this.socket.leave(this.region);
|
||||
this.region = region;
|
||||
};
|
||||
|
||||
Player.prototype.addState = function (state, executionTime) {
|
||||
this.addHistory(state, executionTime);
|
||||
this.state = state;
|
||||
this.sequence += this.inputs.length;
|
||||
this.inputs = [];
|
||||
};
|
||||
+38
-15
@@ -36,9 +36,14 @@ function GarageServer(socketio, options) {
|
||||
|
||||
this.socketPath = namespace;
|
||||
this.io = socketio;
|
||||
this.clientSidePrediction = options.clientSidePrediction;
|
||||
this.registerSocketEvents(options);
|
||||
this.game = new garageServerGame(options, function (state) {
|
||||
socketio.of(namespace).emit('update' ,state);
|
||||
this.game = new garageServerGame(options, function (state, region) {
|
||||
if (!region) {
|
||||
socketio.of(namespace).emit('u' ,state);
|
||||
} else {
|
||||
socketio.of(namespace).in(region).emit('u' ,state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,7 +54,7 @@ GarageServer.prototype.registerSocketEvents = function (options) {
|
||||
if (options.logging) {
|
||||
console.log('garageserver.io:: socket ' + socket.id + ' connection');
|
||||
}
|
||||
socket.emit('state', {
|
||||
socket.emit('s', {
|
||||
physicsDelta: (options.physicsInterval ? options.physicsInterval : 15) / 1000,
|
||||
smoothingFactor: options.smoothingFactor ? options.smoothingFactor : 0.3,
|
||||
interpolation: options.interpolation ? options.interpolation : false,
|
||||
@@ -68,26 +73,26 @@ GarageServer.prototype.registerSocketEvents = function (options) {
|
||||
self.onPlayerDisconnect(socket, options);
|
||||
});
|
||||
|
||||
socket.on('input', function (data) {
|
||||
socket.on('i', function (data) {
|
||||
if (options.logging) {
|
||||
console.log('garageserver.io:: socket input ' + socket.id + ' ' + data[0] + ' ' + data[1]);
|
||||
}
|
||||
self.onPlayerInput(socket, data, options);
|
||||
});
|
||||
|
||||
socket.on('ping', function (data) {
|
||||
socket.on('p', function (data) {
|
||||
if (options.logging) {
|
||||
console.log('garageserver.io:: socket ping ' + data);
|
||||
}
|
||||
self.onPing(socket, data, options);
|
||||
});
|
||||
|
||||
socket.on('event', function (data) {
|
||||
socket.on('e', function (data) {
|
||||
if (options.logging) {
|
||||
console.log('garageserver.io:: event ' + data);
|
||||
}
|
||||
if (options.OnEvent) {
|
||||
options.OnEvent(data);
|
||||
if (options.onEvent) {
|
||||
options.onEvent(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -102,7 +107,7 @@ GarageServer.prototype.onPlayerConnect = function (socket, options) {
|
||||
|
||||
GarageServer.prototype.onPlayerDisconnect = function (socket, options) {
|
||||
this.game.removePlayer(socket.id);
|
||||
socket.broadcast.emit('removePlayer', socket.id);
|
||||
socket.broadcast.emit('rp', socket.id);
|
||||
if (options.onPlayerDisconnect) {
|
||||
options.onPlayerDisconnect(socket);
|
||||
}
|
||||
@@ -116,7 +121,7 @@ GarageServer.prototype.onPlayerInput = function (socket, input, options) {
|
||||
};
|
||||
|
||||
GarageServer.prototype.onPing = function (socket, data, options) {
|
||||
socket.emit('ping', data);
|
||||
socket.emit('p', data);
|
||||
if (options.onPing) {
|
||||
options.onPing(socket, data);
|
||||
}
|
||||
@@ -146,12 +151,18 @@ GarageServer.prototype.updateEntityState = function (id, state) {
|
||||
this.game.updateEntityState(id, state);
|
||||
};
|
||||
|
||||
GarageServer.prototype.addEntity = function (id) {
|
||||
this.game.addEntity(id);
|
||||
GarageServer.prototype.addEntity = function (id, referrerId) {
|
||||
this.game.addEntity(id, referrerId);
|
||||
};
|
||||
|
||||
GarageServer.prototype.removeEntity = function (id) {
|
||||
this.io.of(this.socketPath).emit('removeEntity', id);
|
||||
if (this.clientSidePrediction) {
|
||||
var entity = this.game.getEntity(id);
|
||||
this.io.of(this.socketPath).emit('re', { id: entity.referrerId, seq: entity.referrerSeq });
|
||||
}
|
||||
else {
|
||||
this.io.of(this.socketPath).emit('re', { id: id });
|
||||
}
|
||||
this.game.removeEntity(id);
|
||||
};
|
||||
|
||||
@@ -160,9 +171,21 @@ GarageServer.prototype.sendPlayerEvent = function (id, data) {
|
||||
};
|
||||
|
||||
GarageServer.prototype.sendPlayersEvent = function (data) {
|
||||
this.io.of(this.socketPath).emit('event', data);
|
||||
this.io.of(this.socketPath).emit('e', data);
|
||||
};
|
||||
|
||||
GarageServer.prototype.setPlayerRegion = function (id, region) {
|
||||
this.game.setPlayerRegion(id, region);
|
||||
};
|
||||
|
||||
GarageServer.prototype.setEntityRegion = function (id, region) {
|
||||
this.game.setEntityRegion(id, region);
|
||||
};
|
||||
|
||||
GarageServer.prototype.clearRegions = function () {
|
||||
this.game.clearRegions();
|
||||
};
|
||||
|
||||
exports.createGarageServer = function (io, options) {
|
||||
return new GarageServer(io, options);
|
||||
};
|
||||
};
|
||||
|
||||
+92
-25
@@ -11,6 +11,7 @@ function GarageServerGame(options, broadcastCallback) {
|
||||
this.playerController = new playerController(this.options.maxHistorySecondBuffer ? this.options.maxHistorySecondBuffer : 1000);
|
||||
this.entityController = new entityController(this.options.maxHistorySecondBuffer ? this.options.maxHistorySecondBuffer : 1000);
|
||||
this.broadcastCallback = broadcastCallback;
|
||||
this.regions = [];
|
||||
}
|
||||
|
||||
GarageServerGame.prototype.start = function () {
|
||||
@@ -25,19 +26,50 @@ GarageServerGame.prototype.stop = function () {
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.broadcastState = function () {
|
||||
var currentTime = new Date().getTime() - this.startTime,
|
||||
state = { time: currentTime, playerStates: [], entityStates: [] };
|
||||
var i = 0, currentTime = new Date().getTime() - this.startTime,
|
||||
state = { t: currentTime, ps: [], es: [] };
|
||||
|
||||
state.playerStates = this.getState(this.playerController);
|
||||
state.entityStates = this.getState(this.entityController);
|
||||
|
||||
this.broadcastCallback(state);
|
||||
if (this.regions.length > 0) {
|
||||
for (i = 0; i < this.regions.length; i ++) {
|
||||
state.ps = this.getStateByRegion(this.playerController, this.regions[i]);
|
||||
state.es = this.getStateByRegion(this.entityController, this.regions[i]);
|
||||
this.broadcastCallback(state, this.regions[i]);
|
||||
}
|
||||
} else {
|
||||
state.ps = this.getState(this.playerController);
|
||||
state.es = this.getState(this.entityController);
|
||||
this.broadcastCallback(state);
|
||||
}
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.getState = function (controller) {
|
||||
var states = [];
|
||||
var states = [],
|
||||
clientSidePrediction = this.options.clientSidePrediction;
|
||||
|
||||
controller.entities.forEach(function (entity) {
|
||||
states.push([ entity.id, entity.state, entity.sequence ]);
|
||||
if (clientSidePrediction && entity.referrerId != null) {
|
||||
states.push([ entity.id, entity.state, entity.sequence, entity.referrerId, entity.referrerSeq ]);
|
||||
}
|
||||
else {
|
||||
states.push([ entity.id, entity.state, entity.sequence ]);
|
||||
}
|
||||
});
|
||||
return states;
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.getStateByRegion = function (controller, region) {
|
||||
var states = [],
|
||||
clientSidePrediction = this.options.clientSidePrediction;
|
||||
|
||||
controller.entities.forEach(function (entity) {
|
||||
if (entity.region === region) {
|
||||
if (clientSidePrediction && entity.referrerId != null) {
|
||||
states.push([ entity.id, entity.state, entity.sequence, entity.referrerId, entity.referrerSeq ]);
|
||||
}
|
||||
else {
|
||||
states.push([ entity.id, entity.state, entity.sequence ]);
|
||||
}
|
||||
}
|
||||
});
|
||||
return states;
|
||||
};
|
||||
@@ -58,18 +90,6 @@ GarageServerGame.prototype.getEntities = function () {
|
||||
return list;
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.getPlayer = function (id) {
|
||||
var playerFound;
|
||||
|
||||
this.playerController.entities.some(function (player) {
|
||||
if (player.id === id) {
|
||||
playerFound = player;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return playerFound;
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.updatePlayerState = function (id, state) {
|
||||
this.updateState(this.playerController, id, state);
|
||||
};
|
||||
@@ -89,18 +109,27 @@ GarageServerGame.prototype.updateState = function (controller, id, state) {
|
||||
});
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.addPlayer = function (client) {
|
||||
this.playerController.add(client);
|
||||
GarageServerGame.prototype.addPlayer = function (socket) {
|
||||
this.playerController.add(socket);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.removePlayer = function (id) {
|
||||
this.playerController.remove(id);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.addEntity = function (id) {
|
||||
this.entityController.add(id);
|
||||
GarageServerGame.prototype.addEntity = function (id, referrerId) {
|
||||
this.entityController.add(id, referrerId);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.getEntity = function (id) {
|
||||
for (var idx = 0; idx < this.entityController.entities.length; idx ++) {
|
||||
if (this.entityController.entities[idx].id === id) {
|
||||
return this.entityController.entities[idx];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GarageServerGame.prototype.removeEntity = function (id) {
|
||||
this.entityController.remove(id);
|
||||
};
|
||||
@@ -112,8 +141,46 @@ GarageServerGame.prototype.addPlayerInput = function (id, input, sequence, time)
|
||||
GarageServerGame.prototype.sendPlayerEvent = function (id, data) {
|
||||
this.playerController.entities.some(function (player) {
|
||||
if (player.id === id) {
|
||||
player.client.emit('event', data);
|
||||
player.socket.emit('e', data);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.setPlayerRegion = function (id, region) {
|
||||
this.setRegion(this.playerController, id, region);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.setEntityRegion = function (id, region) {
|
||||
this.setRegion(this.entityController, id, region);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.setRegion = function (controller, id, region) {
|
||||
var self = this;
|
||||
controller.entities.some(function (entity) {
|
||||
if (entity.id === id) {
|
||||
entity.setRegion(region);
|
||||
self.updateRegions(region);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.updateRegions = function (region) {
|
||||
var regionFound = false;
|
||||
|
||||
this.regions.forEach(function (item) {
|
||||
if (item === region) {
|
||||
regionFound = true;
|
||||
}
|
||||
});
|
||||
if (!regionFound) {
|
||||
this.regions.push(region);
|
||||
}
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.clearRegions = function () {
|
||||
this.regions = [];
|
||||
this.entityController.clearRegions();
|
||||
this.playerController.clearRegions();
|
||||
};
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
"name": "Jeremiah Billmann",
|
||||
"email": "jcbillmann@yahoo.com"
|
||||
},
|
||||
"version": "0.5.2",
|
||||
"version": "0.6.0",
|
||||
"homepage": "https://github.com/jbillmann/GarageServer.IO",
|
||||
"license" : "MIT",
|
||||
"keywords": [
|
||||
|
||||
Reference in New Issue
Block a user