fix: prediction

This commit is contained in:
cha0s 2024-09-29 01:53:23 -05:00
parent e6f54c3694
commit 46cff307b1

View File

@ -1,24 +1,14 @@
import {LRUCache} from 'lru-cache';
import Components from '@/ecs/components/index.js'; import Components from '@/ecs/components/index.js';
import Ecs from '@/ecs/ecs.js'; import Ecs from '@/ecs/ecs.js';
import Systems from '@/ecs/systems/index.js'; import Systems from '@/ecs/systems/index.js';
import {withResolvers} from '@/util/promise.js'; import {readAsset} from '@/util/resources.js';
const cache = new LRUCache({
max: 128,
});
class PredictionEcs extends Ecs { class PredictionEcs extends Ecs {
async readAsset(uri) { async readAsset(path) {
if (!cache.has(uri)) { const resource = await readAsset(path);
const {promise, resolve, reject} = withResolvers(); return resource
cache.set(uri, promise); ? resource
fetch(uri) : new ArrayBuffer(0);
.then((response) => resolve(response.ok ? response.arrayBuffer() : new ArrayBuffer(0)))
.catch(reject);
}
return cache.get(uri);
} }
} }
@ -49,7 +39,6 @@ function applyClientActions(elapsed) {
} }
} }
} }
action.steps.push(elapsed);
} }
if (1 === action.finished) { if (1 === action.finished) {
if (!Controlled.locked) { if (!Controlled.locked) {
@ -65,20 +54,17 @@ function applyClientActions(elapsed) {
} }
action.finished = 2; action.finished = 2;
} }
if (!action.ack) {
action.stop += elapsed;
}
if (action.ack && 2 === action.finished) { if (action.ack && 2 === action.finished) {
action.steps.shift(); action.start += elapsed;
if (0 === action.steps.length) { if (action.start >= action.stop) {
finished.push(id); finished.push(id);
continue; continue;
} }
} }
let leap = 0; ecs.predict(main, action.stop - action.start);
for (const step of action.steps) {
leap += step;
}
if (leap > 0) {
ecs.predict(main, leap);
}
} }
for (const id of finished) { for (const id of finished) {
actions.delete(id); actions.delete(id);
@ -108,10 +94,13 @@ onmessage = async (event) => {
pending.delete(packet.payload.type); pending.delete(packet.payload.type);
} }
else { else {
const now = performance.now() / 1000;
const tx = { const tx = {
action: packet.payload, action: packet.payload,
ack: false,finished: 0, ack: false,
steps: [], finished: 0,
start: now,
stop: now,
}; };
packet.payload.ack = Math.random(); packet.payload.ack = Math.random();
pending.set(packet.payload.type, packet.payload.ack); pending.set(packet.payload.type, packet.payload.ack);
@ -152,9 +141,20 @@ onmessage = async (event) => {
const authoritative = structuredClone(main.toNet(main)); const authoritative = structuredClone(main.toNet(main));
applyClientActions(packet.payload.elapsed); applyClientActions(packet.payload.elapsed);
if (ecs.diff[mainEntityId]) { if (ecs.diff[mainEntityId]) {
packet.payload.ecs[mainEntityId] = ecs.diff[mainEntityId]; packet.payload.ecs[mainEntityId] ??= {};
ecs.mergeDiff(
packet.payload.ecs[mainEntityId],
ecs.diff[mainEntityId],
);
const reset = {};
for (const componentName in ecs.diff[mainEntityId]) {
reset[componentName] = {};
for (const property in ecs.diff[mainEntityId][componentName]) {
reset[componentName][property] = authoritative[componentName][property];
}
}
await ecs.apply({[mainEntityId]: reset});
} }
await ecs.apply({[mainEntityId]: authoritative});
} }
ecs.setClean(); ecs.setClean();
break; break;