Created
November 17, 2020 22:20
-
-
Save entropylost/2ca32367dc648830c848b46ca1e51ef4 to your computer and use it in GitHub Desktop.
Short thing for deterministic lockstep.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const playerId = 123; // Unique ID. | |
let tick = 0; | |
let minTick = 0; | |
const state = [/* INITIAL STATE*/]; | |
const inputs = [[]]; | |
(function run() { | |
tick++; | |
// currentInputs is an array of all inputs. Each input is of an "input" type. | |
// Inputs is an array of inputs, ordered by tick, with each input containing a .playerId which is the | |
// ID of the player, and a .input which is the "input" type that currentInputs has. | |
const currentInputs = getAllInputs(); | |
inputs[tick] = currentInputs.map((input) => { playerId, input }); | |
// Send all inputs to all other players. | |
send({ playerId, inputs: currentInputs, tick }); | |
// Reset the minTick to the current tick, to keep track of where the simulation should restart from. | |
minTick = tick; | |
// Poll all messages sent. This will call receive for each sender. | |
poll(); | |
// Resimulate. For best performance this would be split between multiple different render ticks | |
// To prevent the game from freezing whenever a packet arrives 10 seconds late. | |
for (let i = minTick; i < tick; i++) { | |
state[i] = simulate(state[i - 1], inputs[i]); | |
} | |
// Simulate the next state. | |
state[tick] = simulate(state[tick - 1], inputs[tick]); | |
requestAnimationFrame(run); | |
})(); | |
// Second argument is just an arbitrary object sent from the other client. | |
// Inputs is the type of an array of a "input". | |
function receive({ playerId, inputs: senderInputs, tick: senderTick }) { | |
if (tick < senderTick) { | |
throw new Error('Sender is sending message in future.'); | |
} | |
inputs[tick].push(...inputs.map((input) => { playerId, input })); | |
minTick = Math.min(minTick, senderTick); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment