mirror of
https://github.com/wassname/GarageServer.IO.git
synced 2026-09-09 11:14:19 +08:00
NPM Publish prep
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
var entity = require('../entities/entity');
|
||||
|
||||
exports = module.exports = EntityController;
|
||||
|
||||
function EntityController (maxHistorySecondBuffer) {
|
||||
this.entities = [];
|
||||
this.maxHistorySecondBuffer = maxHistorySecondBuffer;
|
||||
}
|
||||
|
||||
EntityController.prototype = {
|
||||
add: function (id) {
|
||||
var newEntity, entityFound = false;
|
||||
|
||||
this.entities.some(function (entity) {
|
||||
if (entity.id === id) {
|
||||
newEntity = entity;
|
||||
entityFound = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!entityFound) {
|
||||
newEntity = new entity(id, this.maxHistorySecondBuffer);
|
||||
this.entities.push(newEntity);
|
||||
}
|
||||
return newEntity;
|
||||
},
|
||||
remove: function (id) {
|
||||
for (var i = 0; i < this.entities.length; i ++) {
|
||||
if (this.entities[i].id === id) {
|
||||
this.entities.splice(i, 1)[0];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
var entityController = require('./entitycontroller'),
|
||||
player = require('../entities/player');
|
||||
|
||||
exports = module.exports = PlayerController;
|
||||
|
||||
function PlayerController (maxHistorySecondBuffer) {
|
||||
entityController.call(this, maxHistorySecondBuffer);
|
||||
}
|
||||
|
||||
PlayerController.prototype = Object.create(entityController.prototype);
|
||||
|
||||
PlayerController.prototype.add = function (client) {
|
||||
var newPlayer, playerFound = false;
|
||||
|
||||
this.entities.some(function (player) {
|
||||
if (player.client.id === client.id) {
|
||||
newPlayer = player;
|
||||
playerFound = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!playerFound) {
|
||||
newPlayer = new player(client, this.maxHistorySecondBuffer);
|
||||
this.entities.push(newPlayer);
|
||||
}
|
||||
return newPlayer;
|
||||
};
|
||||
|
||||
PlayerController.prototype.addInput = function (id, input, sequence, time) {
|
||||
this.entities.some(function (player) {
|
||||
if (player.client.id === id) {
|
||||
player.inputs.push({ input: input, seq: sequence, time: time });
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
var history = require('./history');
|
||||
|
||||
exports = module.exports = Entity;
|
||||
|
||||
function Entity (id, maxHistorySecondBuffer) {
|
||||
this.state = {};
|
||||
this.sequence = 1;
|
||||
this.id = id;
|
||||
this.maxHistorySecondBuffer = maxHistorySecondBuffer;
|
||||
this.stateHistory = [];
|
||||
}
|
||||
|
||||
Entity.prototype = {
|
||||
addState: function (state, executionTime) {
|
||||
this.addHistory(state, executionTime);
|
||||
this.state = state;
|
||||
this.sequence += 1;
|
||||
},
|
||||
addHistory: function (state, executionTime) {
|
||||
var minTime, spliceTo = 0, newHistory = new history(state, executionTime);
|
||||
|
||||
this.stateHistory.push(newHistory);
|
||||
minTime = this.stateHistory[this.stateHistory.length - 1].executionTime - this.maxHistorySecondBuffer;
|
||||
|
||||
for (var i = 0; i < this.stateHistory.length; i ++) {
|
||||
if (this.stateHistory[i].executionTime > minTime) {
|
||||
spliceTo = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (spliceTo > 0) {
|
||||
this.stateHistory.splice(0, spliceTo);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
exports = module.exports = History;
|
||||
|
||||
function History (state, executionTime) {
|
||||
this.state = state;
|
||||
this.executionTime = executionTime;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
var entity = require('./entity');
|
||||
|
||||
exports = module.exports = Player;
|
||||
|
||||
function Player (client, maxHistorySecondBuffer) {
|
||||
entity.call(this, client.id, maxHistorySecondBuffer);
|
||||
this.client = client;
|
||||
this.inputs = [];
|
||||
}
|
||||
|
||||
Player.prototype = Object.create(entity.prototype);
|
||||
|
||||
Player.prototype.addState = function (state, executionTime) {
|
||||
this.addHistory(state, executionTime);
|
||||
this.sequence += this.inputs.length;
|
||||
this.inputs = [];
|
||||
};
|
||||
@@ -0,0 +1,165 @@
|
||||
var garageServerGame = require('./garageservergame');
|
||||
|
||||
/*
|
||||
options = {
|
||||
stateInterval: 45,
|
||||
logging: true,
|
||||
clientSidePrediction: true,
|
||||
interpolation: true,
|
||||
interpolationDelay: 100,
|
||||
smoothingFactor: 0.3,
|
||||
pingInterval: 2000,
|
||||
maxUpdateBuffer: 120,
|
||||
maxHistorySecondBuffer: 1000,
|
||||
worldState: {},
|
||||
onPlayerConnect(callback(socket)),
|
||||
onPlayerInput(callback(socket, input)),
|
||||
onPlayerDisconnect(callback(socket)),
|
||||
onPing(callback(socket, data)),
|
||||
onEvent(callback(data))
|
||||
}
|
||||
api methods
|
||||
createGarageServer(io, options)
|
||||
start()
|
||||
stop()
|
||||
getPlayers() : [,{ id, state, [,inputs], [,{ states, executionTimes }] }]
|
||||
getEntities() :[,{ id, state, [,{ state, executionTime }] }]
|
||||
updatePlayerState(id, state)
|
||||
updateEntityState(id, state)
|
||||
addEntity(id)
|
||||
removeEntity(id)
|
||||
sendPlayerEvent(id, data)
|
||||
sendPlayersEvent(data)
|
||||
*/
|
||||
function GarageServer(socketio, options) {
|
||||
var namespace = '/garageserver.io';
|
||||
|
||||
this.socketPath = namespace;
|
||||
this.io = socketio;
|
||||
this.registerSocketEvents(options);
|
||||
this.game = new garageServerGame(options, function (state) {
|
||||
socketio.of(namespace).emit('update' ,state);
|
||||
});
|
||||
}
|
||||
|
||||
GarageServer.prototype.registerSocketEvents = function (options) {
|
||||
var self = this;
|
||||
|
||||
self.io.of(self.socketPath).on('connection', function (socket) {
|
||||
if (options.logging) {
|
||||
console.log('garageserver.io:: socket ' + socket.id + ' connection');
|
||||
}
|
||||
socket.emit('state', {
|
||||
physicsDelta: (options.physicsInterval ? options.physicsInterval : 15) / 1000,
|
||||
smoothingFactor: options.smoothingFactor ? options.smoothingFactor : 0.3,
|
||||
interpolation: options.interpolation ? options.interpolation : false,
|
||||
interpolationDelay: options.interpolationDelay ? options.interpolationDelay : 100,
|
||||
pingInterval: options.pingInterval ? options.pingInterval : 2000,
|
||||
clientSidePrediction: options.clientSidePrediction ? options.clientSidePrediction : false,
|
||||
maxUpdateBuffer: options.maxUpdateBuffer ? options.maxUpdateBuffer : 120,
|
||||
worldState: options.worldState ? options.worldState : {}
|
||||
});
|
||||
self.onPlayerConnect(socket, options);
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
if (options.logging) {
|
||||
console.log('garageserver.io:: socket ' + socket.id + ' disconnect');
|
||||
}
|
||||
self.onPlayerDisconnect(socket, options);
|
||||
});
|
||||
|
||||
socket.on('input', 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) {
|
||||
if (options.logging) {
|
||||
console.log('garageserver.io:: socket ping ' + data);
|
||||
}
|
||||
self.onPing(socket, data, options);
|
||||
});
|
||||
|
||||
socket.on('event', function (data) {
|
||||
if (options.OnEvent) {
|
||||
options.OnEvent(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
GarageServer.prototype.onPlayerConnect = function (socket, options) {
|
||||
this.game.addPlayer(socket);
|
||||
if (options.onPlayerConnect) {
|
||||
options.onPlayerConnect(socket);
|
||||
}
|
||||
};
|
||||
|
||||
GarageServer.prototype.onPlayerDisconnect = function (socket, options) {
|
||||
this.game.removePlayer(socket.id);
|
||||
socket.broadcast.emit('removePlayer', socket.id);
|
||||
if (options.onPlayerDisconnect) {
|
||||
options.onPlayerDisconnect(socket);
|
||||
}
|
||||
};
|
||||
|
||||
GarageServer.prototype.onPlayerInput = function (socket, input, options) {
|
||||
this.game.addPlayerInput(socket.id, input[0], input[1], input[2]);
|
||||
if (options.onPlayerInput) {
|
||||
options.onPlayerInput(socket, input);
|
||||
}
|
||||
};
|
||||
|
||||
GarageServer.prototype.onPing = function (socket, data, options) {
|
||||
socket.emit('ping', data);
|
||||
if (options.onPing) {
|
||||
options.onPing(socket, data);
|
||||
}
|
||||
};
|
||||
|
||||
GarageServer.prototype.start = function () {
|
||||
this.game.start();
|
||||
};
|
||||
|
||||
GarageServer.prototype.stop = function () {
|
||||
this.game.stop();
|
||||
};
|
||||
|
||||
GarageServer.prototype.getPlayers = function () {
|
||||
return this.game.getPlayers();
|
||||
};
|
||||
|
||||
GarageServer.prototype.getEntities = function () {
|
||||
return this.game.getEntities();
|
||||
};
|
||||
|
||||
GarageServer.prototype.updatePlayerState = function (id, state) {
|
||||
this.game.updatePlayerState(id, state);
|
||||
};
|
||||
|
||||
GarageServer.prototype.updateEntityState = function (id, state) {
|
||||
this.game.updateEntityState(id, state);
|
||||
};
|
||||
|
||||
GarageServer.prototype.addEntity = function (id) {
|
||||
this.game.addEntity(id);
|
||||
};
|
||||
|
||||
GarageServer.prototype.removeEntity = function (id) {
|
||||
this.io.of(this.socketPath).emit('removeEntity', id);
|
||||
this.game.removeEntity(id);
|
||||
};
|
||||
|
||||
GarageServer.prototype.sendPlayerEvent = function (id, data) {
|
||||
this.game.sendPlayerEvent(id, data);
|
||||
};
|
||||
|
||||
GarageServer.prototype.sendPlayersEvent = function (data) {
|
||||
this.io.of(this.socketPath).emit('event', data);
|
||||
};
|
||||
|
||||
exports.createGarageServer = function (io, options) {
|
||||
return new GarageServer(io, options);
|
||||
};
|
||||
@@ -0,0 +1,119 @@
|
||||
var playerController = require('./controllers/playercontroller'),
|
||||
entityController = require('./controllers/entitycontroller');
|
||||
|
||||
exports = module.exports = GarageServerGame;
|
||||
|
||||
function GarageServerGame(options, broadcastCallback) {
|
||||
this.options = options;
|
||||
this.startTime = 0;
|
||||
this.stateInterval = options.stateInterval ? options.stateInterval : 45;
|
||||
this.stateIntervalId = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
GarageServerGame.prototype.start = function () {
|
||||
var self = this;
|
||||
|
||||
this.startTime = new Date().getTime();
|
||||
this.stateIntervalId = setInterval(function () { self.broadcastState(); }, this.stateInterval);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.stop = function () {
|
||||
clearInterval(this.stateIntervalId);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.broadcastState = function () {
|
||||
var currentTime = new Date().getTime() - this.startTime,
|
||||
state = { time: currentTime, playerStates: [], entityStates: [] };
|
||||
|
||||
state.playerStates = this.getState(this.playerController);
|
||||
state.entityStates = this.getState(this.entityController);
|
||||
|
||||
this.broadcastCallback(state);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.getState = function (controller) {
|
||||
var states = [];
|
||||
controller.entities.forEach(function (entity) {
|
||||
states.push([ entity.id, entity.state, entity.sequence ]);
|
||||
});
|
||||
return states;
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.getPlayers = function () {
|
||||
var list = [];
|
||||
this.playerController.entities.forEach(function (player) {
|
||||
list.push({ id: player.id, state: player.state, inputs: player.inputs, stateHistory: player.stateHistory });
|
||||
});
|
||||
return list;
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.getEntities = function () {
|
||||
var list = [];
|
||||
this.entityController.entities.forEach(function (entity) {
|
||||
list.push({ id: entity.id, state: entity.state, stateHistory: entity.stateHistory });
|
||||
});
|
||||
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);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.updateEntityState = function (id, state) {
|
||||
this.updateState(this.entityController, id, state);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.updateState = function (controller, id, state) {
|
||||
var currentTime = new Date().getTime() - this.startTime;
|
||||
|
||||
controller.entities.some(function (entity) {
|
||||
if (entity.id === id) {
|
||||
entity.addState(state, currentTime);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.addPlayer = function (client) {
|
||||
this.playerController.add(client);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.removePlayer = function (id) {
|
||||
this.playerController.remove(id);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.addEntity = function (id) {
|
||||
this.entityController.add(id);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.removeEntity = function (id) {
|
||||
this.entityController.remove(id);
|
||||
};
|
||||
|
||||
GarageServerGame.prototype.addPlayerInput = function (id, input, sequence, time) {
|
||||
this.playerController.addInput(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);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user