diff --git a/e2e/part-main.test.ts b/e2e/part-main.test.ts index 5be2e8b..d4666d1 100644 --- a/e2e/part-main.test.ts +++ b/e2e/part-main.test.ts @@ -23,17 +23,20 @@ const clientSave: Save = { path: "@nanoforge-dev/graphics-2d", }, ], - components: [{ name: "ExampleComponent", path: "./components/example.component" }], + components: [ + { + name: "ExampleComponent", + path: "./components/example.component", + paramsNames: ["exampleValueName", "exampleNum"], + }, + ], systems: [{ name: "exampleSystem", path: "./systems/example.system" }], entities: [ { id: "player", - components: [ - { - name: "ExampleComponent", - paramsValues: ["test", 5], - }, - ], + components: { + ExampleComponent: { exampleValueName: "test", exampleNum: 5 }, + }, }, ], }; @@ -212,7 +215,9 @@ describe("part-main schematic", () => { it("should use entity paramsValues from editor save", () => { const content = tree.readContent("/my-app/.nanoforge/editor/client/main.ts"); - expect(content).toContain("options.editor.save.entities[0].components[0].paramsValues[0]"); + expect(content).toContain( + 'options.editor.save.entities[0].components["ExampleComponent"]["exampleValueName"]', + ); }); it("should import components and systems with relative path to root", () => { diff --git a/src/utils/main/main-functions.spec.ts b/src/utils/main/main-functions.spec.ts index fca6f47..0f5874f 100644 --- a/src/utils/main/main-functions.spec.ts +++ b/src/utils/main/main-functions.spec.ts @@ -85,12 +85,12 @@ describe("generateMain", () => { path: "@nanoforge/ecs", }, ], - components: [{ name: "Position", path: "./components/position" }], + components: [{ name: "Position", path: "./components/position", paramsNames: ["x", "y"] }], systems: [{ name: "PhysicsSystem", path: "./systems/physics" }], entities: [ { id: "player", - components: [{ name: "Position", paramsValues: [0, 0] }], + components: { Position: { x: 1, y: 2 } }, }, ], }; @@ -100,7 +100,36 @@ describe("generateMain", () => { ); expect(result).toContain("const registry = ecs.registry;"); expect(result).toContain("const player = registry.spawnEntity();"); - expect(result).toContain("registry.addComponent(player, new Position(0, 0));"); + expect(result).toContain("registry.addComponent(player, new Position(1, 2));"); + expect(result).toContain("registry.addSystem(PhysicsSystem);"); + }); + + it("should generate entity even in reverse order", () => { + const save: Save = { + libraries: [ + { + id: "ecs", + type: SaveLibraryTypeEnum.COMPONENT_SYSTEM, + name: "ECS", + path: "@nanoforge/ecs", + }, + ], + components: [{ name: "Position", path: "./components/position", paramsNames: ["y", "x"] }], + systems: [{ name: "PhysicsSystem", path: "./systems/physics" }], + entities: [ + { + id: "player", + components: { Position: { x: 1, y: 2 } }, + }, + ], + }; + const result = generateMain( + { part: "client", language: "ts", initFunctions: false, editor: false }, + save, + ); + expect(result).toContain("const registry = ecs.registry;"); + expect(result).toContain("const player = registry.spawnEntity();"); + expect(result).toContain("registry.addComponent(player, new Position(2, 1));"); expect(result).toContain("registry.addSystem(PhysicsSystem);"); }); }); diff --git a/src/utils/main/main-functions.ts b/src/utils/main/main-functions.ts index dcf50f7..36e4864 100644 --- a/src/utils/main/main-functions.ts +++ b/src/utils/main/main-functions.ts @@ -49,7 +49,7 @@ export const generateMain = (options: MainOptions, save: Save) => { .generateRegistry(save.libraries) .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_REGISTRY_INIT) - .generateEntities(save.entities) + .generateEntities(save.components, save.entities) .generateSystems(save.systems) .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_REGISTRY_INIT) diff --git a/src/utils/main/main.generator.spec.ts b/src/utils/main/main.generator.spec.ts index 28c33d8..05c61f0 100644 --- a/src/utils/main/main.generator.spec.ts +++ b/src/utils/main/main.generator.spec.ts @@ -132,19 +132,36 @@ describe("MainGenerator", () => { describe("generateEntities", () => { it("should generate entity spawn and component additions", () => { + const components = [ + { + name: "Position", + path: "non", + paramsNames: ["x", "y"], + }, + { + name: "Velocity", + path: "non", + paramsNames: ["fast"], + }, + ]; const entities = [ { id: "player", - components: [ - { name: "Position", paramsValues: [0, 0] }, - { name: "Velocity", paramsValues: [1] }, - ], + components: { + Position: { + x: 1, + y: 2, + }, + Velocity: { + fast: 3, + }, + }, }, ]; - const result = new MainGenerator().generateEntities(entities).toString(); + const result = new MainGenerator().generateEntities(components, entities).toString(); expect(result).toContain("const player = registry.spawnEntity();"); - expect(result).toContain("registry.addComponent(player, new Position(0, 0));"); - expect(result).toContain("registry.addComponent(player, new Velocity(1));"); + expect(result).toContain("registry.addComponent(player, new Position(1, 2));"); + expect(result).toContain("registry.addComponent(player, new Velocity(3));"); }); }); diff --git a/src/utils/main/main.generator.ts b/src/utils/main/main.generator.ts index 8b28ddf..010f74b 100644 --- a/src/utils/main/main.generator.ts +++ b/src/utils/main/main.generator.ts @@ -105,8 +105,8 @@ export class MainGenerator { return this; } - generateEntities(entities: SaveEntity[]): MainGenerator { - entities.forEach((entity, index) => this.generateEntity(entity, index)); + generateEntities(components: SaveComponent[], entities: SaveEntity[]): MainGenerator { + entities.forEach((entity, index) => this.generateEntity(components, entity, index)); return this; } @@ -159,16 +159,26 @@ export class MainGenerator { return this; } - private generateEntity(entity: SaveEntity, entityIndex: number): void { + private generateEntity( + components: SaveComponent[], + entity: SaveEntity, + entityIndex: number, + ): void { this.writeLine(`const ${entity.id} = registry.spawnEntity();`); - entity.components.forEach(({ name, paramsValues: rawParams }, componentIndex) => { + Object.entries(entity.components).forEach(([componentName, rawParams]) => { + const originalsParams = components.find(({ name }) => name === componentName)?.paramsNames; + if (!originalsParams) + throw new Error("Missing component in entity or inexistent saved component"); const params: string[] = !this.editor - ? rawParams.map(getStringParam) - : rawParams.map( - (_param, index) => - `options.editor.save.entities[${entityIndex}].components[${componentIndex}].paramsValues[${index}]`, - ); - this.writeLine(`registry.addComponent(${entity.id}, new ${name}(${params.join(", ")}));`); + ? Object.values(originalsParams).map((ogParam) => { + return getStringParam(rawParams[ogParam]); + }) + : Object.values(originalsParams).map((ogParam) => { + return `options.editor.save.entities[${entityIndex}].components["${componentName}"]["${ogParam}"]`; + }); + this.writeLine( + `registry.addComponent(${entity.id}, new ${componentName}(${params.join(", ")}));`, + ); }); this.endSection(); } diff --git a/src/utils/main/save.type.ts b/src/utils/main/save.type.ts index 40d365e..36372a3 100644 --- a/src/utils/main/save.type.ts +++ b/src/utils/main/save.type.ts @@ -17,6 +17,7 @@ export interface SaveLibrary { export interface SaveComponent { name: string; path: string; + paramsNames: string[]; } export interface SaveSystem { @@ -26,10 +27,7 @@ export interface SaveSystem { export interface SaveEntity { id: string; - components: { - name: string; - paramsValues: any[]; - }[]; + components: Record>; } export interface Save {