Allow rewinding a replay without desyncing it
This commit is contained in:
parent
410af788fc
commit
0f0c7437a6
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
js/main.js
10
js/main.js
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user