mirror of
https://github.com/wassname/GarageServer.IO.git
synced 2026-07-14 01:00:07 +08:00
205 lines
7.5 KiB
JavaScript
205 lines
7.5 KiB
JavaScript
/*
|
|
options = {
|
|
onConnect: function()
|
|
onPlayerUpdate: function (data),
|
|
onPlayerDisconnect: function (id),
|
|
onPing: function (data),
|
|
logging: true,
|
|
clientSidePrediction: true,
|
|
onUpdatePhysics: function (state, inputs),
|
|
interpolation: true,
|
|
interpolationDelay: 100,
|
|
pingInterval: 2000
|
|
}
|
|
*/
|
|
|
|
window.GarageServerIO = (function (window, socketio) {
|
|
|
|
var io = socketio,
|
|
socket = null,
|
|
sequenceNumber = 0,
|
|
processedSequenceNumber = 0,
|
|
players = [],
|
|
inputs = [],
|
|
updates = [],
|
|
options = null,
|
|
pingDelay = 100,
|
|
serverOffset,
|
|
|
|
// TODO: DONE CALLBACK
|
|
connectToGarageServer = function (path, opts) {
|
|
socket = io.connect(path + '/garageserver.io');
|
|
options = opts;
|
|
registerSocketEvents();
|
|
registerPinger();
|
|
},
|
|
|
|
registerSocketEvents = function () {
|
|
socket.on('update', function(data) {
|
|
updatePlayerInput(data);
|
|
if (options.logging) {
|
|
console.log('garageserver.io:: socket update ' + data);
|
|
}
|
|
});
|
|
socket.on('ping', function(data) {
|
|
pingDelay = new Date().getTime() - data.pingTime;
|
|
serverOffset = new Date().getTime() - data.serverTime + pingDelay;
|
|
if (options.logging) {
|
|
console.log('garageserver.io:: socket ping delay ' + pingDelay + ', server offset ' + serverOffset);
|
|
}
|
|
});
|
|
socket.on('removePlayer', function(id) {
|
|
removePlayer(id);
|
|
if (options.logging) {
|
|
console.log('garageserver.io:: socket removePlayer ' + id);
|
|
}
|
|
});
|
|
},
|
|
|
|
registerPinger = function () {
|
|
var interval = 2000;
|
|
if (options.pingInterval) {
|
|
interval = options.pingInterval;
|
|
}
|
|
setInterval(function (){
|
|
socket.emit('ping', new Date().getTime());
|
|
}, interval);
|
|
},
|
|
|
|
updatePlayerInput = function (data) {
|
|
var playerFound = false,
|
|
updateFound = false,
|
|
playerIdx = 0,
|
|
updateIdx = 0;
|
|
|
|
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;
|
|
break;
|
|
}
|
|
}
|
|
if (!updateFound) {
|
|
players[playerIdx].updates.push({ state: data.state, seq: data.seq, timestamp: data.timestamp });
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
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(data);
|
|
}
|
|
},
|
|
|
|
removePlayer = function (id) {
|
|
for (var i = 0; i < players.length; i ++) {
|
|
if (players[i].id === id) {
|
|
players.splice(i, 1)[0];
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (options.onPlayerDisconnect) {
|
|
options.onPlayerDisconnect(id);
|
|
}
|
|
},
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
sequenceNumber += 1;
|
|
inputs.push({ input: clientInput, seq: sequenceNumber });
|
|
|
|
if (options.clientSidePrediction && options.onUpdatePhysics) {
|
|
inputsToProcess.push({ input: clientInput });
|
|
newState = options.onUpdatePhysics(currentState, inputsToProcess);
|
|
processedSequenceNumber += 1;
|
|
updates.push({ state: newState, seq: processedSequenceNumber });
|
|
}
|
|
sendPlayerInput(clientInput);
|
|
},
|
|
|
|
sendPlayerInput = function (clientInput) {
|
|
socket.emit('input', { input: clientInput, seq: sequenceNumber });
|
|
},
|
|
|
|
getPlayerStates = function (stateCallback) {
|
|
var maxUpdate = 0;
|
|
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);
|
|
}
|
|
};
|
|
|
|
return {
|
|
connectToGarageServer: connectToGarageServer,
|
|
addPlayerInput: addPlayerInput,
|
|
getPlayerStates: getPlayerStates
|
|
};
|
|
|
|
}) (window, io); |