@lagless/core 0.0.35 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/ecs-runner.d.ts +1 -1
- package/dist/lib/ecs-runner.d.ts.map +1 -1
- package/dist/lib/ecs-runner.js +8 -2
- package/dist/lib/ecs-runner.js.map +1 -1
- package/dist/lib/ecs-simulation.d.ts +24 -4
- package/dist/lib/ecs-simulation.d.ts.map +1 -1
- package/dist/lib/ecs-simulation.js +57 -1
- package/dist/lib/ecs-simulation.js.map +1 -1
- package/dist/lib/hash-verification/abstract-hash-verification.system.d.ts.map +1 -1
- package/dist/lib/hash-verification/abstract-hash-verification.system.js +5 -0
- package/dist/lib/hash-verification/abstract-hash-verification.system.js.map +1 -1
- package/dist/lib/hash-verification/create-hash-reporter.d.ts.map +1 -1
- package/dist/lib/hash-verification/create-hash-reporter.js +11 -8
- package/dist/lib/hash-verification/create-hash-reporter.js.map +1 -1
- package/dist/lib/input/abstract-input-provider.d.ts +1 -0
- package/dist/lib/input/abstract-input-provider.d.ts.map +1 -1
- package/dist/lib/input/abstract-input-provider.js +8 -1
- package/dist/lib/input/abstract-input-provider.js.map +1 -1
- package/dist/lib/input/input-provider-di-token.d.ts +1 -0
- package/dist/lib/input/input-provider-di-token.d.ts.map +1 -1
- package/dist/lib/input/input-provider-di-token.js +3 -0
- package/dist/lib/input/input-provider-di-token.js.map +1 -1
- package/dist/lib/input/local-input-provider.d.ts +1 -0
- package/dist/lib/input/local-input-provider.d.ts.map +1 -1
- package/dist/lib/input/local-input-provider.js +5 -0
- package/dist/lib/input/local-input-provider.js.map +1 -1
- package/dist/lib/input/replay-input-provider.d.ts +1 -0
- package/dist/lib/input/replay-input-provider.d.ts.map +1 -1
- package/dist/lib/input/replay-input-provider.js +5 -0
- package/dist/lib/input/replay-input-provider.js.map +1 -1
- package/dist/lib/mem/managers/entities-manager.d.ts +3 -2
- package/dist/lib/mem/managers/entities-manager.d.ts.map +1 -1
- package/dist/lib/mem/managers/entities-manager.js +65 -23
- package/dist/lib/mem/managers/entities-manager.js.map +1 -1
- package/dist/lib/mem/managers/filters-manager.d.ts +2 -2
- package/dist/lib/mem/managers/filters-manager.d.ts.map +1 -1
- package/dist/lib/mem/managers/filters-manager.js +19 -4
- package/dist/lib/mem/managers/filters-manager.js.map +1 -1
- package/dist/lib/mem/mem.d.ts.map +1 -1
- package/dist/lib/mem/mem.js +4 -2
- package/dist/lib/mem/mem.js.map +1 -1
- package/dist/lib/signals/signal.d.ts +4 -3
- package/dist/lib/signals/signal.d.ts.map +1 -1
- package/dist/lib/signals/signal.js +34 -34
- package/dist/lib/signals/signal.js.map +1 -1
- package/dist/lib/signals/signals.registry.d.ts +1 -1
- package/dist/lib/signals/signals.registry.d.ts.map +1 -1
- package/dist/lib/signals/signals.registry.js +2 -2
- package/dist/lib/signals/signals.registry.js.map +1 -1
- package/dist/lib/types/abstract-filter.d.ts +3 -2
- package/dist/lib/types/abstract-filter.d.ts.map +1 -1
- package/dist/lib/types/abstract-filter.js +22 -21
- package/dist/lib/types/abstract-filter.js.map +1 -1
- package/dist/lib/types/ecs-types.d.ts +5 -3
- package/dist/lib/types/ecs-types.d.ts.map +1 -1
- package/dist/lib/types/ecs-types.js.map +1 -1
- package/package.json +4 -5
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { AbstractInputProvider } from './abstract-input-provider.js';
|
|
2
2
|
export class LocalInputProvider extends AbstractInputProvider {
|
|
3
|
+
get verifiedTick() {
|
|
4
|
+
var _this__simulation;
|
|
5
|
+
var _this__simulation_tick;
|
|
6
|
+
return (_this__simulation_tick = (_this__simulation = this._simulation) == null ? void 0 : _this__simulation.tick) != null ? _this__simulation_tick : -1;
|
|
7
|
+
}
|
|
3
8
|
getInvalidateRollbackTick() {
|
|
4
9
|
return undefined;
|
|
5
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/input/local-input-provider.ts"],"sourcesContent":["import { AbstractInputProvider } from './abstract-input-provider.js';\n\nexport class LocalInputProvider extends AbstractInputProvider {\n public override playerSlot = 0;\n\n public override getInvalidateRollbackTick(): void | number {\n return undefined;\n }\n}\n"],"names":["AbstractInputProvider","LocalInputProvider","getInvalidateRollbackTick","undefined","playerSlot"],"rangeMappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/input/local-input-provider.ts"],"sourcesContent":["import { AbstractInputProvider } from './abstract-input-provider.js';\n\nexport class LocalInputProvider extends AbstractInputProvider {\n public override playerSlot = 0;\n\n public override get verifiedTick(): number {\n return this._simulation?.tick ?? -1;\n }\n\n public override getInvalidateRollbackTick(): void | number {\n return undefined;\n }\n}\n"],"names":["AbstractInputProvider","LocalInputProvider","verifiedTick","_simulation","tick","getInvalidateRollbackTick","undefined","playerSlot"],"rangeMappings":";;;;;;;;;;;;;;","mappings":"AAAA,SAASA,qBAAqB,QAAQ,+BAA+B;AAErE,OAAO,MAAMC,2BAA2BD;IAGtC,IAAoBE,eAAuB;YAClC;YAAA;QAAP,OAAO,CAAA,0BAAA,oBAAA,IAAI,CAACC,WAAW,qBAAhB,kBAAkBC,IAAI,YAAtB,yBAA0B,CAAC;IACpC;IAEgBC,4BAA2C;QACzD,OAAOC;IACT;;;aARgBC,aAAa;;AAS/B"}
|
|
@@ -3,6 +3,7 @@ import { ECSConfig } from '../ecs-config.js';
|
|
|
3
3
|
import { InputRegistry } from './input-registry.js';
|
|
4
4
|
export declare class ReplayInputProvider extends AbstractInputProvider {
|
|
5
5
|
playerSlot: number;
|
|
6
|
+
get verifiedTick(): number;
|
|
6
7
|
getInvalidateRollbackTick(): undefined;
|
|
7
8
|
constructor(replayData: ArrayBuffer, ecsConfig: ECSConfig, inputRegistry: InputRegistry);
|
|
8
9
|
update(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-input-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/input/replay-input-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQpD,qBAAa,mBAAoB,SAAQ,qBAAqB;IAC5C,UAAU,SAAK;
|
|
1
|
+
{"version":3,"file":"replay-input-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/input/replay-input-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQpD,qBAAa,mBAAoB,SAAQ,qBAAqB;IAC5C,UAAU,SAAK;IAE/B,IAAoB,YAAY,IAAI,MAAM,CAEzC;IAEe,yBAAyB;gBAKvC,UAAU,EAAE,WAAW,EACvB,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa;IAMd,MAAM,IAAI,IAAI;WAIhB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,GAAG,WAAW;WAWrG,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,GAAG,mBAAmB;CAUvG"}
|
|
@@ -6,6 +6,11 @@ const MAX_PLAYERS_OFFSET = SEED_OFFSET + SEED_LENGTH;
|
|
|
6
6
|
const FPS_OFFSET = MAX_PLAYERS_OFFSET + 1;
|
|
7
7
|
const REPLAY_DATA_OFFSET = FPS_OFFSET + 1;
|
|
8
8
|
export class ReplayInputProvider extends AbstractInputProvider {
|
|
9
|
+
get verifiedTick() {
|
|
10
|
+
var _this__simulation;
|
|
11
|
+
var _this__simulation_tick;
|
|
12
|
+
return (_this__simulation_tick = (_this__simulation = this._simulation) == null ? void 0 : _this__simulation.tick) != null ? _this__simulation_tick : -1;
|
|
13
|
+
}
|
|
9
14
|
getInvalidateRollbackTick() {
|
|
10
15
|
return undefined;
|
|
11
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/input/replay-input-provider.ts"],"sourcesContent":["import { AbstractInputProvider } from './abstract-input-provider.js';\nimport { ECSConfig } from '../ecs-config.js';\nimport { InputRegistry } from './input-registry.js';\n\nconst SEED_OFFSET = 0;\nconst SEED_LENGTH = 16;\nconst MAX_PLAYERS_OFFSET = SEED_OFFSET + SEED_LENGTH;\nconst FPS_OFFSET = MAX_PLAYERS_OFFSET + 1;\nconst REPLAY_DATA_OFFSET = FPS_OFFSET + 1;\n\nexport class ReplayInputProvider extends AbstractInputProvider {\n public override playerSlot = 0;\n\n public override getInvalidateRollbackTick() {\n return undefined;\n }\n\n constructor(\n replayData: ArrayBuffer,\n ecsConfig: ECSConfig,\n inputRegistry: InputRegistry,\n ) {\n super(ecsConfig, inputRegistry);\n this._rpcHistory.import(inputRegistry, replayData);\n }\n\n public override update(): void {\n // do nothing, all inputs are pre-recorded\n }\n\n public static exportReplay(seed: Uint8Array, maxPlayers: number, fps: number, replayData: ArrayBuffer): ArrayBuffer {\n const replay = new ArrayBuffer(REPLAY_DATA_OFFSET + replayData.byteLength);\n const replayUint8 = new Uint8Array(replay);\n replayUint8.set(seed, SEED_OFFSET);\n const replayView = new DataView(replay);\n replayView.setUint8(MAX_PLAYERS_OFFSET, maxPlayers);\n replayView.setUint8(FPS_OFFSET, fps);\n replayUint8.set(new Uint8Array(replayData), REPLAY_DATA_OFFSET);\n return replay;\n }\n\n public static createFromReplay(replay: ArrayBuffer, inputRegistry: InputRegistry): ReplayInputProvider {\n const replayUint8 = new Uint8Array(replay);\n const seed = replayUint8.slice(SEED_OFFSET, SEED_OFFSET + SEED_LENGTH);\n const replayView = new DataView(replay);\n const maxPlayers = replayView.getUint8(MAX_PLAYERS_OFFSET);\n const fps = replayView.getUint8(FPS_OFFSET);\n const rpcData = replay.slice(REPLAY_DATA_OFFSET);\n const ecsConfig = new ECSConfig({ maxPlayers, seed, fps });\n return new ReplayInputProvider(rpcData, ecsConfig, inputRegistry);\n }\n}\n"],"names":["AbstractInputProvider","ECSConfig","SEED_OFFSET","SEED_LENGTH","MAX_PLAYERS_OFFSET","FPS_OFFSET","REPLAY_DATA_OFFSET","ReplayInputProvider","getInvalidateRollbackTick","undefined","update","exportReplay","seed","maxPlayers","fps","replayData","replay","ArrayBuffer","byteLength","replayUint8","Uint8Array","set","replayView","DataView","setUint8","createFromReplay","inputRegistry","slice","getUint8","rpcData","ecsConfig","constructor","playerSlot","_rpcHistory","import"],"rangeMappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/input/replay-input-provider.ts"],"sourcesContent":["import { AbstractInputProvider } from './abstract-input-provider.js';\nimport { ECSConfig } from '../ecs-config.js';\nimport { InputRegistry } from './input-registry.js';\n\nconst SEED_OFFSET = 0;\nconst SEED_LENGTH = 16;\nconst MAX_PLAYERS_OFFSET = SEED_OFFSET + SEED_LENGTH;\nconst FPS_OFFSET = MAX_PLAYERS_OFFSET + 1;\nconst REPLAY_DATA_OFFSET = FPS_OFFSET + 1;\n\nexport class ReplayInputProvider extends AbstractInputProvider {\n public override playerSlot = 0;\n\n public override get verifiedTick(): number {\n return this._simulation?.tick ?? -1;\n }\n\n public override getInvalidateRollbackTick() {\n return undefined;\n }\n\n constructor(\n replayData: ArrayBuffer,\n ecsConfig: ECSConfig,\n inputRegistry: InputRegistry,\n ) {\n super(ecsConfig, inputRegistry);\n this._rpcHistory.import(inputRegistry, replayData);\n }\n\n public override update(): void {\n // do nothing, all inputs are pre-recorded\n }\n\n public static exportReplay(seed: Uint8Array, maxPlayers: number, fps: number, replayData: ArrayBuffer): ArrayBuffer {\n const replay = new ArrayBuffer(REPLAY_DATA_OFFSET + replayData.byteLength);\n const replayUint8 = new Uint8Array(replay);\n replayUint8.set(seed, SEED_OFFSET);\n const replayView = new DataView(replay);\n replayView.setUint8(MAX_PLAYERS_OFFSET, maxPlayers);\n replayView.setUint8(FPS_OFFSET, fps);\n replayUint8.set(new Uint8Array(replayData), REPLAY_DATA_OFFSET);\n return replay;\n }\n\n public static createFromReplay(replay: ArrayBuffer, inputRegistry: InputRegistry): ReplayInputProvider {\n const replayUint8 = new Uint8Array(replay);\n const seed = replayUint8.slice(SEED_OFFSET, SEED_OFFSET + SEED_LENGTH);\n const replayView = new DataView(replay);\n const maxPlayers = replayView.getUint8(MAX_PLAYERS_OFFSET);\n const fps = replayView.getUint8(FPS_OFFSET);\n const rpcData = replay.slice(REPLAY_DATA_OFFSET);\n const ecsConfig = new ECSConfig({ maxPlayers, seed, fps });\n return new ReplayInputProvider(rpcData, ecsConfig, inputRegistry);\n }\n}\n"],"names":["AbstractInputProvider","ECSConfig","SEED_OFFSET","SEED_LENGTH","MAX_PLAYERS_OFFSET","FPS_OFFSET","REPLAY_DATA_OFFSET","ReplayInputProvider","verifiedTick","_simulation","tick","getInvalidateRollbackTick","undefined","update","exportReplay","seed","maxPlayers","fps","replayData","replay","ArrayBuffer","byteLength","replayUint8","Uint8Array","set","replayView","DataView","setUint8","createFromReplay","inputRegistry","slice","getUint8","rpcData","ecsConfig","constructor","playerSlot","_rpcHistory","import"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,qBAAqB,QAAQ,+BAA+B;AACrE,SAASC,SAAS,QAAQ,mBAAmB;AAG7C,MAAMC,cAAc;AACpB,MAAMC,cAAc;AACpB,MAAMC,qBAAqBF,cAAcC;AACzC,MAAME,aAAaD,qBAAqB;AACxC,MAAME,qBAAqBD,aAAa;AAExC,OAAO,MAAME,4BAA4BP;IAGvC,IAAoBQ,eAAuB;YAClC;YAAA;QAAP,OAAO,CAAA,0BAAA,oBAAA,IAAI,CAACC,WAAW,qBAAhB,kBAAkBC,IAAI,YAAtB,yBAA0B,CAAC;IACpC;IAEgBC,4BAA4B;QAC1C,OAAOC;IACT;IAWgBC,SAAe;IAC7B,0CAA0C;IAC5C;IAEA,OAAcC,aAAaC,IAAgB,EAAEC,UAAkB,EAAEC,GAAW,EAAEC,UAAuB,EAAe;QAClH,MAAMC,SAAS,IAAIC,YAAYd,qBAAqBY,WAAWG,UAAU;QACzE,MAAMC,cAAc,IAAIC,WAAWJ;QACnCG,YAAYE,GAAG,CAACT,MAAMb;QACtB,MAAMuB,aAAa,IAAIC,SAASP;QAChCM,WAAWE,QAAQ,CAACvB,oBAAoBY;QACxCS,WAAWE,QAAQ,CAACtB,YAAYY;QAChCK,YAAYE,GAAG,CAAC,IAAID,WAAWL,aAAaZ;QAC5C,OAAOa;IACT;IAEA,OAAcS,iBAAiBT,MAAmB,EAAEU,aAA4B,EAAuB;QACrG,MAAMP,cAAc,IAAIC,WAAWJ;QACnC,MAAMJ,OAAOO,YAAYQ,KAAK,CAAC5B,aAAaA,cAAcC;QAC1D,MAAMsB,aAAa,IAAIC,SAASP;QAChC,MAAMH,aAAaS,WAAWM,QAAQ,CAAC3B;QACvC,MAAMa,MAAMQ,WAAWM,QAAQ,CAAC1B;QAChC,MAAM2B,UAAUb,OAAOW,KAAK,CAACxB;QAC7B,MAAM2B,YAAY,IAAIhC,UAAU;YAAEe;YAAYD;YAAME;QAAI;QACxD,OAAO,IAAIV,oBAAoByB,SAASC,WAAWJ;IACrD;IAjCAK,YACEhB,UAAuB,EACvBe,SAAoB,EACpBJ,aAA4B,CAC5B;QACA,KAAK,CAACI,WAAWJ;aAfHM,aAAa;QAgB3B,IAAI,CAACC,WAAW,CAACC,MAAM,CAACR,eAAeX;IACzC;AA2BF"}
|
|
@@ -5,17 +5,18 @@ import { ECSConfig } from '../../ecs-config.js';
|
|
|
5
5
|
import { Prefab } from '../../prefab.js';
|
|
6
6
|
import { IComponentConstructor } from '../../types/index.js';
|
|
7
7
|
import { MemoryTracker } from '@lagless/binary';
|
|
8
|
-
/** Sentinel value indicating an entity slot is unused / removed. */
|
|
8
|
+
/** Sentinel value indicating an entity slot is unused / removed. All mask words are set to 0xFFFFFFFF. */
|
|
9
9
|
export declare const ENTITY_REMOVED_MASK = 4294967295;
|
|
10
10
|
export declare class EntitiesManager implements IAbstractMemory {
|
|
11
11
|
private readonly _ECSConfig;
|
|
12
12
|
private readonly _ComponentsMemory;
|
|
13
13
|
private readonly _FiltersMemory;
|
|
14
|
+
private readonly _maskWords;
|
|
14
15
|
private _nextEntityId;
|
|
15
16
|
private _removedEntitiesLength;
|
|
16
17
|
private _removedEntities;
|
|
17
18
|
private _entitiesComponentsMasks;
|
|
18
|
-
constructor(_ECSConfig: ECSConfig, _ComponentsMemory: ComponentsManager, _FiltersMemory: FiltersManager);
|
|
19
|
+
constructor(_ECSConfig: ECSConfig, _ComponentsMemory: ComponentsManager, _FiltersMemory: FiltersManager, _maskWords?: 1 | 2);
|
|
19
20
|
createEntity(prefab?: Prefab): number;
|
|
20
21
|
removeEntity(entity: number): void;
|
|
21
22
|
isEntityAlive(entity: number): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities-manager.d.ts","sourceRoot":"","sources":["../../../../src/lib/mem/managers/entities-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,
|
|
1
|
+
{"version":3,"file":"entities-manager.d.ts","sourceRoot":"","sources":["../../../../src/lib/mem/managers/entities-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,0GAA0G;AAC1G,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAE9C,qBAAa,eAAgB,YAAW,eAAe;IAOnD,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAT7B,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,sBAAsB,CAAe;IAC7C,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,wBAAwB,CAAe;gBAG5B,UAAU,EAAE,SAAS,EACrB,iBAAiB,EAAE,iBAAiB,EACpC,cAAc,EAAE,cAAc,EAC9B,UAAU,GAAE,CAAC,GAAG,CAAK;IAGjC,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IAoCrC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IA6BlC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAStC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,qBAAqB,GAAG,IAAI;IAQ/E,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,qBAAqB,GAAG,IAAI;IAQlF,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,qBAAqB,GAAG,OAAO;IAUlF,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAazD,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,kBAAkB;IAWnB,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAe5D,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;CAMnD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Sentinel value indicating an entity slot is unused / removed. */ export const ENTITY_REMOVED_MASK = 0xFFFFFFFF;
|
|
1
|
+
/** Sentinel value indicating an entity slot is unused / removed. All mask words are set to 0xFFFFFFFF. */ export const ENTITY_REMOVED_MASK = 0xFFFFFFFF;
|
|
2
2
|
export class EntitiesManager {
|
|
3
3
|
createEntity(prefab) {
|
|
4
4
|
let entity = this.popRemovedEntities();
|
|
@@ -9,66 +9,107 @@ export class EntitiesManager {
|
|
|
9
9
|
if (entity >= this._ECSConfig.maxEntities) {
|
|
10
10
|
throw new Error(`Maximum number of entities (${this._ECSConfig.maxEntities}) exceeded`);
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
// Clear all mask words for the entity
|
|
13
|
+
const base = entity * this._maskWords;
|
|
14
|
+
for(let w = 0; w < this._maskWords; w++){
|
|
15
|
+
this._entitiesComponentsMasks[base + w] = 0;
|
|
16
|
+
}
|
|
13
17
|
if (prefab) {
|
|
14
18
|
for (const [ComponentConstructor, Values] of prefab){
|
|
15
|
-
const
|
|
16
|
-
|
|
19
|
+
const bitIndex = ComponentConstructor.ID;
|
|
20
|
+
const wordOffset = bitIndex >>> 5;
|
|
21
|
+
const bit = 1 << (bitIndex & 31);
|
|
22
|
+
this._entitiesComponentsMasks[base + wordOffset] |= bit;
|
|
17
23
|
if (!Values) continue;
|
|
24
|
+
const componentInstance = this._ComponentsMemory.get(ComponentConstructor);
|
|
18
25
|
for (const [fieldName, value] of Object.entries(Values)){
|
|
19
26
|
if (value === undefined) continue;
|
|
20
27
|
componentInstance.unsafe[fieldName][entity] = value;
|
|
21
28
|
}
|
|
22
29
|
}
|
|
23
30
|
}
|
|
24
|
-
this.updateFilters(entity
|
|
31
|
+
this.updateFilters(entity);
|
|
25
32
|
return entity;
|
|
26
33
|
}
|
|
27
34
|
removeEntity(entity) {
|
|
28
35
|
if (entity < 0 || entity >= this._ECSConfig.maxEntities) {
|
|
29
36
|
throw new Error(`Entity ID ${entity} is out of bounds`);
|
|
30
37
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
const base = entity * this._maskWords;
|
|
39
|
+
// Guard against double removal (all mask words must be sentinel)
|
|
40
|
+
let isRemoved = true;
|
|
41
|
+
for(let w = 0; w < this._maskWords; w++){
|
|
42
|
+
if (this._entitiesComponentsMasks[base + w] !== ENTITY_REMOVED_MASK) {
|
|
43
|
+
isRemoved = false;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (isRemoved) return;
|
|
48
|
+
// Set all mask words to sentinel
|
|
49
|
+
for(let w = 0; w < this._maskWords; w++){
|
|
50
|
+
this._entitiesComponentsMasks[base + w] = ENTITY_REMOVED_MASK;
|
|
34
51
|
}
|
|
35
|
-
this._entitiesComponentsMasks[entity] = ENTITY_REMOVED_MASK;
|
|
36
52
|
// Add the entity to the removed entities stack
|
|
37
53
|
this._removedEntities[this._removedEntitiesLength[0]] = entity;
|
|
38
54
|
this._removedEntitiesLength[0]++;
|
|
39
|
-
this.
|
|
55
|
+
this._FiltersMemory.removeEntityFromAllFilters(entity);
|
|
40
56
|
}
|
|
41
57
|
isEntityAlive(entity) {
|
|
42
58
|
if (entity < 0 || entity >= this._ECSConfig.maxEntities) return false;
|
|
43
|
-
|
|
59
|
+
const base = entity * this._maskWords;
|
|
60
|
+
for(let w = 0; w < this._maskWords; w++){
|
|
61
|
+
if (this._entitiesComponentsMasks[base + w] !== ENTITY_REMOVED_MASK) return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
44
64
|
}
|
|
45
65
|
addComponent(entity, ComponentConstructor) {
|
|
46
|
-
|
|
47
|
-
|
|
66
|
+
const bitIndex = ComponentConstructor.ID;
|
|
67
|
+
const base = entity * this._maskWords;
|
|
68
|
+
const wordOffset = bitIndex >>> 5;
|
|
69
|
+
this._entitiesComponentsMasks[base + wordOffset] |= 1 << (bitIndex & 31);
|
|
70
|
+
this.updateFilters(entity);
|
|
48
71
|
}
|
|
49
72
|
removeComponent(entity, ComponentConstructor) {
|
|
50
|
-
|
|
51
|
-
|
|
73
|
+
const bitIndex = ComponentConstructor.ID;
|
|
74
|
+
const base = entity * this._maskWords;
|
|
75
|
+
const wordOffset = bitIndex >>> 5;
|
|
76
|
+
this._entitiesComponentsMasks[base + wordOffset] &= ~(1 << (bitIndex & 31));
|
|
77
|
+
this.updateFilters(entity);
|
|
52
78
|
}
|
|
53
79
|
hasComponent(entity, ComponentConstructor) {
|
|
54
80
|
if (entity < 0 || entity >= this._ECSConfig.maxEntities) {
|
|
55
81
|
throw new Error(`Entity ID ${entity} is out of bounds`);
|
|
56
82
|
}
|
|
57
|
-
|
|
83
|
+
const bitIndex = ComponentConstructor.ID;
|
|
84
|
+
const base = entity * this._maskWords;
|
|
85
|
+
const wordOffset = bitIndex >>> 5;
|
|
86
|
+
return (this._entitiesComponentsMasks[base + wordOffset] & 1 << (bitIndex & 31)) !== 0;
|
|
58
87
|
}
|
|
59
88
|
hasPrefab(entity, prefab) {
|
|
89
|
+
const base = entity * this._maskWords;
|
|
60
90
|
for (const [ComponentConstructor] of prefab){
|
|
61
|
-
|
|
91
|
+
const bitIndex = ComponentConstructor.ID;
|
|
92
|
+
const wordOffset = bitIndex >>> 5;
|
|
93
|
+
if ((this._entitiesComponentsMasks[base + wordOffset] & 1 << (bitIndex & 31)) === 0) {
|
|
62
94
|
return false;
|
|
63
95
|
}
|
|
64
96
|
}
|
|
65
97
|
return true;
|
|
66
98
|
}
|
|
67
|
-
updateFilters(entity
|
|
68
|
-
|
|
99
|
+
updateFilters(entity) {
|
|
100
|
+
const base = entity * this._maskWords;
|
|
101
|
+
// Check if entity has any components set (all words zero means empty)
|
|
102
|
+
let isEmpty = true;
|
|
103
|
+
for(let w = 0; w < this._maskWords; w++){
|
|
104
|
+
if (this._entitiesComponentsMasks[base + w] !== 0) {
|
|
105
|
+
isEmpty = false;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (isEmpty) {
|
|
69
110
|
this._FiltersMemory.removeEntityFromAllFilters(entity);
|
|
70
111
|
} else {
|
|
71
|
-
this._FiltersMemory.updateEntityInAllFilters(entity,
|
|
112
|
+
this._FiltersMemory.updateEntityInAllFilters(entity, this._entitiesComponentsMasks, base, this._maskWords);
|
|
72
113
|
}
|
|
73
114
|
}
|
|
74
115
|
popRemovedEntities() {
|
|
@@ -86,7 +127,7 @@ export class EntitiesManager {
|
|
|
86
127
|
tracker.add(this._removedEntitiesLength.byteLength);
|
|
87
128
|
this._removedEntities = new Uint32Array(arrayBuffer, tracker.ptr, this._ECSConfig.maxEntities);
|
|
88
129
|
tracker.add(this._removedEntities.byteLength);
|
|
89
|
-
this._entitiesComponentsMasks = new Uint32Array(arrayBuffer, tracker.ptr, this._ECSConfig.maxEntities);
|
|
130
|
+
this._entitiesComponentsMasks = new Uint32Array(arrayBuffer, tracker.ptr, this._ECSConfig.maxEntities * this._maskWords);
|
|
90
131
|
this._entitiesComponentsMasks.fill(ENTITY_REMOVED_MASK);
|
|
91
132
|
tracker.add(this._entitiesComponentsMasks.byteLength);
|
|
92
133
|
}
|
|
@@ -94,12 +135,13 @@ export class EntitiesManager {
|
|
|
94
135
|
tracker.add(Uint32Array.BYTES_PER_ELEMENT); // nextEntityId
|
|
95
136
|
tracker.add(Uint32Array.BYTES_PER_ELEMENT); // removedEntitiesLength
|
|
96
137
|
tracker.add(this._ECSConfig.maxEntities * Uint32Array.BYTES_PER_ELEMENT); // removedEntities
|
|
97
|
-
tracker.add(this._ECSConfig.maxEntities * Uint32Array.BYTES_PER_ELEMENT); // entitiesComponentsMasks
|
|
138
|
+
tracker.add(this._ECSConfig.maxEntities * this._maskWords * Uint32Array.BYTES_PER_ELEMENT); // entitiesComponentsMasks
|
|
98
139
|
}
|
|
99
|
-
constructor(_ECSConfig, _ComponentsMemory, _FiltersMemory){
|
|
140
|
+
constructor(_ECSConfig, _ComponentsMemory, _FiltersMemory, _maskWords = 1){
|
|
100
141
|
this._ECSConfig = _ECSConfig;
|
|
101
142
|
this._ComponentsMemory = _ComponentsMemory;
|
|
102
143
|
this._FiltersMemory = _FiltersMemory;
|
|
144
|
+
this._maskWords = _maskWords;
|
|
103
145
|
}
|
|
104
146
|
}
|
|
105
147
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/mem/managers/entities-manager.ts"],"sourcesContent":["import { FiltersManager } from './filters-manager.js';\nimport { ComponentsManager } from './components-manager.js';\nimport { IAbstractMemory } from '../abstract-memory.interface.js';\nimport { ECSConfig } from '../../ecs-config.js';\nimport { Prefab } from '../../prefab.js';\nimport { IComponentConstructor } from '../../types/index.js';\nimport { MemoryTracker } from '@lagless/binary';\n\n/** Sentinel value indicating an entity slot is unused / removed. */\nexport const ENTITY_REMOVED_MASK = 0xFFFFFFFF;\n\nexport class EntitiesManager implements IAbstractMemory {\n private _nextEntityId!: Uint32Array;\n private _removedEntitiesLength!: Uint32Array;\n private _removedEntities!: Uint32Array;\n private _entitiesComponentsMasks!: Uint32Array;\n\n constructor(\n private readonly _ECSConfig: ECSConfig,\n private readonly _ComponentsMemory: ComponentsManager,\n private readonly _FiltersMemory: FiltersManager,\n ) {}\n\n public createEntity(prefab?: Prefab): number {\n let entity = this.popRemovedEntities();\n if (entity === undefined) {\n entity = this._nextEntityId[0];\n this._nextEntityId[0]++;\n }\n if (entity >= this._ECSConfig.maxEntities) {\n throw new Error(`Maximum number of entities (${this._ECSConfig.maxEntities}) exceeded`);\n }\n\n this._entitiesComponentsMasks[entity] = 0;\n\n if (prefab) {\n for (const [ ComponentConstructor, Values ] of prefab) {\n const componentInstance = this._ComponentsMemory.get(ComponentConstructor);\n this._entitiesComponentsMasks[entity] |= ComponentConstructor.ID;\n if (!Values) continue;\n for (const [ fieldName, value ] of Object.entries(Values)) {\n if (value === undefined) continue;\n componentInstance.unsafe[fieldName as keyof typeof componentInstance.unsafe][entity] = value;\n }\n }\n }\n\n this.updateFilters(entity, this._entitiesComponentsMasks[entity]);\n\n return entity;\n }\n\n public removeEntity(entity: number): void {\n if (entity < 0 || entity >= this._ECSConfig.maxEntities) {\n throw new Error(`Entity ID ${entity} is out of bounds`);\n }\n\n // Guard against double removal\n if (this._entitiesComponentsMasks[entity] === ENTITY_REMOVED_MASK) {\n return;\n }\n\n this._entitiesComponentsMasks[entity] = ENTITY_REMOVED_MASK;\n\n // Add the entity to the removed entities stack\n this._removedEntities[this._removedEntitiesLength[0]] = entity;\n this._removedEntitiesLength[0]++;\n\n this.updateFilters(entity, ENTITY_REMOVED_MASK);\n }\n\n public isEntityAlive(entity: number): boolean {\n if (entity < 0 || entity >= this._ECSConfig.maxEntities) return false;\n return this._entitiesComponentsMasks[entity] !== ENTITY_REMOVED_MASK;\n }\n\n public addComponent(entity: number, ComponentConstructor: IComponentConstructor): void {\n this._entitiesComponentsMasks[entity] |= ComponentConstructor.ID;\n this.updateFilters(entity, this._entitiesComponentsMasks[entity]);\n }\n\n public removeComponent(entity: number, ComponentConstructor: IComponentConstructor): void {\n this._entitiesComponentsMasks[entity] &= ~ComponentConstructor.ID;\n this.updateFilters(entity, this._entitiesComponentsMasks[entity]);\n }\n\n public hasComponent(entity: number, ComponentConstructor: IComponentConstructor): boolean {\n if (entity < 0 || entity >= this._ECSConfig.maxEntities) {\n throw new Error(`Entity ID ${entity} is out of bounds`);\n }\n return (this._entitiesComponentsMasks[entity] & ComponentConstructor.ID) !== 0;\n }\n\n public hasPrefab(entity: number, prefab: Prefab): boolean {\n for (const [ ComponentConstructor ] of prefab) {\n if ((this._entitiesComponentsMasks[entity] & ComponentConstructor.ID) === 0) {\n return false;\n }\n }\n\n return true;\n }\n\n private updateFilters(entity: number, componentMask: number): void {\n if (componentMask === ENTITY_REMOVED_MASK || componentMask === 0) {\n this._FiltersMemory.removeEntityFromAllFilters(entity);\n } else {\n this._FiltersMemory.updateEntityInAllFilters(entity, componentMask);\n }\n }\n\n private popRemovedEntities(): number | undefined {\n if (this._removedEntitiesLength[0] === 0) {\n return undefined;\n }\n\n const entity = this._removedEntities[this._removedEntitiesLength[0] - 1];\n this._removedEntitiesLength[0]--;\n\n return entity;\n }\n\n public init(arrayBuffer: ArrayBuffer, tracker: MemoryTracker): void {\n this._nextEntityId = new Uint32Array(arrayBuffer, tracker.ptr, 1);\n tracker.add(this._nextEntityId.byteLength);\n\n this._removedEntitiesLength = new Uint32Array(arrayBuffer, tracker.ptr, 1);\n tracker.add(this._removedEntitiesLength.byteLength);\n\n this._removedEntities = new Uint32Array(arrayBuffer, tracker.ptr, this._ECSConfig.maxEntities);\n tracker.add(this._removedEntities.byteLength);\n\n this._entitiesComponentsMasks = new Uint32Array(arrayBuffer, tracker.ptr, this._ECSConfig.maxEntities);\n this._entitiesComponentsMasks.fill(ENTITY_REMOVED_MASK);\n tracker.add(this._entitiesComponentsMasks.byteLength);\n }\n\n public calculateSize(tracker: MemoryTracker): void {\n tracker.add(Uint32Array.BYTES_PER_ELEMENT); // nextEntityId\n tracker.add(Uint32Array.BYTES_PER_ELEMENT); // removedEntitiesLength\n tracker.add(this._ECSConfig.maxEntities * Uint32Array.BYTES_PER_ELEMENT); // removedEntities\n tracker.add(this._ECSConfig.maxEntities * Uint32Array.BYTES_PER_ELEMENT); // entitiesComponentsMasks\n }\n}\n"],"names":["ENTITY_REMOVED_MASK","EntitiesManager","createEntity","prefab","entity","popRemovedEntities","undefined","_nextEntityId","_ECSConfig","maxEntities","Error","_entitiesComponentsMasks","ComponentConstructor","Values","componentInstance","_ComponentsMemory","get","ID","fieldName","value","Object","entries","unsafe","updateFilters","removeEntity","_removedEntities","_removedEntitiesLength","isEntityAlive","addComponent","removeComponent","hasComponent","hasPrefab","componentMask","_FiltersMemory","removeEntityFromAllFilters","updateEntityInAllFilters","init","arrayBuffer","tracker","Uint32Array","ptr","add","byteLength","fill","calculateSize","BYTES_PER_ELEMENT","constructor"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/mem/managers/entities-manager.ts"],"sourcesContent":["import { FiltersManager } from './filters-manager.js';\nimport { ComponentsManager } from './components-manager.js';\nimport { IAbstractMemory } from '../abstract-memory.interface.js';\nimport { ECSConfig } from '../../ecs-config.js';\nimport { Prefab } from '../../prefab.js';\nimport { IComponentConstructor } from '../../types/index.js';\nimport { MemoryTracker } from '@lagless/binary';\n\n/** Sentinel value indicating an entity slot is unused / removed. All mask words are set to 0xFFFFFFFF. */\nexport const ENTITY_REMOVED_MASK = 0xFFFFFFFF;\n\nexport class EntitiesManager implements IAbstractMemory {\n private _nextEntityId!: Uint32Array;\n private _removedEntitiesLength!: Uint32Array;\n private _removedEntities!: Uint32Array;\n private _entitiesComponentsMasks!: Uint32Array;\n\n constructor(\n private readonly _ECSConfig: ECSConfig,\n private readonly _ComponentsMemory: ComponentsManager,\n private readonly _FiltersMemory: FiltersManager,\n private readonly _maskWords: 1 | 2 = 1,\n ) {}\n\n public createEntity(prefab?: Prefab): number {\n let entity = this.popRemovedEntities();\n if (entity === undefined) {\n entity = this._nextEntityId[0];\n this._nextEntityId[0]++;\n }\n if (entity >= this._ECSConfig.maxEntities) {\n throw new Error(`Maximum number of entities (${this._ECSConfig.maxEntities}) exceeded`);\n }\n\n // Clear all mask words for the entity\n const base = entity * this._maskWords;\n for (let w = 0; w < this._maskWords; w++) {\n this._entitiesComponentsMasks[base + w] = 0;\n }\n\n if (prefab) {\n for (const [ ComponentConstructor, Values ] of prefab) {\n const bitIndex = ComponentConstructor.ID;\n const wordOffset = bitIndex >>> 5;\n const bit = 1 << (bitIndex & 31);\n this._entitiesComponentsMasks[base + wordOffset] |= bit;\n if (!Values) continue;\n const componentInstance = this._ComponentsMemory.get(ComponentConstructor);\n for (const [ fieldName, value ] of Object.entries(Values)) {\n if (value === undefined) continue;\n componentInstance.unsafe[fieldName as keyof typeof componentInstance.unsafe][entity] = value;\n }\n }\n }\n\n this.updateFilters(entity);\n\n return entity;\n }\n\n public removeEntity(entity: number): void {\n if (entity < 0 || entity >= this._ECSConfig.maxEntities) {\n throw new Error(`Entity ID ${entity} is out of bounds`);\n }\n\n const base = entity * this._maskWords;\n\n // Guard against double removal (all mask words must be sentinel)\n let isRemoved = true;\n for (let w = 0; w < this._maskWords; w++) {\n if (this._entitiesComponentsMasks[base + w] !== ENTITY_REMOVED_MASK) {\n isRemoved = false;\n break;\n }\n }\n if (isRemoved) return;\n\n // Set all mask words to sentinel\n for (let w = 0; w < this._maskWords; w++) {\n this._entitiesComponentsMasks[base + w] = ENTITY_REMOVED_MASK;\n }\n\n // Add the entity to the removed entities stack\n this._removedEntities[this._removedEntitiesLength[0]] = entity;\n this._removedEntitiesLength[0]++;\n\n this._FiltersMemory.removeEntityFromAllFilters(entity);\n }\n\n public isEntityAlive(entity: number): boolean {\n if (entity < 0 || entity >= this._ECSConfig.maxEntities) return false;\n const base = entity * this._maskWords;\n for (let w = 0; w < this._maskWords; w++) {\n if (this._entitiesComponentsMasks[base + w] !== ENTITY_REMOVED_MASK) return true;\n }\n return false;\n }\n\n public addComponent(entity: number, ComponentConstructor: IComponentConstructor): void {\n const bitIndex = ComponentConstructor.ID;\n const base = entity * this._maskWords;\n const wordOffset = bitIndex >>> 5;\n this._entitiesComponentsMasks[base + wordOffset] |= 1 << (bitIndex & 31);\n this.updateFilters(entity);\n }\n\n public removeComponent(entity: number, ComponentConstructor: IComponentConstructor): void {\n const bitIndex = ComponentConstructor.ID;\n const base = entity * this._maskWords;\n const wordOffset = bitIndex >>> 5;\n this._entitiesComponentsMasks[base + wordOffset] &= ~(1 << (bitIndex & 31));\n this.updateFilters(entity);\n }\n\n public hasComponent(entity: number, ComponentConstructor: IComponentConstructor): boolean {\n if (entity < 0 || entity >= this._ECSConfig.maxEntities) {\n throw new Error(`Entity ID ${entity} is out of bounds`);\n }\n const bitIndex = ComponentConstructor.ID;\n const base = entity * this._maskWords;\n const wordOffset = bitIndex >>> 5;\n return (this._entitiesComponentsMasks[base + wordOffset] & (1 << (bitIndex & 31))) !== 0;\n }\n\n public hasPrefab(entity: number, prefab: Prefab): boolean {\n const base = entity * this._maskWords;\n for (const [ ComponentConstructor ] of prefab) {\n const bitIndex = ComponentConstructor.ID;\n const wordOffset = bitIndex >>> 5;\n if ((this._entitiesComponentsMasks[base + wordOffset] & (1 << (bitIndex & 31))) === 0) {\n return false;\n }\n }\n\n return true;\n }\n\n private updateFilters(entity: number): void {\n const base = entity * this._maskWords;\n\n // Check if entity has any components set (all words zero means empty)\n let isEmpty = true;\n for (let w = 0; w < this._maskWords; w++) {\n if (this._entitiesComponentsMasks[base + w] !== 0) {\n isEmpty = false;\n break;\n }\n }\n\n if (isEmpty) {\n this._FiltersMemory.removeEntityFromAllFilters(entity);\n } else {\n this._FiltersMemory.updateEntityInAllFilters(entity, this._entitiesComponentsMasks, base, this._maskWords);\n }\n }\n\n private popRemovedEntities(): number | undefined {\n if (this._removedEntitiesLength[0] === 0) {\n return undefined;\n }\n\n const entity = this._removedEntities[this._removedEntitiesLength[0] - 1];\n this._removedEntitiesLength[0]--;\n\n return entity;\n }\n\n public init(arrayBuffer: ArrayBuffer, tracker: MemoryTracker): void {\n this._nextEntityId = new Uint32Array(arrayBuffer, tracker.ptr, 1);\n tracker.add(this._nextEntityId.byteLength);\n\n this._removedEntitiesLength = new Uint32Array(arrayBuffer, tracker.ptr, 1);\n tracker.add(this._removedEntitiesLength.byteLength);\n\n this._removedEntities = new Uint32Array(arrayBuffer, tracker.ptr, this._ECSConfig.maxEntities);\n tracker.add(this._removedEntities.byteLength);\n\n this._entitiesComponentsMasks = new Uint32Array(arrayBuffer, tracker.ptr, this._ECSConfig.maxEntities * this._maskWords);\n this._entitiesComponentsMasks.fill(ENTITY_REMOVED_MASK);\n tracker.add(this._entitiesComponentsMasks.byteLength);\n }\n\n public calculateSize(tracker: MemoryTracker): void {\n tracker.add(Uint32Array.BYTES_PER_ELEMENT); // nextEntityId\n tracker.add(Uint32Array.BYTES_PER_ELEMENT); // removedEntitiesLength\n tracker.add(this._ECSConfig.maxEntities * Uint32Array.BYTES_PER_ELEMENT); // removedEntities\n tracker.add(this._ECSConfig.maxEntities * this._maskWords * Uint32Array.BYTES_PER_ELEMENT); // entitiesComponentsMasks\n }\n}\n"],"names":["ENTITY_REMOVED_MASK","EntitiesManager","createEntity","prefab","entity","popRemovedEntities","undefined","_nextEntityId","_ECSConfig","maxEntities","Error","base","_maskWords","w","_entitiesComponentsMasks","ComponentConstructor","Values","bitIndex","ID","wordOffset","bit","componentInstance","_ComponentsMemory","get","fieldName","value","Object","entries","unsafe","updateFilters","removeEntity","isRemoved","_removedEntities","_removedEntitiesLength","_FiltersMemory","removeEntityFromAllFilters","isEntityAlive","addComponent","removeComponent","hasComponent","hasPrefab","isEmpty","updateEntityInAllFilters","init","arrayBuffer","tracker","Uint32Array","ptr","add","byteLength","fill","calculateSize","BYTES_PER_ELEMENT","constructor"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
@@ -6,12 +6,12 @@ export declare class FiltersManager implements IAbstractMemory {
|
|
|
6
6
|
private readonly _ECSConfig;
|
|
7
7
|
private readonly _ECSDeps;
|
|
8
8
|
private readonly _filtersInstances;
|
|
9
|
-
constructor(_ECSConfig: ECSConfig, _ECSDeps: ECSDeps);
|
|
9
|
+
constructor(_ECSConfig: ECSConfig, _ECSDeps: ECSDeps, _maskWords?: 1 | 2);
|
|
10
10
|
init(arrayBuffer: ArrayBuffer, tracker: MemoryTracker): void;
|
|
11
11
|
calculateSize(tracker: MemoryTracker): void;
|
|
12
12
|
get<FilterCtor extends IFilterConstructor>(FilterConstructor: FilterCtor): InstanceType<FilterCtor>;
|
|
13
13
|
[Symbol.iterator](): MapIterator<[IFilterConstructor, IFilterInstance]>;
|
|
14
14
|
removeEntityFromAllFilters(entity: number): void;
|
|
15
|
-
updateEntityInAllFilters(entity: number,
|
|
15
|
+
updateEntityInAllFilters(entity: number, masks: Uint32Array, maskBase: number, maskWords: number): void;
|
|
16
16
|
}
|
|
17
17
|
//# sourceMappingURL=filters-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters-manager.d.ts","sourceRoot":"","sources":["../../../../src/lib/mem/managers/filters-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,qBAAa,cAAe,YAAW,eAAe;
|
|
1
|
+
{"version":3,"file":"filters-manager.d.ts","sourceRoot":"","sources":["../../../../src/lib/mem/managers/filters-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,qBAAa,cAAe,YAAW,eAAe;IAIlD,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkD;gBAGjE,UAAU,EAAE,SAAS,EACrB,QAAQ,EAAE,OAAO,EAClC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC;IAGb,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAO5D,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAM3C,GAAG,CAAC,UAAU,SAAS,kBAAkB,EAAE,iBAAiB,EAAE,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC;IAQnG,CAAC,MAAM,CAAC,QAAQ,CAAC;IAIjB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMhD,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;CA2B/G"}
|
|
@@ -25,10 +25,25 @@ export class FiltersManager {
|
|
|
25
25
|
filterInstance.removeEntityFromFilter(entity);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
updateEntityInAllFilters(entity,
|
|
28
|
+
updateEntityInAllFilters(entity, masks, maskBase, maskWords) {
|
|
29
29
|
for (const filterInstance of this._filtersInstances.values()){
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
let includeOk = true;
|
|
31
|
+
let excludeOk = true;
|
|
32
|
+
for(let w = 0; w < maskWords; w++){
|
|
33
|
+
const entityMaskWord = masks[maskBase + w];
|
|
34
|
+
var _filterInstance_includeMask_w;
|
|
35
|
+
const incWord = (_filterInstance_includeMask_w = filterInstance.includeMask[w]) != null ? _filterInstance_includeMask_w : 0;
|
|
36
|
+
var _filterInstance_excludeMask_w;
|
|
37
|
+
const excWord = (_filterInstance_excludeMask_w = filterInstance.excludeMask[w]) != null ? _filterInstance_excludeMask_w : 0;
|
|
38
|
+
if (incWord && (entityMaskWord & incWord) >>> 0 !== incWord >>> 0) {
|
|
39
|
+
includeOk = false;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
if (excWord && (entityMaskWord & excWord) !== 0) {
|
|
43
|
+
excludeOk = false;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
32
47
|
if (includeOk && excludeOk) {
|
|
33
48
|
filterInstance.addEntityToFilter(entity);
|
|
34
49
|
} else {
|
|
@@ -36,7 +51,7 @@ export class FiltersManager {
|
|
|
36
51
|
}
|
|
37
52
|
}
|
|
38
53
|
}
|
|
39
|
-
constructor(_ECSConfig, _ECSDeps){
|
|
54
|
+
constructor(_ECSConfig, _ECSDeps, _maskWords){
|
|
40
55
|
this._ECSConfig = _ECSConfig;
|
|
41
56
|
this._ECSDeps = _ECSDeps;
|
|
42
57
|
this._filtersInstances = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/mem/managers/filters-manager.ts"],"sourcesContent":["import { ECSConfig } from '../../ecs-config.js';\nimport { IAbstractMemory } from '../abstract-memory.interface.js';\nimport { ECSDeps, IFilterConstructor, IFilterInstance } from '../../types/index.js';\nimport { MemoryTracker } from '@lagless/binary';\n\nexport class FiltersManager implements IAbstractMemory {\n private readonly _filtersInstances = new Map<IFilterConstructor, IFilterInstance>();\n\n constructor(private readonly _ECSConfig: ECSConfig
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/mem/managers/filters-manager.ts"],"sourcesContent":["import { ECSConfig } from '../../ecs-config.js';\nimport { IAbstractMemory } from '../abstract-memory.interface.js';\nimport { ECSDeps, IFilterConstructor, IFilterInstance } from '../../types/index.js';\nimport { MemoryTracker } from '@lagless/binary';\n\nexport class FiltersManager implements IAbstractMemory {\n private readonly _filtersInstances = new Map<IFilterConstructor, IFilterInstance>();\n\n constructor(\n private readonly _ECSConfig: ECSConfig,\n private readonly _ECSDeps: ECSDeps,\n _maskWords?: 1 | 2,\n ) {}\n\n public init(arrayBuffer: ArrayBuffer, tracker: MemoryTracker): void {\n for (const FilterConstructor of this._ECSDeps.filters) {\n const filterInstance = new FilterConstructor(this._ECSConfig.maxEntities, arrayBuffer, tracker);\n this._filtersInstances.set(FilterConstructor, filterInstance);\n }\n }\n\n public calculateSize(tracker: MemoryTracker): void {\n for (const FilterDefinition of this._ECSDeps.filters) {\n FilterDefinition.calculateSize(this._ECSConfig.maxEntities, tracker);\n }\n }\n\n public get<FilterCtor extends IFilterConstructor>(FilterConstructor: FilterCtor): InstanceType<FilterCtor> {\n const filterInstance = this._filtersInstances.get(FilterConstructor);\n if (!filterInstance) {\n throw new Error(`Filter ${FilterConstructor.name} not found`);\n }\n return filterInstance as InstanceType<FilterCtor>;\n }\n\n public [Symbol.iterator]() {\n return this._filtersInstances.entries();\n }\n\n public removeEntityFromAllFilters(entity: number): void {\n for (const filterInstance of this._filtersInstances.values()) {\n filterInstance.removeEntityFromFilter(entity);\n }\n }\n\n public updateEntityInAllFilters(entity: number, masks: Uint32Array, maskBase: number, maskWords: number): void {\n for (const filterInstance of this._filtersInstances.values()) {\n let includeOk = true;\n let excludeOk = true;\n\n for (let w = 0; w < maskWords; w++) {\n const entityMaskWord = masks[maskBase + w];\n const incWord = filterInstance.includeMask[w] ?? 0;\n const excWord = filterInstance.excludeMask[w] ?? 0;\n\n if (incWord && ((entityMaskWord & incWord) >>> 0) !== (incWord >>> 0)) {\n includeOk = false;\n break;\n }\n if (excWord && (entityMaskWord & excWord) !== 0) {\n excludeOk = false;\n break;\n }\n }\n\n if (includeOk && excludeOk) {\n filterInstance.addEntityToFilter(entity);\n } else {\n filterInstance.removeEntityFromFilter(entity);\n }\n }\n }\n}\n"],"names":["FiltersManager","init","arrayBuffer","tracker","FilterConstructor","_ECSDeps","filters","filterInstance","_ECSConfig","maxEntities","_filtersInstances","set","calculateSize","FilterDefinition","get","Error","name","Symbol","iterator","entries","removeEntityFromAllFilters","entity","values","removeEntityFromFilter","updateEntityInAllFilters","masks","maskBase","maskWords","includeOk","excludeOk","w","entityMaskWord","incWord","includeMask","excWord","excludeMask","addEntityToFilter","constructor","_maskWords","Map"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAKA,OAAO,MAAMA;IASJC,KAAKC,WAAwB,EAAEC,OAAsB,EAAQ;QAClE,KAAK,MAAMC,qBAAqB,IAAI,CAACC,QAAQ,CAACC,OAAO,CAAE;YACrD,MAAMC,iBAAiB,IAAIH,kBAAkB,IAAI,CAACI,UAAU,CAACC,WAAW,EAAEP,aAAaC;YACvF,IAAI,CAACO,iBAAiB,CAACC,GAAG,CAACP,mBAAmBG;QAChD;IACF;IAEOK,cAAcT,OAAsB,EAAQ;QACjD,KAAK,MAAMU,oBAAoB,IAAI,CAACR,QAAQ,CAACC,OAAO,CAAE;YACpDO,iBAAiBD,aAAa,CAAC,IAAI,CAACJ,UAAU,CAACC,WAAW,EAAEN;QAC9D;IACF;IAEOW,IAA2CV,iBAA6B,EAA4B;QACzG,MAAMG,iBAAiB,IAAI,CAACG,iBAAiB,CAACI,GAAG,CAACV;QAClD,IAAI,CAACG,gBAAgB;YACnB,MAAM,IAAIQ,MAAM,CAAC,OAAO,EAAEX,kBAAkBY,IAAI,CAAC,UAAU,CAAC;QAC9D;QACA,OAAOT;IACT;IAEO,CAACU,OAAOC,QAAQ,CAAC,GAAG;QACzB,OAAO,IAAI,CAACR,iBAAiB,CAACS,OAAO;IACvC;IAEOC,2BAA2BC,MAAc,EAAQ;QACtD,KAAK,MAAMd,kBAAkB,IAAI,CAACG,iBAAiB,CAACY,MAAM,GAAI;YAC5Df,eAAegB,sBAAsB,CAACF;QACxC;IACF;IAEOG,yBAAyBH,MAAc,EAAEI,KAAkB,EAAEC,QAAgB,EAAEC,SAAiB,EAAQ;QAC7G,KAAK,MAAMpB,kBAAkB,IAAI,CAACG,iBAAiB,CAACY,MAAM,GAAI;YAC5D,IAAIM,YAAY;YAChB,IAAIC,YAAY;YAEhB,IAAK,IAAIC,IAAI,GAAGA,IAAIH,WAAWG,IAAK;gBAClC,MAAMC,iBAAiBN,KAAK,CAACC,WAAWI,EAAE;oBAC1BvB;gBAAhB,MAAMyB,UAAUzB,CAAAA,gCAAAA,eAAe0B,WAAW,CAACH,EAAE,YAA7BvB,gCAAiC;oBACjCA;gBAAhB,MAAM2B,UAAU3B,CAAAA,gCAAAA,eAAe4B,WAAW,CAACL,EAAE,YAA7BvB,gCAAiC;gBAEjD,IAAIyB,WAAW,AAAED,CAAAA,iBAAiBC,OAAM,MAAO,MAAQA,YAAY,GAAI;oBACrEJ,YAAY;oBACZ;gBACF;gBACA,IAAIM,WAAW,AAACH,CAAAA,iBAAiBG,OAAM,MAAO,GAAG;oBAC/CL,YAAY;oBACZ;gBACF;YACF;YAEA,IAAID,aAAaC,WAAW;gBAC1BtB,eAAe6B,iBAAiB,CAACf;YACnC,OAAO;gBACLd,eAAegB,sBAAsB,CAACF;YACxC;QACF;IACF;IA/DAgB,YACE,AAAiB7B,UAAqB,EACtC,AAAiBH,QAAiB,EAClCiC,UAAkB,CAClB;aAHiB9B,aAAAA;aACAH,WAAAA;aAJFK,oBAAoB,IAAI6B;IAMtC;AA4DL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mem.d.ts","sourceRoot":"","sources":["../../../src/lib/mem/mem.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzD,qBAAa,GAAG;IAYF,OAAO,CAAC,QAAQ,CAAC,UAAU;IAAa,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX7E,SAAgB,WAAW,EAAE,WAAW,CAAC;IACzC,SAAgB,WAAW,EAAE,WAAW,CAAC;IACzC,SAAgB,iBAAiB,EAAE,iBAAiB,CAAC;IACrD,SAAgB,iBAAiB,EAAE,iBAAiB,CAAC;IACrD,SAAgB,cAAc,EAAE,cAAc,CAAC;IAC/C,SAAgB,eAAe,EAAE,eAAe,CAAC;IACjD,SAAgB,sBAAsB,EAAE,sBAAsB,CAAC;IAE/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;gBAE5B,UAAU,EAAE,SAAS,EAAmB,QAAQ,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"mem.d.ts","sourceRoot":"","sources":["../../../src/lib/mem/mem.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzD,qBAAa,GAAG;IAYF,OAAO,CAAC,QAAQ,CAAC,UAAU;IAAa,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX7E,SAAgB,WAAW,EAAE,WAAW,CAAC;IACzC,SAAgB,WAAW,EAAE,WAAW,CAAC;IACzC,SAAgB,iBAAiB,EAAE,iBAAiB,CAAC;IACrD,SAAgB,iBAAiB,EAAE,iBAAiB,CAAC;IACrD,SAAgB,cAAc,EAAE,cAAc,CAAC;IAC/C,SAAgB,eAAe,EAAE,eAAe,CAAC;IACjD,SAAgB,sBAAsB,EAAE,sBAAsB,CAAC;IAE/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;gBAE5B,UAAU,EAAE,SAAS,EAAmB,QAAQ,EAAE,OAAO;IAiC/E,cAAc,IAAI,WAAW;IAI7B,aAAa,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAQpD,OAAO,CAAC,aAAa;IAUd,OAAO,IAAI,MAAM;CAQzB"}
|
package/dist/lib/mem/mem.js
CHANGED
|
@@ -35,12 +35,14 @@ export class Mem {
|
|
|
35
35
|
constructor(_ECSConfig, _ECSDeps){
|
|
36
36
|
this._ECSConfig = _ECSConfig;
|
|
37
37
|
this._ECSDeps = _ECSDeps;
|
|
38
|
+
// Derive mask word count from component count (1 word for ≤32, 2 for 33-64)
|
|
39
|
+
const maskWords = Math.max(1, Math.ceil(this._ECSDeps.components.length / 32));
|
|
38
40
|
this.tickManager = new TickManager();
|
|
39
41
|
this.prngManager = new PRNGManager(this._ECSConfig);
|
|
40
42
|
this.componentsManager = new ComponentsManager(this._ECSConfig, this._ECSDeps);
|
|
41
43
|
this.singletonsManager = new SingletonsManager(this._ECSDeps);
|
|
42
|
-
this.filtersManager = new FiltersManager(this._ECSConfig, this._ECSDeps);
|
|
43
|
-
this.entitiesManager = new EntitiesManager(this._ECSConfig, this.componentsManager, this.filtersManager);
|
|
44
|
+
this.filtersManager = new FiltersManager(this._ECSConfig, this._ECSDeps, maskWords);
|
|
45
|
+
this.entitiesManager = new EntitiesManager(this._ECSConfig, this.componentsManager, this.filtersManager, maskWords);
|
|
44
46
|
this.playerResourcesManager = new PlayerResourcesManager(this._ECSConfig, this._ECSDeps);
|
|
45
47
|
this._memoryManagers = [
|
|
46
48
|
this.tickManager,
|
package/dist/lib/mem/mem.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/mem/mem.ts"],"sourcesContent":["// libs/core/src/lib/mem/mem.ts\nimport { ECSDeps } from '../types/index.js';\nimport { ECSConfig } from '../ecs-config.js';\nimport { IAbstractMemory } from './abstract-memory.interface.js';\nimport { ComponentsManager } from './managers/components-manager.js';\nimport { EntitiesManager } from './managers/entities-manager.js';\nimport { SingletonsManager } from './managers/singletons-manager.js';\nimport { FiltersManager } from './managers/filters-manager.js';\nimport { PlayerResourcesManager } from './managers/player-resources-manager.js';\nimport { TickManager } from './managers/tick-manager.js';\nimport { PRNGManager } from './managers/prng-manager.js';\nimport { MemoryTracker } from '@lagless/binary';\n\nexport class Mem {\n public readonly tickManager: TickManager;\n public readonly prngManager: PRNGManager;\n public readonly componentsManager: ComponentsManager;\n public readonly singletonsManager: SingletonsManager;\n public readonly filtersManager: FiltersManager;\n public readonly entitiesManager: EntitiesManager;\n public readonly playerResourcesManager: PlayerResourcesManager;\n\n private readonly _arrayBuffer: ArrayBuffer;\n private readonly _memoryManagers: Array<IAbstractMemory>;\n\n constructor(private readonly _ECSConfig: ECSConfig, private readonly _ECSDeps: ECSDeps) {\n this.tickManager = new TickManager();\n this.prngManager = new PRNGManager(this._ECSConfig);\n this.componentsManager = new ComponentsManager(this._ECSConfig, this._ECSDeps);\n this.singletonsManager = new SingletonsManager(this._ECSDeps);\n this.filtersManager = new FiltersManager(this._ECSConfig, this._ECSDeps);\n this.entitiesManager = new EntitiesManager(this._ECSConfig, this.componentsManager, this.filtersManager);\n this.playerResourcesManager = new PlayerResourcesManager(this._ECSConfig, this._ECSDeps);\n\n this._memoryManagers = [\n this.tickManager,\n this.prngManager,\n this.componentsManager,\n this.singletonsManager,\n this.filtersManager,\n this.entitiesManager,\n this.playerResourcesManager,\n ];\n\n const arrayBufferSize = this.calculateSize();\n\n this._arrayBuffer = new ArrayBuffer(arrayBufferSize);\n\n const tracker = new MemoryTracker();\n\n for (const memoryManager of this._memoryManagers) {\n memoryManager.init(this._arrayBuffer, tracker);\n }\n }\n\n public exportSnapshot(): ArrayBuffer {\n return this._arrayBuffer.slice(0);\n }\n\n public applySnapshot(arrayBuffer: ArrayBuffer): void {\n if (arrayBuffer.byteLength !== this._arrayBuffer.byteLength) {\n throw new Error('Snapshot size mismatch');\n }\n\n new Uint8Array(this._arrayBuffer).set(new Uint8Array(arrayBuffer));\n }\n\n private calculateSize(): number {\n const tracker = new MemoryTracker();\n\n for (const memoryManager of this._memoryManagers) {\n memoryManager.calculateSize(tracker);\n }\n\n return tracker.ptr;\n }\n\n public getHash(): number {\n let hash = 0;\n const dataView = new DataView(this._arrayBuffer);\n for (let i = 0; i < this._arrayBuffer.byteLength; i++) {\n hash = (hash * 31 + dataView.getUint8(i)) >>> 0;\n }\n return hash;\n }\n}\n"],"names":["ComponentsManager","EntitiesManager","SingletonsManager","FiltersManager","PlayerResourcesManager","TickManager","PRNGManager","MemoryTracker","Mem","exportSnapshot","_arrayBuffer","slice","applySnapshot","arrayBuffer","byteLength","Error","Uint8Array","set","calculateSize","tracker","memoryManager","_memoryManagers","ptr","getHash","hash","dataView","DataView","i","getUint8","constructor","_ECSConfig","_ECSDeps","tickManager","prngManager","componentsManager","singletonsManager","filtersManager","entitiesManager","playerResourcesManager","arrayBufferSize","ArrayBuffer","init"],"rangeMappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/mem/mem.ts"],"sourcesContent":["// libs/core/src/lib/mem/mem.ts\nimport { ECSDeps } from '../types/index.js';\nimport { ECSConfig } from '../ecs-config.js';\nimport { IAbstractMemory } from './abstract-memory.interface.js';\nimport { ComponentsManager } from './managers/components-manager.js';\nimport { EntitiesManager } from './managers/entities-manager.js';\nimport { SingletonsManager } from './managers/singletons-manager.js';\nimport { FiltersManager } from './managers/filters-manager.js';\nimport { PlayerResourcesManager } from './managers/player-resources-manager.js';\nimport { TickManager } from './managers/tick-manager.js';\nimport { PRNGManager } from './managers/prng-manager.js';\nimport { MemoryTracker } from '@lagless/binary';\n\nexport class Mem {\n public readonly tickManager: TickManager;\n public readonly prngManager: PRNGManager;\n public readonly componentsManager: ComponentsManager;\n public readonly singletonsManager: SingletonsManager;\n public readonly filtersManager: FiltersManager;\n public readonly entitiesManager: EntitiesManager;\n public readonly playerResourcesManager: PlayerResourcesManager;\n\n private readonly _arrayBuffer: ArrayBuffer;\n private readonly _memoryManagers: Array<IAbstractMemory>;\n\n constructor(private readonly _ECSConfig: ECSConfig, private readonly _ECSDeps: ECSDeps) {\n // Derive mask word count from component count (1 word for ≤32, 2 for 33-64)\n const maskWords = (Math.max(1, Math.ceil(this._ECSDeps.components.length / 32))) as 1 | 2;\n\n this.tickManager = new TickManager();\n this.prngManager = new PRNGManager(this._ECSConfig);\n this.componentsManager = new ComponentsManager(this._ECSConfig, this._ECSDeps);\n this.singletonsManager = new SingletonsManager(this._ECSDeps);\n this.filtersManager = new FiltersManager(this._ECSConfig, this._ECSDeps, maskWords);\n this.entitiesManager = new EntitiesManager(this._ECSConfig, this.componentsManager, this.filtersManager, maskWords);\n this.playerResourcesManager = new PlayerResourcesManager(this._ECSConfig, this._ECSDeps);\n\n this._memoryManagers = [\n this.tickManager,\n this.prngManager,\n this.componentsManager,\n this.singletonsManager,\n this.filtersManager,\n this.entitiesManager,\n this.playerResourcesManager,\n ];\n\n const arrayBufferSize = this.calculateSize();\n\n this._arrayBuffer = new ArrayBuffer(arrayBufferSize);\n\n const tracker = new MemoryTracker();\n\n for (const memoryManager of this._memoryManagers) {\n memoryManager.init(this._arrayBuffer, tracker);\n }\n }\n\n public exportSnapshot(): ArrayBuffer {\n return this._arrayBuffer.slice(0);\n }\n\n public applySnapshot(arrayBuffer: ArrayBuffer): void {\n if (arrayBuffer.byteLength !== this._arrayBuffer.byteLength) {\n throw new Error('Snapshot size mismatch');\n }\n\n new Uint8Array(this._arrayBuffer).set(new Uint8Array(arrayBuffer));\n }\n\n private calculateSize(): number {\n const tracker = new MemoryTracker();\n\n for (const memoryManager of this._memoryManagers) {\n memoryManager.calculateSize(tracker);\n }\n\n return tracker.ptr;\n }\n\n public getHash(): number {\n let hash = 0;\n const dataView = new DataView(this._arrayBuffer);\n for (let i = 0; i < this._arrayBuffer.byteLength; i++) {\n hash = (hash * 31 + dataView.getUint8(i)) >>> 0;\n }\n return hash;\n }\n}\n"],"names":["ComponentsManager","EntitiesManager","SingletonsManager","FiltersManager","PlayerResourcesManager","TickManager","PRNGManager","MemoryTracker","Mem","exportSnapshot","_arrayBuffer","slice","applySnapshot","arrayBuffer","byteLength","Error","Uint8Array","set","calculateSize","tracker","memoryManager","_memoryManagers","ptr","getHash","hash","dataView","DataView","i","getUint8","constructor","_ECSConfig","_ECSDeps","maskWords","Math","max","ceil","components","length","tickManager","prngManager","componentsManager","singletonsManager","filtersManager","entitiesManager","playerResourcesManager","arrayBufferSize","ArrayBuffer","init"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,+BAA+B;AAI/B,SAASA,iBAAiB,QAAQ,mCAAmC;AACrE,SAASC,eAAe,QAAQ,iCAAiC;AACjE,SAASC,iBAAiB,QAAQ,mCAAmC;AACrE,SAASC,cAAc,QAAQ,gCAAgC;AAC/D,SAASC,sBAAsB,QAAQ,yCAAyC;AAChF,SAASC,WAAW,QAAQ,6BAA6B;AACzD,SAASC,WAAW,QAAQ,6BAA6B;AACzD,SAASC,aAAa,QAAQ,kBAAkB;AAEhD,OAAO,MAAMC;IA6CJC,iBAA8B;QACnC,OAAO,IAAI,CAACC,YAAY,CAACC,KAAK,CAAC;IACjC;IAEOC,cAAcC,WAAwB,EAAQ;QACnD,IAAIA,YAAYC,UAAU,KAAK,IAAI,CAACJ,YAAY,CAACI,UAAU,EAAE;YAC3D,MAAM,IAAIC,MAAM;QAClB;QAEA,IAAIC,WAAW,IAAI,CAACN,YAAY,EAAEO,GAAG,CAAC,IAAID,WAAWH;IACvD;IAEQK,gBAAwB;QAC9B,MAAMC,UAAU,IAAIZ;QAEpB,KAAK,MAAMa,iBAAiB,IAAI,CAACC,eAAe,CAAE;YAChDD,cAAcF,aAAa,CAACC;QAC9B;QAEA,OAAOA,QAAQG,GAAG;IACpB;IAEOC,UAAkB;QACvB,IAAIC,OAAO;QACX,MAAMC,WAAW,IAAIC,SAAS,IAAI,CAAChB,YAAY;QAC/C,IAAK,IAAIiB,IAAI,GAAGA,IAAI,IAAI,CAACjB,YAAY,CAACI,UAAU,EAAEa,IAAK;YACrDH,OAAO,AAACA,OAAO,KAAKC,SAASG,QAAQ,CAACD,OAAQ;QAChD;QACA,OAAOH;IACT;IA9DAK,YAAY,AAAiBC,UAAqB,EAAE,AAAiBC,QAAiB,CAAE;aAA3DD,aAAAA;aAAwCC,WAAAA;QACnE,4EAA4E;QAC5E,MAAMC,YAAaC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,IAAI,CAAC,IAAI,CAACJ,QAAQ,CAACK,UAAU,CAACC,MAAM,GAAG;QAE3E,IAAI,CAACC,WAAW,GAAG,IAAIjC;QACvB,IAAI,CAACkC,WAAW,GAAG,IAAIjC,YAAY,IAAI,CAACwB,UAAU;QAClD,IAAI,CAACU,iBAAiB,GAAG,IAAIxC,kBAAkB,IAAI,CAAC8B,UAAU,EAAE,IAAI,CAACC,QAAQ;QAC7E,IAAI,CAACU,iBAAiB,GAAG,IAAIvC,kBAAkB,IAAI,CAAC6B,QAAQ;QAC5D,IAAI,CAACW,cAAc,GAAG,IAAIvC,eAAe,IAAI,CAAC2B,UAAU,EAAE,IAAI,CAACC,QAAQ,EAAEC;QACzE,IAAI,CAACW,eAAe,GAAG,IAAI1C,gBAAgB,IAAI,CAAC6B,UAAU,EAAE,IAAI,CAACU,iBAAiB,EAAE,IAAI,CAACE,cAAc,EAAEV;QACzG,IAAI,CAACY,sBAAsB,GAAG,IAAIxC,uBAAuB,IAAI,CAAC0B,UAAU,EAAE,IAAI,CAACC,QAAQ;QAEvF,IAAI,CAACV,eAAe,GAAG;YACrB,IAAI,CAACiB,WAAW;YAChB,IAAI,CAACC,WAAW;YAChB,IAAI,CAACC,iBAAiB;YACtB,IAAI,CAACC,iBAAiB;YACtB,IAAI,CAACC,cAAc;YACnB,IAAI,CAACC,eAAe;YACpB,IAAI,CAACC,sBAAsB;SAC5B;QAED,MAAMC,kBAAkB,IAAI,CAAC3B,aAAa;QAE1C,IAAI,CAACR,YAAY,GAAG,IAAIoC,YAAYD;QAEpC,MAAM1B,UAAU,IAAIZ;QAEpB,KAAK,MAAMa,iBAAiB,IAAI,CAACC,eAAe,CAAE;YAChDD,cAAc2B,IAAI,CAAC,IAAI,CAACrC,YAAY,EAAES;QACxC;IACF;AAgCF"}
|
|
@@ -14,14 +14,15 @@ export declare abstract class Signal<TData = unknown> {
|
|
|
14
14
|
readonly Cancelled: EventEmitter<SignalEvent<TData>>;
|
|
15
15
|
private readonly _pending;
|
|
16
16
|
private readonly _awaitingVerification;
|
|
17
|
-
private
|
|
17
|
+
private _lastVerifiedTick;
|
|
18
18
|
constructor(_ECSConfig: ECSConfig);
|
|
19
19
|
emit(tick: number, data: TData): void;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Verify/cancel signals for ticks up to verifiedTick.
|
|
22
|
+
* Called each simulation tick from SignalsRegistry.
|
|
22
23
|
* @internal
|
|
23
24
|
*/
|
|
24
|
-
_onTick(
|
|
25
|
+
_onTick(verifiedTick: number): void;
|
|
25
26
|
/**
|
|
26
27
|
* Перед rollback — очищаем pending для тиков которые будут пересимулированы
|
|
27
28
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../../src/lib/signals/signal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,MAAM,WAAW,WAAW,CAAC,KAAK;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IAEjC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;CACnC;AAED,8BACsB,MAAM,CAAC,KAAK,GAAG,OAAO;IAS9B,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,SAAS;IARpD,SAAgB,SAAS,mCAA0C;IACnE,SAAgB,QAAQ,mCAA0C;IAClE,SAAgB,SAAS,mCAA0C;IAEnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA8B;IACpE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../../src/lib/signals/signal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,MAAM,WAAW,WAAW,CAAC,KAAK;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IAEjC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;CACnC;AAED,8BACsB,MAAM,CAAC,KAAK,GAAG,OAAO;IAS9B,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,SAAS;IARpD,SAAgB,SAAS,mCAA0C;IACnE,SAAgB,QAAQ,mCAA0C;IAClE,SAAgB,SAAS,mCAA0C;IAEnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA8B;IACpE,OAAO,CAAC,iBAAiB,CAAM;gBAEA,UAAU,EAAE,SAAS;IAE7C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI;IA4B5C;;;;OAIG;IACI,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAgC1C;;;OAGG;IACI,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAS9C;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,OAAO;IAoB3C,OAAO,IAAI,IAAI;CAQvB"}
|
|
@@ -32,43 +32,42 @@ export class Signal {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Verify/cancel signals for ticks up to verifiedTick.
|
|
36
|
+
* Called each simulation tick from SignalsRegistry.
|
|
36
37
|
* @internal
|
|
37
|
-
*/ _onTick(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
matchIdx
|
|
54
|
-
|
|
38
|
+
*/ _onTick(verifiedTick) {
|
|
39
|
+
while(this._lastVerifiedTick < verifiedTick){
|
|
40
|
+
const nextTick = this._lastVerifiedTick + 1;
|
|
41
|
+
const awaiting = this._awaitingVerification.get(nextTick);
|
|
42
|
+
if (awaiting && awaiting.length > 0) {
|
|
43
|
+
var _this__pending_get;
|
|
44
|
+
const pending = (_this__pending_get = this._pending.get(nextTick)) != null ? _this__pending_get : [];
|
|
45
|
+
const pendingMatched = new Array(pending.length).fill(false);
|
|
46
|
+
for (const awaitingData of awaiting){
|
|
47
|
+
let matchIdx = -1;
|
|
48
|
+
for(let i = 0; i < pending.length; i++){
|
|
49
|
+
if (!pendingMatched[i] && this._dataEquals(pending[i], awaitingData)) {
|
|
50
|
+
matchIdx = i;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (matchIdx >= 0) {
|
|
55
|
+
pendingMatched[matchIdx] = true;
|
|
56
|
+
this.Verified.emit({
|
|
57
|
+
tick: nextTick,
|
|
58
|
+
data: awaitingData
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
this.Cancelled.emit({
|
|
62
|
+
tick: nextTick,
|
|
63
|
+
data: awaitingData
|
|
64
|
+
});
|
|
65
|
+
}
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.Verified.emit({
|
|
60
|
-
tick: verifyTick,
|
|
61
|
-
data: awaitingData
|
|
62
|
-
});
|
|
63
|
-
} else {
|
|
64
|
-
// Событие было Predicted, но нет в pending после rollback
|
|
65
|
-
this.Cancelled.emit({
|
|
66
|
-
tick: verifyTick,
|
|
67
|
-
data: awaitingData
|
|
68
|
-
});
|
|
69
|
-
}
|
|
68
|
+
this._cleanupTick(nextTick);
|
|
69
|
+
this._lastVerifiedTick = nextTick;
|
|
70
70
|
}
|
|
71
|
-
this._cleanupTick(verifyTick);
|
|
72
71
|
}
|
|
73
72
|
/**
|
|
74
73
|
* Перед rollback — очищаем pending для тиков которые будут пересимулированы
|
|
@@ -108,6 +107,7 @@ export class Signal {
|
|
|
108
107
|
dispose() {
|
|
109
108
|
this._pending.clear();
|
|
110
109
|
this._awaitingVerification.clear();
|
|
110
|
+
this._lastVerifiedTick = -1;
|
|
111
111
|
this.Predicted.clear();
|
|
112
112
|
this.Verified.clear();
|
|
113
113
|
this.Cancelled.clear();
|
|
@@ -119,7 +119,7 @@ export class Signal {
|
|
|
119
119
|
this.Cancelled = new EventEmitter();
|
|
120
120
|
this._pending = new Map();
|
|
121
121
|
this._awaitingVerification = new Map();
|
|
122
|
-
this.
|
|
122
|
+
this._lastVerifiedTick = -1;
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
Signal = _ts_decorate([
|