mirror of
https://github.com/wassname/GarageServer.IO.git
synced 2026-07-27 11:18:04 +08:00
Fixed client prediction and prepped for interpolation
This commit is contained in:
+72
-88
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user