refactor: split WorldEvent into EntityEvent and RelEvent

This commit is contained in:
hypercross 2026-05-31 16:31:27 +08:00
parent 05674a349f
commit 81efb6cb0a
3 changed files with 29 additions and 13 deletions

View File

@ -11,6 +11,8 @@ export { makeEntity, entityIndex, entityGeneration } from "./entity";
export { SparseSet } from "./storage/sparse-set"; export { SparseSet } from "./storage/sparse-set";
export type { export type {
WorldEvent, WorldEvent,
EntityEvent,
RelEvent,
QueryUpdate, QueryUpdate,
RelationshipUpdate, RelationshipUpdate,
} from "./observable/events"; } from "./observable/events";

View File

@ -4,17 +4,25 @@ import type { Entity } from "../entity";
// ── World Events ────────────────────────────────────── // ── World Events ──────────────────────────────────────
/** /**
* Discriminated union of all world-level events. * Events that carry an `entity` field component and lifecycle events.
* Emitted via `world.events$`.
*/ */
export type WorldEvent = export type EntityEvent =
| SpawnedEvent | SpawnedEvent
| DestroyedEvent | DestroyedEvent
| ComponentAddedEvent | ComponentAddedEvent
| ComponentRemovedEvent | ComponentRemovedEvent
| ComponentChangedEvent | ComponentChangedEvent;
| RelAddedEvent
| RelRemovedEvent; /**
* Events that carry `source`/`target` fields relationship events.
*/
export type RelEvent = RelAddedEvent | RelRemovedEvent;
/**
* Discriminated union of all world-level events.
* Emitted via `world.events$`.
*/
export type WorldEvent = EntityEvent | RelEvent;
export interface SpawnedEvent { export interface SpawnedEvent {
type: "spawned"; type: "spawned";

View File

@ -1,7 +1,12 @@
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import type { Query } from "../query"; import type { Query } from "../query";
import type { Entity } from "../entity"; import type { Entity } from "../entity";
import type { WorldEvent, QueryUpdate, RelationshipUpdate } from "./events"; import type {
WorldEvent,
EntityEvent,
QueryUpdate,
RelationshipUpdate,
} from "./events";
import type { RelationshipDef } from "../relationship"; import type { RelationshipDef } from "../relationship";
import type { ComponentDef } from "../component"; import type { ComponentDef } from "../component";
@ -143,21 +148,21 @@ export class ObservableLayer {
queryMatches: (query: Query, e: Entity) => boolean, queryMatches: (query: Query, e: Entity) => boolean,
): void { ): void {
if (!("entity" in event)) return; if (!("entity" in event)) return;
const entityEvent = event as EntityEvent;
// Determine which component keys are relevant // Determine which component keys are relevant
let keys: symbol[] = []; let keys: symbol[] = [];
switch (event.type) { switch (entityEvent.type) {
case "spawned": case "spawned":
case "destroyed": case "destroyed":
// Check all observers (via the ANY_KEY set)
keys = [ANY_KEY]; keys = [ANY_KEY];
break; break;
case "componentAdded": case "componentAdded":
case "componentRemoved": case "componentRemoved":
case "componentChanged": case "componentChanged":
keys = [event.component._key]; keys = [entityEvent.component._key];
break; break;
} }
@ -169,7 +174,8 @@ export class ObservableLayer {
for (const o of set) { for (const o of set) {
if (!seen.has(o)) { if (!seen.has(o)) {
seen.add(o); seen.add(o);
this._updateObserver(o, event, queryMatches); // event is entity-bearing after the in-guard above
this._updateObserver(o, entityEvent, queryMatches);
} }
} }
} }
@ -179,10 +185,10 @@ export class ObservableLayer {
private _updateObserver( private _updateObserver(
obs: QueryObserverState, obs: QueryObserverState,
event: WorldEvent, event: EntityEvent,
queryMatches: (query: Query, e: Entity) => boolean, queryMatches: (query: Query, e: Entity) => boolean,
): void { ): void {
const e = event.entity!; const e = event.entity;
const wasMatched = obs.matched.has(e); const wasMatched = obs.matched.has(e);
const nowMatches = queryMatches(obs.query, e); const nowMatches = queryMatches(obs.query, e);