Allow rewinding a replay without desyncing it

This commit is contained in:
Eevee (Evelyn Woods) 2020-12-11 21:14:19 -07:00
parent 410af788fc
commit 0f0c7437a6
2 changed files with 27 additions and 20 deletions

View File

@ -25,13 +25,20 @@ class CC2Demo {
this.blob_seed = this.bytes[2]; this.blob_seed = this.bytes[2];
} }
*[Symbol.iterator]() { decompress() {
let duration = 0;
let l = this.bytes.length; let l = this.bytes.length;
if (l % 2 === 0) { if (l % 2 === 0) {
l--; l--;
} }
let input = new Set; for (let p = 3; p < l; p += 2) {
duration += this.bytes[p];
}
let inputs = new Uint8Array(duration);
let i = 0;
let t = 0; let t = 0;
let input = 0;
for (let p = 3; p < l; p += 2) { for (let p = 3; p < l; p += 2) {
// The first byte measures how long the /previous/ input remains // The first byte measures how long the /previous/ input remains
// valid, so yield that first. Note that this is measured in 60Hz // valid, so yield that first. Note that this is measured in 60Hz
@ -44,24 +51,31 @@ class CC2Demo {
t += delay; t += delay;
while (t >= 3) { while (t >= 3) {
t -= 3; t -= 3;
yield input; inputs[i] = input;
i++;
} }
let input_mask = this.bytes[p + 1]; input = this.bytes[p + 1];
let is_player_2 = ((input_mask & 0x80) !== 0); let is_player_2 = ((input & 0x80) !== 0);
// TODO handle player 2 // TODO handle player 2
if (is_player_2) if (is_player_2)
continue; continue;
}
for (let [action, bit] of Object.entries(CC2_DEMO_INPUT_MASK)) { // TODO maybe turn this into, like, a type, or something
if ((input_mask & bit) === 0) { return {
input.delete(action); inputs: inputs,
length: duration,
get(t) {
if (t >= this.inputs.length) {
return new Set;
} }
else { else {
input.add(action); let input = this.inputs[t];
} return new Set(Object.entries(CC2_DEMO_INPUT_MASK).filter(([action, bit]) => input & bit).map(([action, bit]) => action));
}
} }
},
};
} }
} }
@ -1826,7 +1840,6 @@ const MAX_SIMULTANEOUS_REQUESTS = 5;
resolve(game); resolve(game);
} }
console.log(game);
return promise; return promise;
} }

View File

@ -898,7 +898,7 @@ class Player extends PrimaryView {
play_demo() { play_demo() {
this.restart_level(); this.restart_level();
let demo = this.level.stored_level.demo; let demo = this.level.stored_level.demo;
this.demo_faucet = demo[Symbol.iterator](); this.demo_faucet = demo.decompress();
this.level.force_floor_direction = demo.initial_force_floor_direction; this.level.force_floor_direction = demo.initial_force_floor_direction;
this.level._blob_modifier = demo.blob_seed; this.level._blob_modifier = demo.blob_seed;
// FIXME should probably start playback on first real input // FIXME should probably start playback on first real input
@ -908,13 +908,7 @@ class Player extends PrimaryView {
get_input() { get_input() {
let input; let input;
if (this.demo_faucet) { if (this.demo_faucet) {
let step = this.demo_faucet.next(); input = this.demo_faucet.get(this.level.tic_counter);
if (step.done) {
input = new Set;
}
else {
input = step.value;
}
} }
else { else {
// Convert input keys to actions. This is only done now // Convert input keys to actions. This is only done now