diff --git a/client/garageserver.io.js b/client/garageserver.io.js index 2ae7381..225ac46 100644 --- a/client/garageserver.io.js +++ b/client/garageserver.io.js @@ -6,9 +6,9 @@ options = { onPing: function (data), logging: true, clientSidePrediction: true, - onUpdatePhysics: function (state, inputs), + onUpdatePlayerPhysics: function (state, inputs), interpolation: true, - interpolationDelay: 100, + onInterpolation: function(statePrevious, stateTarget, amount) pingInterval: 2000 } */ @@ -17,14 +17,12 @@ window.GarageServerIO = (function (window, socketio) { var io = socketio, socket = null, - sequenceNumber = 0, - processedSequenceNumber = 0, + sequenceNumber = 1, players = [], inputs = [], - updates = [], + currentState = {}, options = null, pingDelay = 100, - serverOffset, // TODO: DONE CALLBACK connectToGarageServer = function (path, opts) { @@ -36,16 +34,15 @@ window.GarageServerIO = (function (window, socketio) { registerSocketEvents = function () { socket.on('update', function(data) { - updatePlayerInput(data); + updateState(data); if (options.logging) { - console.log('garageserver.io:: socket update ' + data); + //console.log('garageserver.io:: socket state update'); } }); socket.on('ping', function(data) { - pingDelay = new Date().getTime() - data.pingTime; - serverOffset = new Date().getTime() - data.serverTime + pingDelay; + pingDelay = new Date().getTime() - data; if (options.logging) { - console.log('garageserver.io:: socket ping delay ' + pingDelay + ', server offset ' + serverOffset); + console.log('garageserver.io:: socket ping delay ' + pingDelay); } }); socket.on('removePlayer', function(id) { @@ -65,70 +62,75 @@ window.GarageServerIO = (function (window, socketio) { socket.emit('ping', new Date().getTime()); }, interval); }, + + updateState = function (data) { + updatePlayerState(data); + updateEntityState(data); + }, - updatePlayerInput = function (data) { - var playerFound = false, - updateFound = false, + updatePlayerState = function (data) { + var updateFound = false, + playerFound = false, playerIdx = 0, - updateIdx = 0; + updateIdx = 0, + stateIdx = 0, + playerState; - if (socket.socket.sessionid === data.id) { - for (updateIdx = 0; updateIdx < updates.length; updateIdx ++) { - if (updates[updateIdx].seq === data.seq) { - updates[updateIdx].state = data.state; - updateFound = true; - break; - } - } - if (!updateFound) { - updates.push(data); - } - if (options.clientSidePrediction) { - for (updateIdx = 0; updateIdx < updates.length; updateIdx ++) { - if (updates[updateIdx].seq == processedSequenceNumber) { - updates.splice(0, updateIdx); - } - } - for (updateIdx = 0; updateIdx < inputs.length; updateIdx ++) { - if (inputs[updateIdx].seq == processedSequenceNumber) { - inputs.splice(0, updateIdx + 1); - } - } - if (updates.length > 0 && inputs.length > 0) { - options.onUpdatePhysics(updates[0].state, inputs); - } - } - } else { - for (playerIdx = 0; playerIdx < players.length; playerIdx ++) { - if (players[playerIdx].id === data.id) { - playerFound = true; - for (updateIdx = 0; updateIdx < players[playerIdx].updates.length; updateIdx ++) { - if (players[playerIdx].updates[updateIdx].seq === data.seq) { - players[playerIdx].updates[updateIdx].state = data.state; - updateFound = true; + for(stateIdx = 0; stateIdx < data.playerStates.length; stateIdx ++) { + playerFound = false; + updateFound = false; + playerState = data.playerStates[stateIdx]; + + if (socket.socket.sessionid === playerState.id) { + currentState = playerState.state; + + if (options.clientSidePrediction) { + for (updateIdx = 0; updateIdx < inputs.length; updateIdx ++) { + if (inputs[updateIdx].seq == playerState.seq) { + inputs.splice(0, updateIdx + 1); break; } } - if (!updateFound) { - players[playerIdx].updates.push({ state: data.state, seq: data.seq, timestamp: data.timestamp }); + if (inputs.length > 0) { + currentState = options.onUpdatePlayerPhysics(currentState, inputs); } - break; + } + } else { + for (playerIdx = 0; playerIdx < players.length; playerIdx ++) { + if (players[playerIdx].id === playerState.id) { + playerFound = true; + for (updateIdx = 0; updateIdx < players[playerIdx].updates.length; updateIdx ++) { + if (players[playerIdx].updates[updateIdx].seq === playerState.seq) { + players[playerIdx].updates[updateIdx].state = playerState.state; + updateFound = true; + break; + } + } + if (!updateFound) { + players[playerIdx].updates.push({ state: playerState.state, seq: playerState.seq, time: playerState.time }); + } + break; + } + } + + if (!playerFound) { + var player = { + id: playerState.id, + updates: [] + }; + player.updates.push({ state: playerState.state, seq: playerState.seq, time: playerState.time }); + players.push(player); } } - if (!playerFound) { - var player = { - id: data.id, - updates: [] - }; - player.updates.push({ state: data.state, seq: data.seq }); - players.push(player); + if (options.onPlayerUpdate) { + options.onPlayerUpdate(playerState); } } - - if (options.onPlayerUpdate) { - options.onPlayerUpdate(data); - } + }, + + updateEntityState = function (data) { + }, removePlayer = function (id) { @@ -145,26 +147,14 @@ window.GarageServerIO = (function (window, socketio) { }, addPlayerInput = function (clientInput) { - var currentState = {}, - newState = {}, - inputsToProcess = []; - - if (options.clientSidePrediction) { - for (var i = 0; i < updates.length; i ++) { - if (updates[i].seq == processedSequenceNumber) { - currentState = updates[i].state; - } - } - } + var inputsToProcess = []; sequenceNumber += 1; inputs.push({ input: clientInput, seq: sequenceNumber }); - if (options.clientSidePrediction && options.onUpdatePhysics) { + if (options.clientSidePrediction && options.onUpdatePlayerPhysics) { inputsToProcess.push({ input: clientInput }); - newState = options.onUpdatePhysics(currentState, inputsToProcess); - processedSequenceNumber += 1; - updates.push({ state: newState, seq: processedSequenceNumber }); + currentState = options.onUpdatePlayerPhysics(currentState, inputsToProcess); } sendPlayerInput(clientInput); }, @@ -178,22 +168,16 @@ window.GarageServerIO = (function (window, socketio) { for (var playerIdx = 0; playerIdx < players.length; playerIdx ++) { if (players[playerIdx].updates.length > 0) { if (options.interpolation) { - for (var updateIdx = players[playerIdx].updates.length - 1; updateIdx >= 0; updateIdx --) { - if (players[playerIdx].updates[updateIdx].timestamp > (new Date().getTime() - serverOffset)) { - stateCallback(players[playerIdx].updates[updateIdx].state); - break; - } - } + + + } else { maxUpdate = players[playerIdx].updates.length - 1; stateCallback(players[playerIdx].updates[maxUpdate].state); } } } - if (updates.length > 0) { - maxUpdate = updates.length - 1; - stateCallback(updates[maxUpdate].state); - } + stateCallback(currentState); }; return { diff --git a/example/app.js b/example/app.js index eecdf44..59870dc 100644 --- a/example/app.js +++ b/example/app.js @@ -45,7 +45,7 @@ sockets.set('log level', 0); garageServer.createGarageServer(sockets,{ logging: true, - onUpdatePhysics: function (state, inputs) { + onUpdatePlayerPhysics: function (state, inputs) { var i = 0; if (!state.x && !state.y) { state.x = 0; diff --git a/example/public/javascripts/game.js b/example/public/javascripts/game.js index ee765b1..ea4e981 100644 --- a/example/public/javascripts/game.js +++ b/example/public/javascripts/game.js @@ -3,7 +3,7 @@ $(function () { logging: true, clientSidePrediction: true, //interpolation: true, - onUpdatePhysics: function (state, inputs) { + onUpdatePlayerPhysics: function (state, inputs) { var i = 0; if (!state.x && !state.y) { state.x = 0; diff --git a/lib/server/garageserver.io.js b/lib/server/garageserver.io.js index d52c3d3..63c215f 100644 --- a/lib/server/garageserver.io.js +++ b/lib/server/garageserver.io.js @@ -2,14 +2,14 @@ var garageServerGame = require('./garageservergame'); /* options = { - onUpdatePhysics: function (state, inputs), physicsInterval: 15, - playersInterval: 45, + stateInterval: 45, logging: true, onPlayerConnect: function (socket), onPlayerInput: function (socket, input), onPlayerDisconnect: function (socket), onPing: function (socket, data), + onUpdatePlayerPhysics: function (state, inputs), } */ @@ -74,7 +74,7 @@ GarageServer.prototype.onPlayerInput = function (socket, input, options) { }; GarageServer.prototype.onPing = function (socket, data, options) { - socket.emit('ping', { 'pingTime': data, 'serverTime': new Date().getTime() }); + socket.emit('ping', data); if (options.onPing) { options.onPing(socket, data); } diff --git a/lib/server/garageservergame.js b/lib/server/garageservergame.js index 245053b..4d47879 100644 --- a/lib/server/garageservergame.js +++ b/lib/server/garageservergame.js @@ -2,27 +2,42 @@ function GarageServerGame(options) { var self = this; this.players = []; + this.entities = []; this.options = options; + this.startTime = new Date().getTime(); this.physicsIntervalId = setInterval(function () { self.updatePhysics(options); }, options.physicsInterval ? options.physicsInterval : 15); - this.playersIntervalId = setInterval(function () { self.updatePlayers(options); }, options.playersInterval ? options.playersInterval : 45); + this.stateIntervalId = setInterval(function () { self.updateState(options); }, options.stateInterval ? options.stateInterval : 45); } +GarageServerGame.prototype.updateState = function (options) { + this.updatePlayers(options); + this.updateEntities(options); +}; + GarageServerGame.prototype.updatePlayers = function (options) { - var currentTime = new Date().getTime(); - for (var i = 0; i < this.players.length; i ++) { - if(this.players[i].inputs.length > 0) { - this.players[i].client.emit('update', { id: this.players[i].client.id, state: this.players[i].state, seq: this.players[i].sequence, timestamp: currentTime }); - this.players[i].client.broadcast.emit('update', { id: this.players[i].client.id, state: this.players[i].state, seq: this.players[i].sequence, timestamp: currentTime }); - } + var currentTime = new Date().getTime() - this.startTime, + state = { time: currentTime, playerStates: [] }, + i = 0; + + for (i = 0; i < this.players.length; i ++) { + state.playerStates.push({ id: this.players[i].client.id, state: this.players[i].state, seq: this.players[i].sequence }); } + + for (i = 0; i < this.players.length; i ++) { + this.players[i].client.emit('update', state); + } +}; + +GarageServerGame.prototype.updateEntities = function (options) { + }; GarageServerGame.prototype.updatePhysics = function (options) { for (var i = 0; i < this.players.length; i ++) { if (this.players[i].inputs.length > 0) { - if (this.options.onUpdatePhysics) { - this.players[i].state = this.options.onUpdatePhysics(this.players[i].state, this.players[i].inputs); + if (this.options.onUpdatePlayerPhysics) { + this.players[i].state = this.options.onUpdatePlayerPhysics(this.players[i].state, this.players[i].inputs); } this.players[i].sequence += this.players[i].inputs.length; this.players[i].inputs = []; @@ -37,9 +52,10 @@ GarageServerGame.prototype.addPlayer = function (client) { } } + // Set player state callback var player = { client: client, - state: {}, + state: {x: 0, y: 0}, inputs: [], sequence: 1 };