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