Skip to content

Commit 0b0a42a

Browse files
committed
refactor(entity): replace createRelationId with relation function
- Updated the entity and related test files to use the new `relation` function instead of `createRelationId` for creating relation IDs. - This change improves code clarity and consistency across the codebase.
1 parent 9bbb6e7 commit 0b0a42a

8 files changed

Lines changed: 71 additions & 75 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ world.flushCommands(); // 钩子在这里被调用
8585
ECS 还支持通配符关系生命周期钩子,可以监听特定组件的所有关系变化:
8686

8787
```typescript
88-
import { World, createComponentId, createRelationId } from "@codehz/ecs";
88+
import { World, createComponentId, relation } from "@codehz/ecs";
8989

9090
// 定义组件类型
9191
type Position = { x: number; y: number };
@@ -100,7 +100,7 @@ const world = new World();
100100
const entity = world.createEntity();
101101

102102
// 创建通配符关系ID,用于监听所有 Position 相关的关系
103-
const wildcardPositionRelation = createRelationId(PositionId, "*");
103+
const wildcardPositionRelation = relation(PositionId, "*");
104104

105105
// 注册通配符关系钩子
106106
world.registerLifecycleHook(wildcardPositionRelation, {
@@ -114,7 +114,7 @@ world.registerLifecycleHook(wildcardPositionRelation, {
114114

115115
// 创建实体间的关系
116116
const entity2 = world.createEntity();
117-
const positionRelation = createRelationId(PositionId, entity2);
117+
const positionRelation = relation(PositionId, entity2);
118118
world.addComponent(entity, positionRelation, { x: 10, y: 20 });
119119
world.flushCommands(); // 通配符钩子会被触发
120120
```

src/archetype.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from "bun:test";
2-
import { Archetype, createComponentId, createEntityId, createRelationId, type EntityId } from "./index";
2+
import { Archetype, createComponentId, createEntityId, relation, type EntityId } from "./index";
33

44
describe("Archetype", () => {
55
type Position = { x: number; y: number };
@@ -70,9 +70,9 @@ describe("Archetype", () => {
7070
// Create relation component types
7171
const target1 = createEntityId(1027);
7272
const target2 = createEntityId(1028);
73-
const relation1 = createRelationId(positionComponent, target1);
74-
const relation2 = createRelationId(positionComponent, target2);
75-
const wildcardPositionRelation = createRelationId(positionComponent, "*");
73+
const relation1 = relation(positionComponent, target1);
74+
const relation2 = relation(positionComponent, target2);
75+
const wildcardPositionRelation = relation(positionComponent, "*");
7676

7777
const entity = createEntityId(1024);
7878

@@ -133,18 +133,18 @@ describe("Archetype", () => {
133133

134134
it("should handle wildcard relations in forEachWithComponents", () => {
135135
// Create a relation component type: position relation from entity to entity
136-
const positionRelation = createRelationId(positionComponent, createEntityId(1026)); // Dummy target for type
137-
const wildcardPositionRelation = createRelationId(positionComponent, "*");
136+
const positionRelation = relation(positionComponent, createEntityId(1026)); // Dummy target for type
137+
const wildcardPositionRelation = relation(positionComponent, "*");
138138

139139
const entity1 = createEntityId(1024);
140140
const entity2 = createEntityId(1025);
141141
const target1 = createEntityId(1027);
142142
const target2 = createEntityId(1028);
143143

144144
// Create specific relations for entity1 and entity2
145-
const relation1 = createRelationId(positionComponent, target1);
146-
const relation2 = createRelationId(positionComponent, target2);
147-
const relation3 = createRelationId(positionComponent, createEntityId(1029)); // For entity2
145+
const relation1 = relation(positionComponent, target1);
146+
const relation2 = relation(positionComponent, target2);
147+
const relation3 = relation(positionComponent, createEntityId(1029)); // For entity2
148148

149149
// Archetype with multiple relations
150150
const archetype1 = new Archetype([relation1, relation2]);
@@ -190,9 +190,9 @@ describe("Archetype", () => {
190190
// Test with wildcard relations to check cache invalidation
191191
const target1 = createEntityId(1027);
192192
const target2 = createEntityId(1028);
193-
const relation1 = createRelationId(positionComponent, target1);
194-
const relation2 = createRelationId(positionComponent, target2);
195-
const wildcardPositionRelation = createRelationId(positionComponent, "*");
193+
const relation1 = relation(positionComponent, target1);
194+
const relation2 = relation(positionComponent, target2);
195+
const wildcardPositionRelation = relation(positionComponent, "*");
196196

197197
const archetype = new Archetype([relation1, relation2]);
198198

src/entity.test.ts

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
ComponentIdManager,
66
createComponentId,
77
createEntityId,
8-
createRelationId,
8+
relation,
99
decodeRelationId,
1010
ENTITY_ID_START,
1111
EntityIdManager,
@@ -38,7 +38,7 @@ describe("Entity ID System", () => {
3838
expect(isComponentId(createComponentId(2))).toBe(true);
3939
expect(isComponentId(createComponentId(COMPONENT_ID_MAX))).toBe(true);
4040
expect(isComponentId(createEntityId(ENTITY_ID_START))).toBe(false);
41-
expect(isComponentId(createRelationId(createComponentId(1), createEntityId(ENTITY_ID_START)))).toBe(false);
41+
expect(isComponentId(relation(createComponentId(1), createEntityId(ENTITY_ID_START)))).toBe(false);
4242
});
4343
});
4444

@@ -58,15 +58,15 @@ describe("Entity ID System", () => {
5858
expect(isEntityId(createEntityId(ENTITY_ID_START))).toBe(true);
5959
expect(isEntityId(createEntityId(10000))).toBe(true);
6060
expect(isEntityId(createComponentId(1))).toBe(false);
61-
expect(isEntityId(createRelationId(createComponentId(1), createEntityId(ENTITY_ID_START)))).toBe(false);
61+
expect(isEntityId(relation(createComponentId(1), createEntityId(ENTITY_ID_START)))).toBe(false);
6262
});
6363
});
6464

6565
describe("Relation IDs", () => {
6666
it("should create valid relation IDs with entities", () => {
6767
const compId = createComponentId(5);
6868
const entId = createEntityId(ENTITY_ID_START + 10);
69-
const relationId = createRelationId(compId, entId);
69+
const relationId = relation(compId, entId);
7070

7171
expect(relationId).toBeLessThan(0);
7272
expect(isRelationId(relationId)).toBe(true);
@@ -75,25 +75,23 @@ describe("Entity ID System", () => {
7575
it("should create valid relation IDs with components", () => {
7676
const compId1 = createComponentId(5);
7777
const compId2 = createComponentId(10);
78-
const relationId = createRelationId(compId1, compId2);
78+
const relationId = relation(compId1, compId2);
7979

8080
expect(relationId).toBeLessThan(0);
8181
expect(isRelationId(relationId)).toBe(true);
8282
});
8383

8484
it("should reject invalid relation creation", () => {
8585
const entId = createEntityId(ENTITY_ID_START);
86-
expect(() => createRelationId(1024 as EntityId, entId)).toThrow(); // invalid component id
87-
expect(() => createRelationId(createComponentId(5), -1 as EntityId)).toThrow(); // invalid target id
88-
expect(() =>
89-
createRelationId(createComponentId(5), createRelationId(createComponentId(1), createEntityId(1025))),
90-
).toThrow(); // relation as target
86+
expect(() => relation(1024 as EntityId, entId)).toThrow(); // invalid component id
87+
expect(() => relation(createComponentId(5), -1 as EntityId)).toThrow(); // invalid target id
88+
expect(() => relation(createComponentId(5), relation(createComponentId(1), createEntityId(1025)))).toThrow(); // relation as target
9189
});
9290

9391
it("should decode relation IDs with entities correctly", () => {
9492
const compId = createComponentId(42);
9593
const entId = createEntityId(ENTITY_ID_START + 123);
96-
const relationId = createRelationId(compId, entId);
94+
const relationId = relation(compId, entId);
9795

9896
const decoded = decodeRelationId(relationId);
9997
expect(decoded.componentId).toBe(compId);
@@ -104,7 +102,7 @@ describe("Entity ID System", () => {
104102
it("should decode relation IDs with components correctly", () => {
105103
const compId1 = createComponentId(42);
106104
const compId2 = createComponentId(100);
107-
const relationId = createRelationId(compId1, compId2);
105+
const relationId = relation(compId1, compId2);
108106

109107
const decoded = decodeRelationId(relationId);
110108
expect(decoded.componentId).toBe(compId1);
@@ -114,17 +112,17 @@ describe("Entity ID System", () => {
114112

115113
it("should create valid wildcard relation IDs", () => {
116114
const compId = createComponentId(5);
117-
const relationId = createRelationId(compId, "*");
115+
const relationId = relation(compId, "*");
118116

119117
expect(relationId).toBeLessThan(0);
120118
expect(isRelationId(relationId)).toBe(true);
121119
});
122120

123121
it("should identify wildcard relation IDs correctly", () => {
124122
const compId = createComponentId(5);
125-
const wildcardRelationId = createRelationId(compId, "*");
126-
const entityRelationId = createRelationId(compId, createEntityId(ENTITY_ID_START));
127-
const componentRelationId = createRelationId(compId, createComponentId(10));
123+
const wildcardRelationId = relation(compId, "*");
124+
const entityRelationId = relation(compId, createEntityId(ENTITY_ID_START));
125+
const componentRelationId = relation(compId, createComponentId(10));
128126
const entityId = createEntityId(ENTITY_ID_START);
129127
const componentId = createComponentId(1);
130128

@@ -137,7 +135,7 @@ describe("Entity ID System", () => {
137135

138136
it("should decode wildcard relation IDs correctly", () => {
139137
const compId = createComponentId(42);
140-
const relationId = createRelationId(compId, "*");
138+
const relationId = relation(compId, "*");
141139

142140
const decoded = decodeRelationId(relationId);
143141
expect(decoded.componentId).toBe(compId);
@@ -152,11 +150,9 @@ describe("Entity ID System", () => {
152150
expect(getIdType(createComponentId(500))).toBe("component");
153151
expect(getIdType(createEntityId(ENTITY_ID_START))).toBe("entity");
154152
expect(getIdType(createEntityId(10000))).toBe("entity");
155-
expect(getIdType(createRelationId(createComponentId(1), createEntityId(ENTITY_ID_START)))).toBe(
156-
"entity-relation",
157-
);
158-
expect(getIdType(createRelationId(createComponentId(1), createComponentId(2)))).toBe("component-relation");
159-
expect(getIdType(createRelationId(createComponentId(1), "*"))).toBe("wildcard-relation");
153+
expect(getIdType(relation(createComponentId(1), createEntityId(ENTITY_ID_START)))).toBe("entity-relation");
154+
expect(getIdType(relation(createComponentId(1), createComponentId(2)))).toBe("component-relation");
155+
expect(getIdType(relation(createComponentId(1), "*"))).toBe("wildcard-relation");
160156

161157
// Invalid IDs
162158
expect(getIdType(INVALID_COMPONENT_ID as EntityId)).toBe("invalid");
@@ -177,21 +173,21 @@ describe("Entity ID System", () => {
177173
expect(entityResult.targetId).toBeUndefined();
178174

179175
// Entity relation
180-
const entityRelationId = createRelationId(createComponentId(5), createEntityId(ENTITY_ID_START + 200));
176+
const entityRelationId = relation(createComponentId(5), createEntityId(ENTITY_ID_START + 200));
181177
const entityRelationResult = getDetailedIdType(entityRelationId);
182178
expect(entityRelationResult.type).toBe("entity-relation");
183179
expect(entityRelationResult.componentId).toBe(createComponentId(5));
184180
expect(entityRelationResult.targetId).toBe(createEntityId(ENTITY_ID_START + 200));
185181

186182
// Component relation
187-
const compRelationId = createRelationId(createComponentId(10), createComponentId(20));
183+
const compRelationId = relation(createComponentId(10), createComponentId(20));
188184
const compRelationResult = getDetailedIdType(compRelationId);
189185
expect(compRelationResult.type).toBe("component-relation");
190186
expect(compRelationResult.componentId).toBe(createComponentId(10));
191187
expect(compRelationResult.targetId).toBe(createComponentId(20));
192188

193189
// Wildcard relation
194-
const wildcardRelationId = createRelationId(createComponentId(15), "*");
190+
const wildcardRelationId = relation(createComponentId(15), "*");
195191
const wildcardRelationResult = getDetailedIdType(wildcardRelationId);
196192
expect(wildcardRelationResult.type).toBe("wildcard-relation");
197193
expect(wildcardRelationResult.componentId).toBe(createComponentId(15));
@@ -229,15 +225,15 @@ describe("Entity ID System", () => {
229225
it("should inspect relation IDs with entities", () => {
230226
const compId = createComponentId(5);
231227
const entId = createEntityId(ENTITY_ID_START + 10);
232-
const relationId = createRelationId(compId, entId);
228+
const relationId = relation(compId, entId);
233229

234230
expect(inspectEntityId(relationId)).toBe("Relation ID: Component ID (5) -> Entity ID (1034)");
235231
});
236232

237233
it("should inspect relation IDs with components", () => {
238234
const compId1 = createComponentId(10);
239235
const compId2 = createComponentId(20);
240-
const relationId = createRelationId(compId1, compId2);
236+
const relationId = relation(compId1, compId2);
241237

242238
expect(inspectEntityId(relationId)).toBe("Relation ID: Component ID (10) -> Component ID (20)");
243239
});
@@ -250,7 +246,7 @@ describe("Entity ID System", () => {
250246

251247
it("should inspect wildcard relation IDs", () => {
252248
const compId = createComponentId(15);
253-
const relationId = createRelationId(compId, "*");
249+
const relationId = relation(compId, "*");
254250

255251
expect(inspectEntityId(relationId)).toBe("Relation ID: Component ID (15) -> Wildcard (*)");
256252
});
@@ -263,7 +259,7 @@ describe("Entity ID System", () => {
263259
expect(Number.isSafeInteger(largeEntityId)).toBe(true);
264260

265261
const compId = createComponentId(1023);
266-
const relationId = createRelationId(compId, largeEntityId as EntityId);
262+
const relationId = relation(compId, largeEntityId as EntityId);
267263
expect(Number.isSafeInteger(relationId)).toBe(true);
268264

269265
const decoded = decodeRelationId(relationId);
@@ -309,7 +305,7 @@ describe("EntityIdManager", () => {
309305
const manager = new EntityIdManager();
310306
expect(() => manager.deallocate(1000 as EntityId)).toThrow(); // Below ENTITY_ID_START
311307
expect(() => manager.deallocate(createComponentId(5))).toThrow(); // Component ID
312-
expect(() => manager.deallocate(createRelationId(createComponentId(1), createEntityId(1025)))).toThrow(); // Relation ID
308+
expect(() => manager.deallocate(relation(createComponentId(1), createEntityId(1025)))).toThrow(); // Relation ID
313309
});
314310

315311
it("should reject deallocation of unallocated IDs", () => {

src/entity.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ type RelationIdType<T, U> = U extends void ? EntityId<T> : T extends void ? Enti
6464
* @param componentId The component ID (0-1023)
6565
* @param targetId The target ID (entity, component, or '*' for wildcard)
6666
*/
67-
export function createRelationId<T>(componentId: EntityId<T>, targetId: "*"): WildcardRelationId<T>;
68-
export function createRelationId<T, U>(componentId: EntityId<T>, targetId: EntityId<U>): RelationIdType<T, U>;
69-
export function createRelationId<T>(componentId: EntityId<T>, targetId: EntityId<any> | "*"): EntityId<any> {
67+
export function relation<T>(componentId: EntityId<T>, targetId: "*"): WildcardRelationId<T>;
68+
export function relation<T, U>(componentId: EntityId<T>, targetId: EntityId<U>): RelationIdType<T, U>;
69+
export function relation<T>(componentId: EntityId<T>, targetId: EntityId<any> | "*"): EntityId<any> {
7070
if (!isComponentId(componentId)) {
7171
throw new Error("First argument must be a valid component ID");
7272
}

src/query-filter.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, it, expect } from "bun:test";
22
import { Archetype } from "./archetype";
33
import type { EntityId } from "./entity";
4-
import { createRelationId } from "./entity";
4+
import { relation } from "./entity";
55
import { matchesComponentTypes, matchesFilter, type QueryFilter } from "./query-filter";
66

77
// Mock component IDs for testing
@@ -69,31 +69,31 @@ describe("Query Filter Functions", () => {
6969
});
7070

7171
it("should return false when archetype contains a negative wildcard relation component", () => {
72-
const wildcardRelation = createRelationId(relationComponent, "*");
72+
const wildcardRelation = relation(relationComponent, "*");
7373
const archetype = new Archetype([positionComponent, wildcardRelation]);
7474
const filter: QueryFilter = { negativeComponentTypes: [wildcardRelation] };
7575
expect(matchesFilter(archetype, filter)).toBe(false);
7676
});
7777

7878
it("should return false when archetype contains a specific relation matching negative wildcard filter", () => {
79-
const wildcardRelation = createRelationId(relationComponent, "*");
80-
const otherRelation = createRelationId(relationComponent, 1025 as EntityId);
79+
const wildcardRelation = relation(relationComponent, "*");
80+
const otherRelation = relation(relationComponent, 1025 as EntityId);
8181
const archetype = new Archetype([positionComponent, otherRelation]);
8282
const filter: QueryFilter = { negativeComponentTypes: [wildcardRelation] };
8383
expect(matchesFilter(archetype, filter)).toBe(false);
8484
});
8585

8686
it("should return true when archetype does not contain any relations with the wildcard component", () => {
87-
const wildcardRelation = createRelationId(relationComponent, "*");
87+
const wildcardRelation = relation(relationComponent, "*");
8888
const otherComponent = 5 as EntityId<{ other: number }>;
8989
const archetype = new Archetype([positionComponent, otherComponent]);
9090
const filter: QueryFilter = { negativeComponentTypes: [wildcardRelation] };
9191
expect(matchesFilter(archetype, filter)).toBe(true);
9292
});
9393

9494
it("should return false when archetype contains wildcard relation matching negative filter", () => {
95-
const wildcardRelation = createRelationId(relationComponent, "*");
96-
const matchingRelation = createRelationId(relationComponent, 1026 as EntityId);
95+
const wildcardRelation = relation(relationComponent, "*");
96+
const matchingRelation = relation(relationComponent, 1026 as EntityId);
9797
const archetype = new Archetype([positionComponent, matchingRelation]);
9898
const filter: QueryFilter = { negativeComponentTypes: [wildcardRelation] };
9999
expect(matchesFilter(archetype, filter)).toBe(false);

src/query.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, it, expect } from "bun:test";
22
import { World } from "./world";
33
import { Query } from "./query";
4-
import { createComponentId, createRelationId, type EntityId } from "./entity";
4+
import { createComponentId, relation, type EntityId } from "./entity";
55

66
describe("Query", () => {
77
describe("Query Creation and Basic Functionality", () => {
@@ -261,7 +261,7 @@ describe("Query", () => {
261261
const world = new World();
262262

263263
// Create a wildcard relation for position component
264-
const wildcardPositionRelation = createRelationId(positionComponent, "*");
264+
const wildcardPositionRelation = relation(positionComponent, "*");
265265
const query = world.createQuery([wildcardPositionRelation]);
266266

267267
const entity1 = world.createEntity();
@@ -287,7 +287,7 @@ describe("Query", () => {
287287
const world = new World();
288288

289289
// Create a wildcard relation for position component
290-
const wildcardPositionRelation = createRelationId(positionComponent, "*");
290+
const wildcardPositionRelation = relation(positionComponent, "*");
291291
const query = world.createQuery([velocityComponent, wildcardPositionRelation]);
292292

293293
const entity1 = world.createEntity();

0 commit comments

Comments
 (0)