(hopefully) improved reconciliation

This commit is contained in:
ari melody 2024-08-30 12:30:53 +01:00
parent c35c18bbbc
commit 5c936df3f6
Signed by: ari
GPG key ID: CF99829C92678188
2 changed files with 95 additions and 36 deletions

View file

@ -109,23 +109,32 @@ function start() {
break; break;
case "update": { case "update": {
server_tick = data.tick; server_tick = data.tick;
var prediction = predictions[data.tick];
if (prediction) {
Object.keys(predictions).forEach(tick => {
if (tick < data.tick) delete predictions[tick];
});
server_ping = new Date() - prediction.time;
}
Object.keys(data.players).forEach(id => { Object.keys(data.players).forEach(id => {
const player = players[id]; const player = players[id];
const update = data.players[id]; const update = data.players[id];
// this should never be true, but just in case
if (!player) return;
if (id == client_id) { if (id == client_id) {
// clear all predictions prior to this tick
Object.keys(predictions).forEach(tick => {
if (tick < data.tick) delete predictions[tick];
});
var prediction = predictions[data.tick];
if (!prediction) return; if (!prediction) return;
server_ping = new Date() - prediction.time; const predicted = prediction.player;
if (Math.abs(prediction.x - update.x) > 1) // clear all predictions prior to this tick
players[client_id].x = update.x; if (predicted != update) {
if (Math.abs(prediction.y - update.y) > 1) var diff_x = predicted.x - update.x;
players[client_id].y = update.y; var diff_y = predicted.y - update.y;
// apply difference to all predictions
Object.values(predictions).forEach(p => {
p.x -= diff_x;
p.y -= diff_y;
});
// update client state to reflect
player.x -= diff_x;
player.y -= diff_y;
}
delete predictions[data.tick]; delete predictions[data.tick];
} else { } else {
player.x = update.x; player.x = update.x;
@ -135,9 +144,33 @@ function start() {
Object.keys(data.props).forEach(id => { Object.keys(data.props).forEach(id => {
const prop = props[id]; const prop = props[id];
const update = data.props[id]; const update = data.props[id];
if (!prediction) {
prop.x = update.x;
prop.y = update.y;
prop.xv = update.xv;
prop.yv = update.yv;
return;
}
prop.x = update.x; const predicted = prediction.props[id];
prop.y = update.y; if (predicted != update) {
var diff_x = predicted.x - update.x;
var diff_y = predicted.y - update.y;
var diff_xv = predicted.xv - update.xv;
var diff_yv = predicted.yv - update.yv;
// apply difference to all predictions
Object.values(predictions).forEach(p => {
p.x -= diff_x;
p.y -= diff_y;
p.xv -= diff_xv;
p.yv -= diff_yv;
});
// update client state to reflect
prop.x -= diff_x;
prop.y -= diff_y;
prop.xv -= diff_xv;
prop.yv -= diff_yv;
}
}); });
break; break;
} }
@ -211,6 +244,10 @@ function start() {
canvas.addEventListener("keypress", event => { canvas.addEventListener("keypress", event => {
switch (event.key.toLowerCase()) { switch (event.key.toLowerCase()) {
case 'i':
enable_interpolation.update(val => !val);
interpolationToggle.checked = enable_interpolation.get();
break;
case 'p': case 'p':
console.log(predictions); console.log(predictions);
break; break;
@ -288,31 +325,49 @@ function sendChat(msg) {
} }
function update(delta) { function update(delta) {
const prediction = {
time: new Date(),
player: {},
props: {},
};
const clientPlayer = players[client_id]; const clientPlayer = players[client_id];
if (clientPlayer) { if (!clientPlayer) return;
clientPlayer.in_x = input.move_right - input.move_left;
clientPlayer.in_y = input.move_down - input.move_up;
clientPlayer.update(delta); clientPlayer.in_x = input.move_right - input.move_left;
clientPlayer.in_y = input.move_down - input.move_up;
// insert prediction for the next server tick clientPlayer.update(delta);
predictions[ticks] = {
time: new Date(), // insert prediction for the next server tick
x: clientPlayer.x, prediction.player = {
y: clientPlayer.y, x: clientPlayer.x,
y: clientPlayer.y,
};
var t = ticks;
setTimeout(() => {
if (!ws) return;
ws.send(JSON.stringify({
type: "update",
tick: t,
x: input.move_right - input.move_left,
y: input.move_down - input.move_up,
}));
}, fake_ping.get() / 2);
Object.keys(props).forEach(id => {
const prop = props[id];
prop.update(delta, Object.values(players));
prediction.props[id] = {
x: prop.x,
y: prop.y,
xv: prop.xv,
yv: prop.yv,
}; };
});
var t = ticks; predictions[ticks] = prediction;
setTimeout(() => {
if (!ws) return;
ws.send(JSON.stringify({
type: "update",
tick: t,
x: input.move_right - input.move_left,
y: input.move_down - input.move_up,
}));
}, fake_ping.get() / 2);
}
ticks++; ticks++;
} }
@ -337,8 +392,8 @@ function draw() {
const server_state = Object.values(predictions)[0]; const server_state = Object.values(predictions)[0];
ctx.fillStyle = "#208020"; ctx.fillStyle = "#208020";
ctx.beginPath(); ctx.beginPath();
ctx.rect(server_state.x - Player.SIZE / 2, ctx.rect(server_state.player.x - Player.SIZE / 2,
server_state.y - Player.SIZE / 2, server_state.player.y - Player.SIZE / 2,
Player.SIZE, Player.SIZE); Player.SIZE, Player.SIZE);
ctx.stroke(); ctx.stroke();
} }

View file

@ -88,6 +88,8 @@ export function init(http_server) {
name: prop.name, name: prop.name,
x: prop.x, x: prop.x,
y: prop.y, y: prop.y,
xv: prop.xv,
yv: prop.yv,
col: prop.colour, col: prop.colour,
sprite: prop.sprite, sprite: prop.sprite,
} }
@ -193,6 +195,8 @@ function update() {
frame_props[id] = { frame_props[id] = {
x: prop.x, x: prop.x,
y: prop.y, y: prop.y,
xv: prop.xv,
yv: prop.yv,
} }
}); });