diff --git a/packages/recs/src/Component.ts b/packages/recs/src/Component.ts index d65796c091..bd4ba16b8e 100644 --- a/packages/recs/src/Component.ts +++ b/packages/recs/src/Component.ts @@ -145,7 +145,7 @@ export function overridableComponent(component: Component): const overrides = new Map; nonce: number }>(); // Map from EntityIndex to current overridden component value - const overriddenEntityValues = new Map>>(); + const overriddenEntityValues = new Map> | null>(); // Update event stream that takes into account overridden entity values const update$ = new Subject<{ @@ -188,7 +188,7 @@ export function overridableComponent(component: Component): function getOverriddenComponentValue(entity: EntityIndex): ComponentValue | undefined { const originalValue = getComponentValue(component, entity); const overriddenValue = overriddenEntityValues.get(entity); - return originalValue || overriddenValue + return (originalValue || overriddenValue) && overriddenValue !== null // null is a valid override, in this case return undefined ? ({ ...originalValue, ...overriddenValue } as ComponentValue) : undefined; } @@ -241,9 +241,10 @@ export function overridableComponent(component: Component): }) as OverridableComponent; // Internal function to set the current overridden component value and emit the update event - function setOverriddenComponentValue(entity: EntityIndex, value?: Partial>) { + function setOverriddenComponentValue(entity: EntityIndex, value?: Partial> | null) { + // Check specifically for undefined - null is a valid override const prevValue = getOverriddenComponentValue(entity); - if (value) overriddenEntityValues.set(entity, value); + if (value !== undefined) overriddenEntityValues.set(entity, value); else overriddenEntityValues.delete(entity); update$.next({ entity, value: [getOverriddenComponentValue(entity), prevValue], component: overriddenComponent }); } diff --git a/packages/recs/src/World.ts b/packages/recs/src/World.ts index dda390f10a..83149ea138 100644 --- a/packages/recs/src/World.ts +++ b/packages/recs/src/World.ts @@ -15,7 +15,13 @@ export function createWorld() { function registerEntity({ id, idSuffix }: { id?: EntityID; idSuffix?: string } = {}) { const entity = (id || entities.length + (idSuffix ? "-" + idSuffix : "")) as EntityID; - const index = (entities.push(entity) - 1) as EntityIndex; + + // Skip if entity already exists + let index = entityToIndex.get(entity); + if (index != null) return index; + + // Register entity + index = (entities.push(entity) - 1) as EntityIndex; entityToIndex.set(entity, index); return index; } diff --git a/packages/recs/src/types.ts b/packages/recs/src/types.ts index b33087800e..be102c7060 100644 --- a/packages/recs/src/types.ts +++ b/packages/recs/src/types.ts @@ -150,7 +150,7 @@ export type SchemaOf> = C extends Component export type Override = { entity: EntityIndex; - value: Partial>; + value: Partial> | null; }; export type OverridableComponent = Component & { diff --git a/packages/recs/tests/System.spec.ts b/packages/recs/tests/System.spec.ts index b7f80f5f30..9586098914 100644 --- a/packages/recs/tests/System.spec.ts +++ b/packages/recs/tests/System.spec.ts @@ -22,7 +22,7 @@ describe("System", () => { entity = createEntity(world, [withValue(Position, { x: 1, y: 2 })]); }); - it("defineSystem should rerun the system if the query result changes (enter, update, exit)", () => { + it.only("defineSystem should rerun the system if the query result changes (enter, update, exit)", () => { const mock = jest.fn(); defineSystem(world, [Has(Position)], mock);