@lagless/codegen 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/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js CHANGED
@@ -26,7 +26,7 @@ async function generateFromConfig(options) {
26
26
  }
27
27
  const { schema, projectName } = parseYamlConfig(configContent, configPath);
28
28
  // Determine output directory
29
- const outputDir = outputPath || path.join(path.dirname(configPath), '..', 'code-gen');
29
+ const outputDir = outputPath || path.join(path.dirname(configPath), 'code-gen');
30
30
  // Determine templates directory
31
31
  const templateDir = templatesPath || path.join(DIRNAME, '..', 'files');
32
32
  console.log(`Generating ECS code...`);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { program } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { parseYamlConfig } from './parser.js';\nimport { generateCode } from './generator.js';\nimport { FileOperations } from './template-engine.js';\nimport { DIRNAME } from './dirname.js';\n\ninterface CliOptions {\n config: string;\n output?: string;\n templates?: string;\n}\n\nprogram\n .name('lagless-codegen')\n .description('Generate ECS code from YAML configuration')\n .version('1.0.0')\n .requiredOption('-c, --config <path>', 'Path to YAML configuration file')\n .option('-o, --output <path>', 'Output directory (default: config_dir/../code-gen)')\n .option('-t, --templates <path>', 'Templates directory')\n .action(async (options: CliOptions) => {\n try {\n await generateFromConfig(options);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nasync function generateFromConfig(options: CliOptions): Promise<void> {\n const { config: configPath, output: outputPath, templates: templatesPath } = options;\n\n // Validate config file exists\n if (!fs.existsSync(configPath)) {\n throw new Error(`Config file not found: ${configPath}`);\n }\n\n // Read and parse config\n const configContent = fs.readFileSync(configPath, 'utf-8');\n if (!configContent.trim()) {\n throw new Error(`Config file is empty: ${configPath}`);\n }\n\n const { schema, projectName } = parseYamlConfig(configContent, configPath);\n\n // Determine output directory\n const outputDir = outputPath || path.join(path.dirname(configPath), '..', 'code-gen');\n\n // Determine templates directory\n const templateDir = templatesPath || path.join(DIRNAME, '..', 'files');\n\n console.log(`Generating ECS code...`);\n console.log(`Config: ${configPath}`);\n console.log(`Output: ${outputDir}`);\n console.log(`Templates: ${templateDir}`);\n console.log(`Project: ${projectName}`);\n\n // Create file operations for Node.js filesystem\n const fileOperations: FileOperations = {\n readFile: (filePath: string) => {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return '';\n }\n },\n writeFile: (filePath: string, content: string) => {\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, content, 'utf-8');\n },\n joinPath: (...segments: string[]) => path.join(...segments),\n exists: (filePath: string) => fs.existsSync(filePath),\n readDir: (dirPath: string) => {\n try {\n return fs.readdirSync(dirPath);\n } catch {\n return [];\n }\n },\n isDirectory: (filePath: string) => {\n try {\n return fs.statSync(filePath).isDirectory();\n } catch {\n return false;\n }\n },\n };\n\n // Generate code\n await generateCode({\n schema,\n projectName,\n outputDir,\n templateDir,\n fileOperations,\n });\n\n console.log('ECS code generation complete!');\n console.log(`Generated ${schema.components.length} components and ${schema.singletons.length} singletons.`);\n console.log(`Project name: ${projectName}`);\n console.log(`Output written to: ${outputDir}`);\n}\n\n// Handle unhandled promise rejections\nprocess.on('unhandledRejection', (reason, promise) => {\n console.error('Unhandled Rejection at:', promise, 'reason:', reason);\n process.exit(1);\n});\n\nprogram.parse();\n"],"names":["program","fs","path","parseYamlConfig","generateCode","DIRNAME","name","description","version","requiredOption","option","action","options","generateFromConfig","error","console","Error","message","process","exit","config","configPath","output","outputPath","templates","templatesPath","existsSync","configContent","readFileSync","trim","schema","projectName","outputDir","join","dirname","templateDir","log","fileOperations","readFile","filePath","writeFile","content","dir","mkdirSync","recursive","writeFileSync","joinPath","segments","exists","readDir","dirPath","readdirSync","isDirectory","statSync","components","length","singletons","on","reason","promise","parse"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { program } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { parseYamlConfig } from './parser.js';\nimport { generateCode } from './generator.js';\nimport { FileOperations } from './template-engine.js';\nimport { DIRNAME } from './dirname.js';\n\ninterface CliOptions {\n config: string;\n output?: string;\n templates?: string;\n}\n\nprogram\n .name('lagless-codegen')\n .description('Generate ECS code from YAML configuration')\n .version('1.0.0')\n .requiredOption('-c, --config <path>', 'Path to YAML configuration file')\n .option('-o, --output <path>', 'Output directory (default: config_dir/../code-gen)')\n .option('-t, --templates <path>', 'Templates directory')\n .action(async (options: CliOptions) => {\n try {\n await generateFromConfig(options);\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nasync function generateFromConfig(options: CliOptions): Promise<void> {\n const { config: configPath, output: outputPath, templates: templatesPath } = options;\n\n // Validate config file exists\n if (!fs.existsSync(configPath)) {\n throw new Error(`Config file not found: ${configPath}`);\n }\n\n // Read and parse config\n const configContent = fs.readFileSync(configPath, 'utf-8');\n if (!configContent.trim()) {\n throw new Error(`Config file is empty: ${configPath}`);\n }\n\n const { schema, projectName } = parseYamlConfig(configContent, configPath);\n\n // Determine output directory\n const outputDir = outputPath || path.join(path.dirname(configPath), 'code-gen');\n\n // Determine templates directory\n const templateDir = templatesPath || path.join(DIRNAME, '..', 'files');\n\n console.log(`Generating ECS code...`);\n console.log(`Config: ${configPath}`);\n console.log(`Output: ${outputDir}`);\n console.log(`Templates: ${templateDir}`);\n console.log(`Project: ${projectName}`);\n\n // Create file operations for Node.js filesystem\n const fileOperations: FileOperations = {\n readFile: (filePath: string) => {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return '';\n }\n },\n writeFile: (filePath: string, content: string) => {\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, content, 'utf-8');\n },\n joinPath: (...segments: string[]) => path.join(...segments),\n exists: (filePath: string) => fs.existsSync(filePath),\n readDir: (dirPath: string) => {\n try {\n return fs.readdirSync(dirPath);\n } catch {\n return [];\n }\n },\n isDirectory: (filePath: string) => {\n try {\n return fs.statSync(filePath).isDirectory();\n } catch {\n return false;\n }\n },\n };\n\n // Generate code\n await generateCode({\n schema,\n projectName,\n outputDir,\n templateDir,\n fileOperations,\n });\n\n console.log('ECS code generation complete!');\n console.log(`Generated ${schema.components.length} components and ${schema.singletons.length} singletons.`);\n console.log(`Project name: ${projectName}`);\n console.log(`Output written to: ${outputDir}`);\n}\n\n// Handle unhandled promise rejections\nprocess.on('unhandledRejection', (reason, promise) => {\n console.error('Unhandled Rejection at:', promise, 'reason:', reason);\n process.exit(1);\n});\n\nprogram.parse();\n"],"names":["program","fs","path","parseYamlConfig","generateCode","DIRNAME","name","description","version","requiredOption","option","action","options","generateFromConfig","error","console","Error","message","process","exit","config","configPath","output","outputPath","templates","templatesPath","existsSync","configContent","readFileSync","trim","schema","projectName","outputDir","join","dirname","templateDir","log","fileOperations","readFile","filePath","writeFile","content","dir","mkdirSync","recursive","writeFileSync","joinPath","segments","exists","readDir","dirPath","readdirSync","isDirectory","statSync","components","length","singletons","on","reason","promise","parse"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const DIRNAME: string;
2
+ //# sourceMappingURL=dirname.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dirname.d.ts","sourceRoot":"","sources":["../src/dirname.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,QAI8B,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { ECSSchema } from '@lagless/core';
2
+ import { FileOperations } from './template-engine.js';
3
+ import { SimulationType } from './parser.js';
4
+ export interface GenerateCodeOptions {
5
+ schema: ECSSchema;
6
+ projectName: string;
7
+ outputDir: string;
8
+ templateDir: string;
9
+ fileOperations: FileOperations;
10
+ simulationType?: SimulationType;
11
+ }
12
+ export declare function generateBarrelFileContent(schema: ECSSchema, projectName: string): string;
13
+ export declare function generateCode(options: GenerateCodeOptions): Promise<void>;
14
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmB,MAAM,eAAe,CAAC;AAC3D,OAAO,EAA2C,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE/F,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAsCxF;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqJ9E"}
package/dist/generator.js CHANGED
@@ -81,21 +81,31 @@ export async function generateCode(options) {
81
81
  fileOperations
82
82
  });
83
83
  }
84
- // Generate Filter classes
84
+ // Determine mask word count from component count
85
+ const maskWords = Math.max(1, Math.ceil(schema.components.length / 32));
86
+ // Generate Filter classes (masks are number[] with one element per Uint32 word)
85
87
  for (const filter of schema.filters){
86
88
  const componentsImports = [
87
89
  ...filter.include,
88
90
  ...filter.exclude
89
91
  ].map((c)=>c.name);
90
- const includeMask = filter.include.reduce((acc, component)=>acc | component.id, 0);
91
- const excludeMask = filter.exclude.reduce((acc, component)=>acc | component.id, 0);
92
+ const includeMaskWords = new Array(maskWords).fill(0);
93
+ for (const component of filter.include){
94
+ const w = component.id >>> 5;
95
+ includeMaskWords[w] |= 1 << (component.id & 31);
96
+ }
97
+ const excludeMaskWords = new Array(maskWords).fill(0);
98
+ for (const component of filter.exclude){
99
+ const w = component.id >>> 5;
100
+ excludeMaskWords[w] |= 1 << (component.id & 31);
101
+ }
92
102
  await processTemplate({
93
103
  templateDir: joinPath(templateDir, 'filter'),
94
104
  outputDir,
95
105
  data: {
96
106
  filter,
97
- includeMask,
98
- excludeMask,
107
+ includeMaskWords,
108
+ excludeMaskWords,
99
109
  componentsImports,
100
110
  name: filter.name,
101
111
  projectName
@@ -138,9 +148,12 @@ export async function generateCode(options) {
138
148
  },
139
149
  fileOperations
140
150
  });
141
- // Generate Runner class
151
+ var _options_simulationType;
152
+ // Generate Runner class (template varies by simulationType)
153
+ const simulationType = (_options_simulationType = options.simulationType) != null ? _options_simulationType : 'raw';
154
+ const runnerTemplateDir = simulationType === 'physics3d' ? 'runner-physics3d' : simulationType === 'physics2d' ? 'runner-physics2d' : 'runner';
142
155
  await processTemplate({
143
- templateDir: joinPath(templateDir, 'runner'),
156
+ templateDir: joinPath(templateDir, runnerTemplateDir),
144
157
  outputDir,
145
158
  data: {
146
159
  projectName,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generator.ts"],"sourcesContent":["import { ECSSchema, FieldDefinition } from '@lagless/core';\nimport { generateFromTemplate as processTemplate, FileOperations } from './template-engine.js';\nimport { FieldTypeReverse, getTypeSizeBytes, typedArrayConstructors, typeToArrayConstructor } from '@lagless/binary';\n\nexport interface GenerateCodeOptions {\n schema: ECSSchema;\n projectName: string;\n outputDir: string;\n templateDir: string;\n fileOperations: FileOperations;\n}\n\nexport function generateBarrelFileContent(schema: ECSSchema, projectName: string): string {\n let content = '// Generated by @lagless/codegen. Do not edit manually.\\n\\n';\n\n // Export components\n schema.components.forEach((component) => {\n content += `export * from './${component.name}.js';\\n`;\n });\n\n // Export singletons\n schema.singletons.forEach((singleton) => {\n content += `export * from './${singleton.name}.js';\\n`;\n });\n\n // Export player resources\n schema.playerResources.forEach((playerResource) => {\n content += `export * from './${playerResource.name}.js';\\n`;\n });\n\n // Export filters\n schema.filters.forEach((filter) => {\n content += `export * from './${filter.name}.js';\\n`;\n });\n\n // Export inputs\n schema.inputs.forEach((input) => {\n content += `export * from './${input.name}.js';\\n`;\n });\n\n // Export input registry\n content += `export * from './${projectName}InputRegistry.js';\\n`;\n\n // Export core\n content += `export * from './${projectName}.core.js';\\n`;\n\n // Export runner\n content += `export * from './${projectName}.runner.js';\\n`;\n\n return content;\n}\n\nexport async function generateCode(options: GenerateCodeOptions): Promise<void> {\n const { schema, projectName, outputDir, templateDir, fileOperations } = options;\n const { writeFile, joinPath, exists } = fileOperations;\n\n // Ensure output directory exists\n if (!exists(outputDir)) {\n writeFile(joinPath(outputDir, '.gitkeep'), '');\n }\n\n // Generate component classes\n for (const component of schema.components) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'component'),\n outputDir,\n data: {\n ...component,\n component,\n projectName,\n typeToArrayConstructor,\n getFieldByteSize: (field: FieldDefinition) => {\n const baseSize = getTypeSizeBytes(field.type);\n return field.isArray ? baseSize * field.arrayLength! : baseSize;\n },\n },\n fileOperations,\n });\n }\n\n // Generate singleton classes\n for (const singleton of schema.singletons) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'singleton'),\n outputDir,\n data: {\n ...singleton,\n singleton,\n projectName,\n typeToArrayConstructor,\n },\n fileOperations,\n });\n }\n\n // Generate playerResource classes\n for (const playerResource of schema.playerResources) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'playerResource'),\n outputDir,\n data: {\n ...playerResource,\n playerResource,\n projectName,\n typeToArrayConstructor,\n },\n fileOperations,\n });\n }\n\n // Generate Filter classes\n for (const filter of schema.filters) {\n const componentsImports = [...filter.include, ...filter.exclude].map((c) => c.name);\n const includeMask = filter.include.reduce((acc, component) => acc | component.id, 0);\n const excludeMask = filter.exclude.reduce((acc, component) => acc | component.id, 0);\n\n await processTemplate({\n templateDir: joinPath(templateDir, 'filter'),\n outputDir,\n data: {\n filter,\n includeMask,\n excludeMask,\n componentsImports,\n name: filter.name,\n projectName,\n },\n fileOperations,\n });\n }\n\n // Generate Input classes\n for (const input of schema.inputs) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'input'),\n outputDir,\n data: {\n ...input,\n input,\n projectName,\n FieldTypeReverse,\n typedArrayConstructors,\n },\n fileOperations,\n });\n }\n\n // Generate input registry\n await processTemplate({\n templateDir: joinPath(templateDir, 'input-registry'),\n outputDir,\n data: {\n projectName,\n inputs: schema.inputs,\n schema,\n },\n fileOperations,\n });\n\n // Generate ECSCore class\n await processTemplate({\n templateDir: joinPath(templateDir, 'core'),\n outputDir,\n data: {\n projectName,\n schema,\n },\n fileOperations,\n });\n\n // Generate Runner class\n await processTemplate({\n templateDir: joinPath(templateDir, 'runner'),\n outputDir,\n data: {\n projectName,\n schema,\n },\n fileOperations,\n });\n\n // Generate barrel file\n const barrelContent = generateBarrelFileContent(schema, projectName);\n writeFile(joinPath(outputDir, 'index.ts'), barrelContent);\n}\n"],"names":["generateFromTemplate","processTemplate","FieldTypeReverse","getTypeSizeBytes","typedArrayConstructors","typeToArrayConstructor","generateBarrelFileContent","schema","projectName","content","components","forEach","component","name","singletons","singleton","playerResources","playerResource","filters","filter","inputs","input","generateCode","options","outputDir","templateDir","fileOperations","writeFile","joinPath","exists","data","getFieldByteSize","field","baseSize","type","isArray","arrayLength","componentsImports","include","exclude","map","c","includeMask","reduce","acc","id","excludeMask","barrelContent"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["../src/generator.ts"],"sourcesContent":["import { ECSSchema, FieldDefinition } from '@lagless/core';\nimport { generateFromTemplate as processTemplate, FileOperations } from './template-engine.js';\nimport { FieldTypeReverse, getTypeSizeBytes, typedArrayConstructors, typeToArrayConstructor } from '@lagless/binary';\nimport { SimulationType } from './parser.js';\n\nexport interface GenerateCodeOptions {\n schema: ECSSchema;\n projectName: string;\n outputDir: string;\n templateDir: string;\n fileOperations: FileOperations;\n simulationType?: SimulationType;\n}\n\nexport function generateBarrelFileContent(schema: ECSSchema, projectName: string): string {\n let content = '// Generated by @lagless/codegen. Do not edit manually.\\n\\n';\n\n // Export components\n schema.components.forEach((component) => {\n content += `export * from './${component.name}.js';\\n`;\n });\n\n // Export singletons\n schema.singletons.forEach((singleton) => {\n content += `export * from './${singleton.name}.js';\\n`;\n });\n\n // Export player resources\n schema.playerResources.forEach((playerResource) => {\n content += `export * from './${playerResource.name}.js';\\n`;\n });\n\n // Export filters\n schema.filters.forEach((filter) => {\n content += `export * from './${filter.name}.js';\\n`;\n });\n\n // Export inputs\n schema.inputs.forEach((input) => {\n content += `export * from './${input.name}.js';\\n`;\n });\n\n // Export input registry\n content += `export * from './${projectName}InputRegistry.js';\\n`;\n\n // Export core\n content += `export * from './${projectName}.core.js';\\n`;\n\n // Export runner\n content += `export * from './${projectName}.runner.js';\\n`;\n\n return content;\n}\n\nexport async function generateCode(options: GenerateCodeOptions): Promise<void> {\n const { schema, projectName, outputDir, templateDir, fileOperations } = options;\n const { writeFile, joinPath, exists } = fileOperations;\n\n // Ensure output directory exists\n if (!exists(outputDir)) {\n writeFile(joinPath(outputDir, '.gitkeep'), '');\n }\n\n // Generate component classes\n for (const component of schema.components) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'component'),\n outputDir,\n data: {\n ...component,\n component,\n projectName,\n typeToArrayConstructor,\n getFieldByteSize: (field: FieldDefinition) => {\n const baseSize = getTypeSizeBytes(field.type);\n return field.isArray ? baseSize * field.arrayLength! : baseSize;\n },\n },\n fileOperations,\n });\n }\n\n // Generate singleton classes\n for (const singleton of schema.singletons) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'singleton'),\n outputDir,\n data: {\n ...singleton,\n singleton,\n projectName,\n typeToArrayConstructor,\n },\n fileOperations,\n });\n }\n\n // Generate playerResource classes\n for (const playerResource of schema.playerResources) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'playerResource'),\n outputDir,\n data: {\n ...playerResource,\n playerResource,\n projectName,\n typeToArrayConstructor,\n },\n fileOperations,\n });\n }\n\n // Determine mask word count from component count\n const maskWords = Math.max(1, Math.ceil(schema.components.length / 32));\n\n // Generate Filter classes (masks are number[] with one element per Uint32 word)\n for (const filter of schema.filters) {\n const componentsImports = [...filter.include, ...filter.exclude].map((c) => c.name);\n\n const includeMaskWords = new Array<number>(maskWords).fill(0);\n for (const component of filter.include) {\n const w = component.id >>> 5;\n includeMaskWords[w] |= 1 << (component.id & 31);\n }\n\n const excludeMaskWords = new Array<number>(maskWords).fill(0);\n for (const component of filter.exclude) {\n const w = component.id >>> 5;\n excludeMaskWords[w] |= 1 << (component.id & 31);\n }\n\n await processTemplate({\n templateDir: joinPath(templateDir, 'filter'),\n outputDir,\n data: {\n filter,\n includeMaskWords,\n excludeMaskWords,\n componentsImports,\n name: filter.name,\n projectName,\n },\n fileOperations,\n });\n }\n\n // Generate Input classes\n for (const input of schema.inputs) {\n await processTemplate({\n templateDir: joinPath(templateDir, 'input'),\n outputDir,\n data: {\n ...input,\n input,\n projectName,\n FieldTypeReverse,\n typedArrayConstructors,\n },\n fileOperations,\n });\n }\n\n // Generate input registry\n await processTemplate({\n templateDir: joinPath(templateDir, 'input-registry'),\n outputDir,\n data: {\n projectName,\n inputs: schema.inputs,\n schema,\n },\n fileOperations,\n });\n\n // Generate ECSCore class\n await processTemplate({\n templateDir: joinPath(templateDir, 'core'),\n outputDir,\n data: {\n projectName,\n schema,\n },\n fileOperations,\n });\n\n // Generate Runner class (template varies by simulationType)\n const simulationType = options.simulationType ?? 'raw';\n const runnerTemplateDir =\n simulationType === 'physics3d' ? 'runner-physics3d' : simulationType === 'physics2d' ? 'runner-physics2d' : 'runner';\n\n await processTemplate({\n templateDir: joinPath(templateDir, runnerTemplateDir),\n outputDir,\n data: {\n projectName,\n schema,\n },\n fileOperations,\n });\n\n // Generate barrel file\n const barrelContent = generateBarrelFileContent(schema, projectName);\n writeFile(joinPath(outputDir, 'index.ts'), barrelContent);\n}\n"],"names":["generateFromTemplate","processTemplate","FieldTypeReverse","getTypeSizeBytes","typedArrayConstructors","typeToArrayConstructor","generateBarrelFileContent","schema","projectName","content","components","forEach","component","name","singletons","singleton","playerResources","playerResource","filters","filter","inputs","input","generateCode","options","outputDir","templateDir","fileOperations","writeFile","joinPath","exists","data","getFieldByteSize","field","baseSize","type","isArray","arrayLength","maskWords","Math","max","ceil","length","componentsImports","include","exclude","map","c","includeMaskWords","Array","fill","w","id","excludeMaskWords","simulationType","runnerTemplateDir","barrelContent"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './parser.js';
2
+ export * from './generator.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Tree } from '@nx/devkit';
2
+ interface GeneratorOptions {
3
+ configPath: string;
4
+ }
5
+ export default function (tree: Tree, options: GeneratorOptions): Promise<() => void>;
6
+ export {};
7
+ //# sourceMappingURL=nx-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nx-generator.d.ts","sourceRoot":"","sources":["../src/nx-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAkC,MAAM,YAAY,CAAC;AAOlE,UAAU,gBAAgB;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yBAA+B,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,uBAmEnE"}
@@ -11,7 +11,7 @@ export default async function(tree, options) {
11
11
  }
12
12
  const configContent = tree.read(configPath, 'utf-8');
13
13
  if (!configContent) throw new Error(`Config file is empty: ${configPath}`);
14
- const { schema, projectName } = parseYamlConfig(configContent, configPath);
14
+ const { schema, projectName, simulationType } = parseYamlConfig(configContent, configPath);
15
15
  // Generate output directory from config path (../code-gen)
16
16
  const outputDir = joinPathFragments(configPath, '../code-gen');
17
17
  const templateDir = joinPathFragments(DIRNAME, '..', 'files');
@@ -53,7 +53,8 @@ export default async function(tree, options) {
53
53
  projectName,
54
54
  outputDir,
55
55
  templateDir,
56
- fileOperations
56
+ fileOperations,
57
+ simulationType
57
58
  });
58
59
  await formatFiles(tree);
59
60
  return ()=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/nx-generator.ts"],"sourcesContent":["import { Tree, formatFiles, joinPathFragments } from '@nx/devkit';\nimport { parseYamlConfig } from './parser.js';\nimport { generateCode } from './generator.js';\nimport { FileOperations } from './template-engine.js';\nimport * as fs from 'fs';\nimport { DIRNAME } from './dirname.js';\n\ninterface GeneratorOptions {\n configPath: string;\n}\n\nexport default async function (tree: Tree, options: GeneratorOptions) {\n // Read and parse YAML config\n const configPath = options.configPath;\n if (!tree.exists(configPath)) {\n throw new Error(`Config file not found: ${configPath}`);\n }\n\n const configContent = tree.read(configPath, 'utf-8');\n if (!configContent) throw new Error(`Config file is empty: ${configPath}`);\n\n const { schema, projectName } = parseYamlConfig(configContent, configPath);\n\n // Generate output directory from config path (../code-gen)\n const outputDir = joinPathFragments(configPath, '../code-gen');\n const templateDir = joinPathFragments(DIRNAME, '..', 'files');\n\n // Create file operations adapter for NX Tree\n const fileOperations: FileOperations = {\n writeFile: (path: string, content: string) => tree.write(path, content),\n // Only writeFile uses tree, other methods use fs\n readFile: (path: string) => fs.readFileSync(path, 'utf-8'),\n joinPath: (...segments: string[]) => joinPathFragments(...segments),\n exists: (path: string) => {\n try {\n fs.accessSync(path, fs.constants.F_OK);\n return true;\n } catch {\n return false;\n }\n },\n readDir: (path: string) => {\n try {\n return fs.readdirSync(path);\n } catch {\n return [];\n }\n },\n isDirectory: (path: string) => {\n try {\n return fs.statSync(path).isDirectory();\n } catch {\n return false;\n }\n },\n };\n\n if (!tree.exists(outputDir)) {\n tree.write(joinPathFragments(outputDir, '.gitkeep'), '');\n }\n\n // Generate code using the unified template engine\n await generateCode({\n schema,\n projectName,\n outputDir,\n templateDir,\n fileOperations,\n });\n\n await formatFiles(tree);\n\n return () => {\n console.log('ECS code generation complete!');\n console.log(`Generated ${schema.components.length} components and ${schema.singletons.length} singletons.`);\n console.log(`Project name: ${projectName}`);\n };\n}\n"],"names":["formatFiles","joinPathFragments","parseYamlConfig","generateCode","fs","DIRNAME","tree","options","configPath","exists","Error","configContent","read","schema","projectName","outputDir","templateDir","fileOperations","writeFile","path","content","write","readFile","readFileSync","joinPath","segments","accessSync","constants","F_OK","readDir","readdirSync","isDirectory","statSync","console","log","components","length","singletons"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAAeA,WAAW,EAAEC,iBAAiB,QAAQ,aAAa;AAClE,SAASC,eAAe,QAAQ,cAAc;AAC9C,SAASC,YAAY,QAAQ,iBAAiB;AAE9C,YAAYC,QAAQ,KAAK;AACzB,SAASC,OAAO,QAAQ,eAAe;AAMvC,eAAe,eAAgBC,IAAU,EAAEC,OAAyB;IAClE,6BAA6B;IAC7B,MAAMC,aAAaD,QAAQC,UAAU;IACrC,IAAI,CAACF,KAAKG,MAAM,CAACD,aAAa;QAC5B,MAAM,IAAIE,MAAM,CAAC,uBAAuB,EAAEF,WAAW,CAAC;IACxD;IAEA,MAAMG,gBAAgBL,KAAKM,IAAI,CAACJ,YAAY;IAC5C,IAAI,CAACG,eAAe,MAAM,IAAID,MAAM,CAAC,sBAAsB,EAAEF,WAAW,CAAC;IAEzE,MAAM,EAAEK,MAAM,EAAEC,WAAW,EAAE,GAAGZ,gBAAgBS,eAAeH;IAE/D,2DAA2D;IAC3D,MAAMO,YAAYd,kBAAkBO,YAAY;IAChD,MAAMQ,cAAcf,kBAAkBI,SAAS,MAAM;IAErD,6CAA6C;IAC7C,MAAMY,iBAAiC;QACrCC,WAAW,CAACC,MAAcC,UAAoBd,KAAKe,KAAK,CAACF,MAAMC;QAC/D,iDAAiD;QACjDE,UAAU,CAACH,OAAiBf,GAAGmB,YAAY,CAACJ,MAAM;QAClDK,UAAU,CAAC,GAAGC,WAAuBxB,qBAAqBwB;QAC1DhB,QAAQ,CAACU;YACP,IAAI;gBACFf,GAAGsB,UAAU,CAACP,MAAMf,GAAGuB,SAAS,CAACC,IAAI;gBACrC,OAAO;YACT,EAAE,UAAM;gBACN,OAAO;YACT;QACF;QACAC,SAAS,CAACV;YACR,IAAI;gBACF,OAAOf,GAAG0B,WAAW,CAACX;YACxB,EAAE,UAAM;gBACN,OAAO,EAAE;YACX;QACF;QACAY,aAAa,CAACZ;YACZ,IAAI;gBACF,OAAOf,GAAG4B,QAAQ,CAACb,MAAMY,WAAW;YACtC,EAAE,UAAM;gBACN,OAAO;YACT;QACF;IACF;IAEA,IAAI,CAACzB,KAAKG,MAAM,CAACM,YAAY;QAC3BT,KAAKe,KAAK,CAACpB,kBAAkBc,WAAW,aAAa;IACvD;IAEA,kDAAkD;IAClD,MAAMZ,aAAa;QACjBU;QACAC;QACAC;QACAC;QACAC;IACF;IAEA,MAAMjB,YAAYM;IAElB,OAAO;QACL2B,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC,CAAC,UAAU,EAAErB,OAAOsB,UAAU,CAACC,MAAM,CAAC,gBAAgB,EAAEvB,OAAOwB,UAAU,CAACD,MAAM,CAAC,YAAY,CAAC;QAC1GH,QAAQC,GAAG,CAAC,CAAC,cAAc,EAAEpB,YAAY,CAAC;IAC5C;AACF"}
1
+ {"version":3,"sources":["../src/nx-generator.ts"],"sourcesContent":["import { Tree, formatFiles, joinPathFragments } from '@nx/devkit';\nimport { parseYamlConfig } from './parser.js';\nimport { generateCode } from './generator.js';\nimport { FileOperations } from './template-engine.js';\nimport * as fs from 'fs';\nimport { DIRNAME } from './dirname.js';\n\ninterface GeneratorOptions {\n configPath: string;\n}\n\nexport default async function (tree: Tree, options: GeneratorOptions) {\n // Read and parse YAML config\n const configPath = options.configPath;\n if (!tree.exists(configPath)) {\n throw new Error(`Config file not found: ${configPath}`);\n }\n\n const configContent = tree.read(configPath, 'utf-8');\n if (!configContent) throw new Error(`Config file is empty: ${configPath}`);\n\n const { schema, projectName, simulationType } = parseYamlConfig(configContent, configPath);\n\n // Generate output directory from config path (../code-gen)\n const outputDir = joinPathFragments(configPath, '../code-gen');\n const templateDir = joinPathFragments(DIRNAME, '..', 'files');\n\n // Create file operations adapter for NX Tree\n const fileOperations: FileOperations = {\n writeFile: (path: string, content: string) => tree.write(path, content),\n // Only writeFile uses tree, other methods use fs\n readFile: (path: string) => fs.readFileSync(path, 'utf-8'),\n joinPath: (...segments: string[]) => joinPathFragments(...segments),\n exists: (path: string) => {\n try {\n fs.accessSync(path, fs.constants.F_OK);\n return true;\n } catch {\n return false;\n }\n },\n readDir: (path: string) => {\n try {\n return fs.readdirSync(path);\n } catch {\n return [];\n }\n },\n isDirectory: (path: string) => {\n try {\n return fs.statSync(path).isDirectory();\n } catch {\n return false;\n }\n },\n };\n\n if (!tree.exists(outputDir)) {\n tree.write(joinPathFragments(outputDir, '.gitkeep'), '');\n }\n\n // Generate code using the unified template engine\n await generateCode({\n schema,\n projectName,\n outputDir,\n templateDir,\n fileOperations,\n simulationType,\n });\n\n await formatFiles(tree);\n\n return () => {\n console.log('ECS code generation complete!');\n console.log(`Generated ${schema.components.length} components and ${schema.singletons.length} singletons.`);\n console.log(`Project name: ${projectName}`);\n };\n}\n"],"names":["formatFiles","joinPathFragments","parseYamlConfig","generateCode","fs","DIRNAME","tree","options","configPath","exists","Error","configContent","read","schema","projectName","simulationType","outputDir","templateDir","fileOperations","writeFile","path","content","write","readFile","readFileSync","joinPath","segments","accessSync","constants","F_OK","readDir","readdirSync","isDirectory","statSync","console","log","components","length","singletons"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAAeA,WAAW,EAAEC,iBAAiB,QAAQ,aAAa;AAClE,SAASC,eAAe,QAAQ,cAAc;AAC9C,SAASC,YAAY,QAAQ,iBAAiB;AAE9C,YAAYC,QAAQ,KAAK;AACzB,SAASC,OAAO,QAAQ,eAAe;AAMvC,eAAe,eAAgBC,IAAU,EAAEC,OAAyB;IAClE,6BAA6B;IAC7B,MAAMC,aAAaD,QAAQC,UAAU;IACrC,IAAI,CAACF,KAAKG,MAAM,CAACD,aAAa;QAC5B,MAAM,IAAIE,MAAM,CAAC,uBAAuB,EAAEF,WAAW,CAAC;IACxD;IAEA,MAAMG,gBAAgBL,KAAKM,IAAI,CAACJ,YAAY;IAC5C,IAAI,CAACG,eAAe,MAAM,IAAID,MAAM,CAAC,sBAAsB,EAAEF,WAAW,CAAC;IAEzE,MAAM,EAAEK,MAAM,EAAEC,WAAW,EAAEC,cAAc,EAAE,GAAGb,gBAAgBS,eAAeH;IAE/E,2DAA2D;IAC3D,MAAMQ,YAAYf,kBAAkBO,YAAY;IAChD,MAAMS,cAAchB,kBAAkBI,SAAS,MAAM;IAErD,6CAA6C;IAC7C,MAAMa,iBAAiC;QACrCC,WAAW,CAACC,MAAcC,UAAoBf,KAAKgB,KAAK,CAACF,MAAMC;QAC/D,iDAAiD;QACjDE,UAAU,CAACH,OAAiBhB,GAAGoB,YAAY,CAACJ,MAAM;QAClDK,UAAU,CAAC,GAAGC,WAAuBzB,qBAAqByB;QAC1DjB,QAAQ,CAACW;YACP,IAAI;gBACFhB,GAAGuB,UAAU,CAACP,MAAMhB,GAAGwB,SAAS,CAACC,IAAI;gBACrC,OAAO;YACT,EAAE,UAAM;gBACN,OAAO;YACT;QACF;QACAC,SAAS,CAACV;YACR,IAAI;gBACF,OAAOhB,GAAG2B,WAAW,CAACX;YACxB,EAAE,UAAM;gBACN,OAAO,EAAE;YACX;QACF;QACAY,aAAa,CAACZ;YACZ,IAAI;gBACF,OAAOhB,GAAG6B,QAAQ,CAACb,MAAMY,WAAW;YACtC,EAAE,UAAM;gBACN,OAAO;YACT;QACF;IACF;IAEA,IAAI,CAAC1B,KAAKG,MAAM,CAACO,YAAY;QAC3BV,KAAKgB,KAAK,CAACrB,kBAAkBe,WAAW,aAAa;IACvD;IAEA,kDAAkD;IAClD,MAAMb,aAAa;QACjBU;QACAC;QACAE;QACAC;QACAC;QACAH;IACF;IAEA,MAAMf,YAAYM;IAElB,OAAO;QACL4B,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC,CAAC,UAAU,EAAEtB,OAAOuB,UAAU,CAACC,MAAM,CAAC,gBAAgB,EAAExB,OAAOyB,UAAU,CAACD,MAAM,CAAC,YAAY,CAAC;QAC1GH,QAAQC,GAAG,CAAC,CAAC,cAAc,EAAErB,YAAY,CAAC;IAC5C;AACF"}
@@ -0,0 +1,24 @@
1
+ import { InputFieldDefinition } from '@lagless/binary';
2
+ import { ECSSchema, FieldDefinition } from '@lagless/core';
3
+ export type SimulationType = 'raw' | 'physics2d' | 'physics3d';
4
+ export interface ECSConfig {
5
+ projectName?: string;
6
+ simulationType?: SimulationType;
7
+ components?: Record<string, Record<string, string> | null>;
8
+ singletons?: Record<string, Record<string, string>>;
9
+ playerResources?: Record<string, Record<string, string>>;
10
+ filters?: Record<string, {
11
+ include?: string[];
12
+ exclude?: string[];
13
+ }>;
14
+ inputs?: Record<string, Record<string, string>>;
15
+ }
16
+ export declare function parseInputFieldType(fieldName: string, fieldType: string): InputFieldDefinition;
17
+ export declare function parseFieldType(typeStr: string): FieldDefinition;
18
+ export declare function getProjectNameFromConfigPath(configPath: string): string;
19
+ export declare function parseYamlConfig(configContent: string, configPath?: string): {
20
+ schema: ECSSchema;
21
+ projectName: string;
22
+ simulationType: SimulationType;
23
+ };
24
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,EAGrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,SAAS,EACT,eAAe,EAKhB,MAAM,eAAe,CAAC;AAGvB,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,WAAW,GAAG,WAAW,CAAC;AAE/D,MAAM,WAAW,SAAS;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACjD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,oBAAoB,CAS9F;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CA6B/D;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAMvE;AAED,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,GAClB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,cAAc,CAAA;CAAE,CAsP5E"}
package/dist/parser.js CHANGED
@@ -48,6 +48,8 @@ export function parseYamlConfig(configContent, configPath) {
48
48
  if (!rawConfig.components && !rawConfig.singletons) {
49
49
  throw new Error('Config must contain at least one of: components, singletons');
50
50
  }
51
+ var _rawConfig_simulationType;
52
+ const simulationType = (_rawConfig_simulationType = rawConfig.simulationType) != null ? _rawConfig_simulationType : 'raw';
51
53
  // Determine project name: from config or from path
52
54
  let projectName;
53
55
  if (rawConfig.projectName) {
@@ -57,23 +59,102 @@ export function parseYamlConfig(configContent, configPath) {
57
59
  } else {
58
60
  throw new Error('projectName must be specified in config or configPath must be provided');
59
61
  }
62
+ // Auto-prepend physics components if needed
63
+ if (simulationType === 'physics3d') {
64
+ if (!rawConfig.components) rawConfig.components = {};
65
+ if (!rawConfig.components['Transform3d']) {
66
+ rawConfig.components = _extends({
67
+ Transform3d: {
68
+ positionX: 'float32',
69
+ positionY: 'float32',
70
+ positionZ: 'float32',
71
+ rotationX: 'float32',
72
+ rotationY: 'float32',
73
+ rotationZ: 'float32',
74
+ rotationW: 'float32',
75
+ prevPositionX: 'float32',
76
+ prevPositionY: 'float32',
77
+ prevPositionZ: 'float32',
78
+ prevRotationX: 'float32',
79
+ prevRotationY: 'float32',
80
+ prevRotationZ: 'float32',
81
+ prevRotationW: 'float32'
82
+ }
83
+ }, rawConfig.components);
84
+ }
85
+ if (!rawConfig.components['PhysicsRefs']) {
86
+ // Insert after Transform3d
87
+ const entries = Object.entries(rawConfig.components);
88
+ const transform3dIdx = entries.findIndex(([name])=>name === 'Transform3d');
89
+ const insertIdx = transform3dIdx >= 0 ? transform3dIdx + 1 : 0;
90
+ entries.splice(insertIdx, 0, [
91
+ 'PhysicsRefs',
92
+ {
93
+ bodyHandle: 'float64',
94
+ colliderHandle: 'float64',
95
+ bodyType: 'uint8',
96
+ collisionLayer: 'uint16'
97
+ }
98
+ ]);
99
+ rawConfig.components = Object.fromEntries(entries);
100
+ }
101
+ }
102
+ // Auto-prepend physics2d components if needed
103
+ if (simulationType === 'physics2d') {
104
+ if (!rawConfig.components) rawConfig.components = {};
105
+ if (!rawConfig.components['Transform2d']) {
106
+ rawConfig.components = _extends({
107
+ Transform2d: {
108
+ positionX: 'float32',
109
+ positionY: 'float32',
110
+ rotation: 'float32',
111
+ prevPositionX: 'float32',
112
+ prevPositionY: 'float32',
113
+ prevRotation: 'float32'
114
+ }
115
+ }, rawConfig.components);
116
+ }
117
+ if (!rawConfig.components['PhysicsRefs']) {
118
+ // Insert after Transform2d
119
+ const entries = Object.entries(rawConfig.components);
120
+ const transform2dIdx = entries.findIndex(([name])=>name === 'Transform2d');
121
+ const insertIdx = transform2dIdx >= 0 ? transform2dIdx + 1 : 0;
122
+ entries.splice(insertIdx, 0, [
123
+ 'PhysicsRefs',
124
+ {
125
+ bodyHandle: 'float64',
126
+ colliderHandle: 'float64',
127
+ bodyType: 'uint8',
128
+ collisionLayer: 'uint16'
129
+ }
130
+ ]);
131
+ rawConfig.components = Object.fromEntries(entries);
132
+ }
133
+ }
60
134
  const components = [];
61
135
  const singletons = [];
62
- // Parse components
136
+ // Parse components (ID is now a bit index: 0, 1, 2, ... instead of bitmask value)
63
137
  let componentIdx = 0;
64
138
  if (rawConfig.components) {
65
- for (const [componentName, componentFields] of Object.entries(rawConfig.components)){
139
+ for (const [componentName, rawComponentFields] of Object.entries(rawConfig.components)){
140
+ const componentFields = rawComponentFields != null ? rawComponentFields : {};
66
141
  const fields = {};
67
142
  for (const [fieldName, fieldType] of Object.entries(componentFields)){
68
143
  fields[fieldName] = parseFieldType(fieldType);
69
144
  }
145
+ const isTag = Object.keys(fields).length === 0;
70
146
  components.push({
71
147
  name: componentName,
72
- id: Math.pow(2, componentIdx++),
73
- fields
148
+ id: componentIdx++,
149
+ fields,
150
+ isTag
74
151
  });
75
152
  }
76
153
  }
154
+ // Validate component count (max 64 supported with two Uint32 mask words)
155
+ if (components.length > 64) {
156
+ throw new Error(`Too many components (${components.length}). Maximum supported is 64.`);
157
+ }
77
158
  // Parse singletons
78
159
  if (rawConfig.singletons) {
79
160
  for (const [singletonName, singletonFields] of Object.entries(rawConfig.singletons)){
@@ -128,6 +209,42 @@ export function parseYamlConfig(configContent, configPath) {
128
209
  });
129
210
  }
130
211
  }
212
+ // Auto-add PhysicsRefsFilter for physics3d
213
+ if (simulationType === 'physics3d') {
214
+ const hasPhysicsFilter = filters.some((f)=>f.name === 'PhysicsRefsFilter');
215
+ if (!hasPhysicsFilter) {
216
+ const physicsRefs = components.find((c)=>c.name === 'PhysicsRefs');
217
+ const transform3d = components.find((c)=>c.name === 'Transform3d');
218
+ if (physicsRefs && transform3d) {
219
+ filters.push({
220
+ name: 'PhysicsRefsFilter',
221
+ include: [
222
+ physicsRefs,
223
+ transform3d
224
+ ],
225
+ exclude: []
226
+ });
227
+ }
228
+ }
229
+ }
230
+ // Auto-add PhysicsRefsFilter for physics2d
231
+ if (simulationType === 'physics2d') {
232
+ const hasPhysicsFilter = filters.some((f)=>f.name === 'PhysicsRefsFilter');
233
+ if (!hasPhysicsFilter) {
234
+ const physicsRefs = components.find((c)=>c.name === 'PhysicsRefs');
235
+ const transform2d = components.find((c)=>c.name === 'Transform2d');
236
+ if (physicsRefs && transform2d) {
237
+ filters.push({
238
+ name: 'PhysicsRefsFilter',
239
+ include: [
240
+ physicsRefs,
241
+ transform2d
242
+ ],
243
+ exclude: []
244
+ });
245
+ }
246
+ }
247
+ }
131
248
  const inputs = new Array();
132
249
  // Parse inputs
133
250
  if (rawConfig.inputs) {
@@ -153,7 +270,8 @@ export function parseYamlConfig(configContent, configPath) {
153
270
  };
154
271
  return {
155
272
  schema,
156
- projectName
273
+ projectName,
274
+ simulationType
157
275
  };
158
276
  }
159
277
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parser.ts"],"sourcesContent":["import {\n getTypeSizeBytes,\n InputFieldDefinition,\n typeStringToFieldType,\n typeToArrayConstructor,\n} from '@lagless/binary';\nimport {\n ComponentDefinition,\n ECSSchema,\n FieldDefinition,\n FilterDefinition,\n IInputDefinition,\n PlayerResourceDefinition,\n SingletonDefinition,\n} from '@lagless/core';\nimport { parse } from 'yaml';\n\nexport interface ECSConfig {\n projectName?: string;\n components?: Record<string, Record<string, string>>;\n singletons?: Record<string, Record<string, string>>;\n playerResources?: Record<string, Record<string, string>>;\n filters?: Record<string, { include?: string[]; exclude?: string[] }>;\n inputs?: Record<string, Record<string, string>>;\n}\n\nexport function parseInputFieldType(fieldName: string, fieldType: string): InputFieldDefinition {\n const res = parseFieldType(fieldType);\n\n return {\n name: fieldName,\n ...res,\n type: typeStringToFieldType[res.type],\n byteLength: res.isArray && res.arrayLength ? getTypeSizeBytes(res.type) * res.arrayLength : getTypeSizeBytes(res.type),\n };\n}\n\nexport function parseFieldType(typeStr: string): FieldDefinition {\n const arrayMatch = typeStr.match(/^(\\w+)\\[(\\d+)]$/);\n if (arrayMatch) {\n const baseType = arrayMatch[1];\n const arrayLength = parseInt(arrayMatch[2], 10);\n\n if (!Object.keys(typeToArrayConstructor).includes(baseType)) {\n throw new Error(`Unsupported array base type: ${baseType}`);\n }\n\n if (arrayLength <= 0) {\n throw new Error(`Array length must be positive: ${arrayLength}`);\n }\n\n return {\n type: baseType,\n isArray: true,\n arrayLength,\n };\n } else {\n if (!Object.keys(typeToArrayConstructor).includes(typeStr)) {\n throw new Error(`Unsupported type: ${typeStr}`);\n }\n\n return {\n type: typeStr,\n isArray: false,\n };\n }\n}\n\nexport function getProjectNameFromConfigPath(configPath: string): string {\n let projectName = configPath.split('/').slice(-5)[0];\n projectName = projectName.slice(0, 1).toUpperCase() + projectName.slice(1);\n // kebab to PascalCase\n projectName = projectName.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());\n return projectName;\n}\n\nexport function parseYamlConfig(configContent: string, configPath?: string): { schema: ECSSchema; projectName: string } {\n const rawConfig = parse(configContent) as ECSConfig;\n\n if (!rawConfig.components && !rawConfig.singletons) {\n throw new Error('Config must contain at least one of: components, singletons');\n }\n\n // Determine project name: from config or from path\n let projectName: string;\n if (rawConfig.projectName) {\n projectName = rawConfig.projectName;\n } else if (configPath) {\n projectName = getProjectNameFromConfigPath(configPath);\n } else {\n throw new Error('projectName must be specified in config or configPath must be provided');\n }\n\n const components: ComponentDefinition[] = [];\n const singletons: SingletonDefinition[] = [];\n\n // Parse components\n let componentIdx = 0;\n if (rawConfig.components) {\n for (const [componentName, componentFields] of Object.entries<Record<string, string>>(rawConfig.components)) {\n const fields: Record<string, FieldDefinition> = {};\n\n for (const [fieldName, fieldType] of Object.entries<string>(componentFields)) {\n fields[fieldName] = parseFieldType(fieldType);\n }\n\n components.push({\n name: componentName,\n id: Math.pow(2, componentIdx++),\n fields,\n });\n }\n }\n\n // Parse singletons\n if (rawConfig.singletons) {\n for (const [singletonName, singletonFields] of Object.entries<Record<string, string>>(rawConfig.singletons)) {\n const fields: Record<string, FieldDefinition> = {};\n\n for (const [fieldName, fieldType] of Object.entries<string>(singletonFields)) {\n fields[fieldName] = parseFieldType(fieldType);\n }\n\n singletons.push({\n name: singletonName,\n fields,\n });\n }\n }\n\n const playerResources = new Array<PlayerResourceDefinition>();\n // Parse player resources\n if (rawConfig.playerResources) {\n for (const [resourceName, resourceFields] of Object.entries<Record<string, string>>(rawConfig.playerResources)) {\n const fields: Record<string, FieldDefinition> = {};\n\n for (const [fieldName, fieldType] of Object.entries<string>(resourceFields)) {\n fields[fieldName] = parseFieldType(fieldType);\n }\n\n playerResources.push({\n name: resourceName,\n fields,\n });\n }\n }\n\n const filters = new Array<FilterDefinition>();\n // Parse filters\n if (rawConfig.filters) {\n for (const [filterName, filterComponents] of Object.entries(rawConfig.filters)) {\n const include: ComponentDefinition[] = [];\n const exclude: ComponentDefinition[] = [];\n\n for (const componentName of filterComponents.include || []) {\n const component = components.find(c => c.name === componentName);\n if (!component) {\n throw new Error(`Component not found in schema: ${componentName}`);\n }\n include.push(component);\n }\n\n for (const componentName of filterComponents.exclude || []) {\n const component = components.find(c => c.name === componentName);\n if (!component) {\n throw new Error(`Component not found in schema: ${componentName}`);\n }\n exclude.push(component);\n }\n\n filters.push({\n name: filterName,\n include,\n exclude,\n });\n }\n }\n\n const inputs = new Array<IInputDefinition>();\n // Parse inputs\n if (rawConfig.inputs) {\n let inputIdx = 1;\n for (const [inputName, inputFields] of Object.entries<Record<string, string>>(rawConfig.inputs)) {\n const fields = new Array<InputFieldDefinition>();\n\n for (const [fieldName, fieldType] of Object.entries<string>(inputFields)) {\n fields.push(parseInputFieldType(fieldName, fieldType));\n }\n\n inputs.push({\n name: inputName,\n id: inputIdx++,\n fields,\n });\n }\n }\n\n const schema = { components, singletons, filters, playerResources, inputs };\n return { schema, projectName };\n}\n"],"names":["getTypeSizeBytes","typeStringToFieldType","typeToArrayConstructor","parse","parseInputFieldType","fieldName","fieldType","res","parseFieldType","name","type","byteLength","isArray","arrayLength","typeStr","arrayMatch","match","baseType","parseInt","Object","keys","includes","Error","getProjectNameFromConfigPath","configPath","projectName","split","slice","toUpperCase","replace","letter","parseYamlConfig","configContent","rawConfig","components","singletons","componentIdx","componentName","componentFields","entries","fields","push","id","Math","pow","singletonName","singletonFields","playerResources","Array","resourceName","resourceFields","filters","filterName","filterComponents","include","exclude","component","find","c","inputs","inputIdx","inputName","inputFields","schema"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,SACEA,gBAAgB,EAEhBC,qBAAqB,EACrBC,sBAAsB,QACjB,kBAAkB;AAUzB,SAASC,KAAK,QAAQ,OAAO;AAW7B,OAAO,SAASC,oBAAoBC,SAAiB,EAAEC,SAAiB;IACtE,MAAMC,MAAMC,eAAeF;IAE3B,OAAO;QACLG,MAAMJ;OACHE;QACHG,MAAMT,qBAAqB,CAACM,IAAIG,IAAI,CAAC;QACrCC,YAAYJ,IAAIK,OAAO,IAAIL,IAAIM,WAAW,GAAGb,iBAAiBO,IAAIG,IAAI,IAAIH,IAAIM,WAAW,GAAGb,iBAAiBO,IAAIG,IAAI;;AAEzH;AAEA,OAAO,SAASF,eAAeM,OAAe;IAC5C,MAAMC,aAAaD,QAAQE,KAAK,CAAC;IACjC,IAAID,YAAY;QACd,MAAME,WAAWF,UAAU,CAAC,EAAE;QAC9B,MAAMF,cAAcK,SAASH,UAAU,CAAC,EAAE,EAAE;QAE5C,IAAI,CAACI,OAAOC,IAAI,CAAClB,wBAAwBmB,QAAQ,CAACJ,WAAW;YAC3D,MAAM,IAAIK,MAAM,CAAC,6BAA6B,EAAEL,SAAS,CAAC;QAC5D;QAEA,IAAIJ,eAAe,GAAG;YACpB,MAAM,IAAIS,MAAM,CAAC,+BAA+B,EAAET,YAAY,CAAC;QACjE;QAEA,OAAO;YACLH,MAAMO;YACNL,SAAS;YACTC;QACF;IACF,OAAO;QACL,IAAI,CAACM,OAAOC,IAAI,CAAClB,wBAAwBmB,QAAQ,CAACP,UAAU;YAC1D,MAAM,IAAIQ,MAAM,CAAC,kBAAkB,EAAER,QAAQ,CAAC;QAChD;QAEA,OAAO;YACLJ,MAAMI;YACNF,SAAS;QACX;IACF;AACF;AAEA,OAAO,SAASW,6BAA6BC,UAAkB;IAC7D,IAAIC,cAAcD,WAAWE,KAAK,CAAC,KAAKC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE;IACpDF,cAAcA,YAAYE,KAAK,CAAC,GAAG,GAAGC,WAAW,KAAKH,YAAYE,KAAK,CAAC;IACxE,sBAAsB;IACtBF,cAAcA,YAAYI,OAAO,CAAC,aAAa,CAACb,OAAOc,SAAWA,OAAOF,WAAW;IACpF,OAAOH;AACT;AAEA,OAAO,SAASM,gBAAgBC,aAAqB,EAAER,UAAmB;IACxE,MAAMS,YAAY9B,MAAM6B;IAExB,IAAI,CAACC,UAAUC,UAAU,IAAI,CAACD,UAAUE,UAAU,EAAE;QAClD,MAAM,IAAIb,MAAM;IAClB;IAEA,mDAAmD;IACnD,IAAIG;IACJ,IAAIQ,UAAUR,WAAW,EAAE;QACzBA,cAAcQ,UAAUR,WAAW;IACrC,OAAO,IAAID,YAAY;QACrBC,cAAcF,6BAA6BC;IAC7C,OAAO;QACL,MAAM,IAAIF,MAAM;IAClB;IAEA,MAAMY,aAAoC,EAAE;IAC5C,MAAMC,aAAoC,EAAE;IAE5C,mBAAmB;IACnB,IAAIC,eAAe;IACnB,IAAIH,UAAUC,UAAU,EAAE;QACxB,KAAK,MAAM,CAACG,eAAeC,gBAAgB,IAAInB,OAAOoB,OAAO,CAAyBN,UAAUC,UAAU,EAAG;YAC3G,MAAMM,SAA0C,CAAC;YAEjD,KAAK,MAAM,CAACnC,WAAWC,UAAU,IAAIa,OAAOoB,OAAO,CAASD,iBAAkB;gBAC5EE,MAAM,CAACnC,UAAU,GAAGG,eAAeF;YACrC;YAEA4B,WAAWO,IAAI,CAAC;gBACdhC,MAAM4B;gBACNK,IAAIC,KAAKC,GAAG,CAAC,GAAGR;gBAChBI;YACF;QACF;IACF;IAEA,mBAAmB;IACnB,IAAIP,UAAUE,UAAU,EAAE;QACxB,KAAK,MAAM,CAACU,eAAeC,gBAAgB,IAAI3B,OAAOoB,OAAO,CAAyBN,UAAUE,UAAU,EAAG;YAC3G,MAAMK,SAA0C,CAAC;YAEjD,KAAK,MAAM,CAACnC,WAAWC,UAAU,IAAIa,OAAOoB,OAAO,CAASO,iBAAkB;gBAC5EN,MAAM,CAACnC,UAAU,GAAGG,eAAeF;YACrC;YAEA6B,WAAWM,IAAI,CAAC;gBACdhC,MAAMoC;gBACNL;YACF;QACF;IACF;IAEA,MAAMO,kBAAkB,IAAIC;IAC5B,yBAAyB;IACzB,IAAIf,UAAUc,eAAe,EAAE;QAC7B,KAAK,MAAM,CAACE,cAAcC,eAAe,IAAI/B,OAAOoB,OAAO,CAAyBN,UAAUc,eAAe,EAAG;YAC9G,MAAMP,SAA0C,CAAC;YAEjD,KAAK,MAAM,CAACnC,WAAWC,UAAU,IAAIa,OAAOoB,OAAO,CAASW,gBAAiB;gBAC3EV,MAAM,CAACnC,UAAU,GAAGG,eAAeF;YACrC;YAEAyC,gBAAgBN,IAAI,CAAC;gBACnBhC,MAAMwC;gBACNT;YACF;QACF;IACF;IAEA,MAAMW,UAAU,IAAIH;IACpB,gBAAgB;IAChB,IAAIf,UAAUkB,OAAO,EAAE;QACrB,KAAK,MAAM,CAACC,YAAYC,iBAAiB,IAAIlC,OAAOoB,OAAO,CAACN,UAAUkB,OAAO,EAAG;YAC9E,MAAMG,UAAiC,EAAE;YACzC,MAAMC,UAAiC,EAAE;YAEzC,KAAK,MAAMlB,iBAAiBgB,iBAAiBC,OAAO,IAAI,EAAE,CAAE;gBAC1D,MAAME,YAAYtB,WAAWuB,IAAI,CAACC,CAAAA,IAAKA,EAAEjD,IAAI,KAAK4B;gBAClD,IAAI,CAACmB,WAAW;oBACd,MAAM,IAAIlC,MAAM,CAAC,+BAA+B,EAAEe,cAAc,CAAC;gBACnE;gBACAiB,QAAQb,IAAI,CAACe;YACf;YAEA,KAAK,MAAMnB,iBAAiBgB,iBAAiBE,OAAO,IAAI,EAAE,CAAE;gBAC1D,MAAMC,YAAYtB,WAAWuB,IAAI,CAACC,CAAAA,IAAKA,EAAEjD,IAAI,KAAK4B;gBAClD,IAAI,CAACmB,WAAW;oBACd,MAAM,IAAIlC,MAAM,CAAC,+BAA+B,EAAEe,cAAc,CAAC;gBACnE;gBACAkB,QAAQd,IAAI,CAACe;YACf;YAEAL,QAAQV,IAAI,CAAC;gBACXhC,MAAM2C;gBACNE;gBACAC;YACF;QACF;IACF;IAEA,MAAMI,SAAS,IAAIX;IACnB,eAAe;IACf,IAAIf,UAAU0B,MAAM,EAAE;QACpB,IAAIC,WAAW;QACf,KAAK,MAAM,CAACC,WAAWC,YAAY,IAAI3C,OAAOoB,OAAO,CAAyBN,UAAU0B,MAAM,EAAG;YAC/F,MAAMnB,SAAS,IAAIQ;YAEnB,KAAK,MAAM,CAAC3C,WAAWC,UAAU,IAAIa,OAAOoB,OAAO,CAASuB,aAAc;gBACxEtB,OAAOC,IAAI,CAACrC,oBAAoBC,WAAWC;YAC7C;YAEAqD,OAAOlB,IAAI,CAAC;gBACVhC,MAAMoD;gBACNnB,IAAIkB;gBACJpB;YACF;QACF;IACF;IAEA,MAAMuB,SAAS;QAAE7B;QAAYC;QAAYgB;QAASJ;QAAiBY;IAAO;IAC1E,OAAO;QAAEI;QAAQtC;IAAY;AAC/B"}
1
+ {"version":3,"sources":["../src/parser.ts"],"sourcesContent":["import {\n getTypeSizeBytes,\n InputFieldDefinition,\n typeStringToFieldType,\n typeToArrayConstructor,\n} from '@lagless/binary';\nimport {\n ComponentDefinition,\n ECSSchema,\n FieldDefinition,\n FilterDefinition,\n IInputDefinition,\n PlayerResourceDefinition,\n SingletonDefinition,\n} from '@lagless/core';\nimport { parse } from 'yaml';\n\nexport type SimulationType = 'raw' | 'physics2d' | 'physics3d';\n\nexport interface ECSConfig {\n projectName?: string;\n simulationType?: SimulationType;\n components?: Record<string, Record<string, string> | null>;\n singletons?: Record<string, Record<string, string>>;\n playerResources?: Record<string, Record<string, string>>;\n filters?: Record<string, { include?: string[]; exclude?: string[] }>;\n inputs?: Record<string, Record<string, string>>;\n}\n\nexport function parseInputFieldType(fieldName: string, fieldType: string): InputFieldDefinition {\n const res = parseFieldType(fieldType);\n\n return {\n name: fieldName,\n ...res,\n type: typeStringToFieldType[res.type as keyof typeof typeStringToFieldType],\n byteLength: res.isArray && res.arrayLength ? getTypeSizeBytes(res.type) * res.arrayLength : getTypeSizeBytes(res.type),\n };\n}\n\nexport function parseFieldType(typeStr: string): FieldDefinition {\n const arrayMatch = typeStr.match(/^(\\w+)\\[(\\d+)]$/);\n if (arrayMatch) {\n const baseType = arrayMatch[1];\n const arrayLength = parseInt(arrayMatch[2], 10);\n\n if (!Object.keys(typeToArrayConstructor).includes(baseType)) {\n throw new Error(`Unsupported array base type: ${baseType}`);\n }\n\n if (arrayLength <= 0) {\n throw new Error(`Array length must be positive: ${arrayLength}`);\n }\n\n return {\n type: baseType,\n isArray: true,\n arrayLength,\n };\n } else {\n if (!Object.keys(typeToArrayConstructor).includes(typeStr)) {\n throw new Error(`Unsupported type: ${typeStr}`);\n }\n\n return {\n type: typeStr,\n isArray: false,\n };\n }\n}\n\nexport function getProjectNameFromConfigPath(configPath: string): string {\n let projectName = configPath.split('/').slice(-5)[0];\n projectName = projectName.slice(0, 1).toUpperCase() + projectName.slice(1);\n // kebab to PascalCase\n projectName = projectName.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());\n return projectName;\n}\n\nexport function parseYamlConfig(\n configContent: string,\n configPath?: string,\n): { schema: ECSSchema; projectName: string; simulationType: SimulationType } {\n const rawConfig = parse(configContent) as ECSConfig;\n\n if (!rawConfig.components && !rawConfig.singletons) {\n throw new Error('Config must contain at least one of: components, singletons');\n }\n\n const simulationType: SimulationType = rawConfig.simulationType ?? 'raw';\n\n // Determine project name: from config or from path\n let projectName: string;\n if (rawConfig.projectName) {\n projectName = rawConfig.projectName;\n } else if (configPath) {\n projectName = getProjectNameFromConfigPath(configPath);\n } else {\n throw new Error('projectName must be specified in config or configPath must be provided');\n }\n\n // Auto-prepend physics components if needed\n if (simulationType === 'physics3d') {\n if (!rawConfig.components) rawConfig.components = {};\n\n if (!rawConfig.components['Transform3d']) {\n rawConfig.components = {\n Transform3d: {\n positionX: 'float32',\n positionY: 'float32',\n positionZ: 'float32',\n rotationX: 'float32',\n rotationY: 'float32',\n rotationZ: 'float32',\n rotationW: 'float32',\n prevPositionX: 'float32',\n prevPositionY: 'float32',\n prevPositionZ: 'float32',\n prevRotationX: 'float32',\n prevRotationY: 'float32',\n prevRotationZ: 'float32',\n prevRotationW: 'float32',\n },\n ...rawConfig.components,\n };\n }\n\n if (!rawConfig.components['PhysicsRefs']) {\n // Insert after Transform3d\n const entries = Object.entries(rawConfig.components);\n const transform3dIdx = entries.findIndex(([name]) => name === 'Transform3d');\n const insertIdx = transform3dIdx >= 0 ? transform3dIdx + 1 : 0;\n entries.splice(insertIdx, 0, [\n 'PhysicsRefs',\n {\n bodyHandle: 'float64',\n colliderHandle: 'float64',\n bodyType: 'uint8',\n collisionLayer: 'uint16',\n },\n ]);\n rawConfig.components = Object.fromEntries(entries);\n }\n }\n\n // Auto-prepend physics2d components if needed\n if (simulationType === 'physics2d') {\n if (!rawConfig.components) rawConfig.components = {};\n\n if (!rawConfig.components['Transform2d']) {\n rawConfig.components = {\n Transform2d: {\n positionX: 'float32',\n positionY: 'float32',\n rotation: 'float32',\n prevPositionX: 'float32',\n prevPositionY: 'float32',\n prevRotation: 'float32',\n },\n ...rawConfig.components,\n };\n }\n\n if (!rawConfig.components['PhysicsRefs']) {\n // Insert after Transform2d\n const entries = Object.entries(rawConfig.components);\n const transform2dIdx = entries.findIndex(([name]) => name === 'Transform2d');\n const insertIdx = transform2dIdx >= 0 ? transform2dIdx + 1 : 0;\n entries.splice(insertIdx, 0, [\n 'PhysicsRefs',\n {\n bodyHandle: 'float64',\n colliderHandle: 'float64',\n bodyType: 'uint8',\n collisionLayer: 'uint16',\n },\n ]);\n rawConfig.components = Object.fromEntries(entries);\n }\n }\n\n const components: ComponentDefinition[] = [];\n const singletons: SingletonDefinition[] = [];\n\n // Parse components (ID is now a bit index: 0, 1, 2, ... instead of bitmask value)\n let componentIdx = 0;\n if (rawConfig.components) {\n for (const [componentName, rawComponentFields] of Object.entries(rawConfig.components)) {\n const componentFields = (rawComponentFields ?? {}) as Record<string, string>;\n const fields: Record<string, FieldDefinition> = {};\n\n for (const [fieldName, fieldType] of Object.entries<string>(componentFields)) {\n fields[fieldName] = parseFieldType(fieldType);\n }\n\n const isTag = Object.keys(fields).length === 0;\n\n components.push({\n name: componentName,\n id: componentIdx++,\n fields,\n isTag,\n });\n }\n }\n\n // Validate component count (max 64 supported with two Uint32 mask words)\n if (components.length > 64) {\n throw new Error(`Too many components (${components.length}). Maximum supported is 64.`);\n }\n\n // Parse singletons\n if (rawConfig.singletons) {\n for (const [singletonName, singletonFields] of Object.entries<Record<string, string>>(rawConfig.singletons)) {\n const fields: Record<string, FieldDefinition> = {};\n\n for (const [fieldName, fieldType] of Object.entries<string>(singletonFields)) {\n fields[fieldName] = parseFieldType(fieldType);\n }\n\n singletons.push({\n name: singletonName,\n fields,\n });\n }\n }\n\n const playerResources = new Array<PlayerResourceDefinition>();\n // Parse player resources\n if (rawConfig.playerResources) {\n for (const [resourceName, resourceFields] of Object.entries<Record<string, string>>(rawConfig.playerResources)) {\n const fields: Record<string, FieldDefinition> = {};\n\n for (const [fieldName, fieldType] of Object.entries<string>(resourceFields)) {\n fields[fieldName] = parseFieldType(fieldType);\n }\n\n playerResources.push({\n name: resourceName,\n fields,\n });\n }\n }\n\n const filters = new Array<FilterDefinition>();\n // Parse filters\n if (rawConfig.filters) {\n for (const [filterName, filterComponents] of Object.entries(rawConfig.filters)) {\n const include: ComponentDefinition[] = [];\n const exclude: ComponentDefinition[] = [];\n\n for (const componentName of filterComponents.include || []) {\n const component = components.find(c => c.name === componentName);\n if (!component) {\n throw new Error(`Component not found in schema: ${componentName}`);\n }\n include.push(component);\n }\n\n for (const componentName of filterComponents.exclude || []) {\n const component = components.find(c => c.name === componentName);\n if (!component) {\n throw new Error(`Component not found in schema: ${componentName}`);\n }\n exclude.push(component);\n }\n\n filters.push({\n name: filterName,\n include,\n exclude,\n });\n }\n }\n\n // Auto-add PhysicsRefsFilter for physics3d\n if (simulationType === 'physics3d') {\n const hasPhysicsFilter = filters.some((f) => f.name === 'PhysicsRefsFilter');\n if (!hasPhysicsFilter) {\n const physicsRefs = components.find((c) => c.name === 'PhysicsRefs');\n const transform3d = components.find((c) => c.name === 'Transform3d');\n if (physicsRefs && transform3d) {\n filters.push({\n name: 'PhysicsRefsFilter',\n include: [physicsRefs, transform3d],\n exclude: [],\n });\n }\n }\n }\n\n // Auto-add PhysicsRefsFilter for physics2d\n if (simulationType === 'physics2d') {\n const hasPhysicsFilter = filters.some((f) => f.name === 'PhysicsRefsFilter');\n if (!hasPhysicsFilter) {\n const physicsRefs = components.find((c) => c.name === 'PhysicsRefs');\n const transform2d = components.find((c) => c.name === 'Transform2d');\n if (physicsRefs && transform2d) {\n filters.push({\n name: 'PhysicsRefsFilter',\n include: [physicsRefs, transform2d],\n exclude: [],\n });\n }\n }\n }\n\n const inputs = new Array<IInputDefinition>();\n // Parse inputs\n if (rawConfig.inputs) {\n let inputIdx = 1;\n for (const [inputName, inputFields] of Object.entries<Record<string, string>>(rawConfig.inputs)) {\n const fields = new Array<InputFieldDefinition>();\n\n for (const [fieldName, fieldType] of Object.entries<string>(inputFields)) {\n fields.push(parseInputFieldType(fieldName, fieldType));\n }\n\n inputs.push({\n name: inputName,\n id: inputIdx++,\n fields,\n });\n }\n }\n\n const schema = { components, singletons, filters, playerResources, inputs };\n return { schema, projectName, simulationType };\n}\n"],"names":["getTypeSizeBytes","typeStringToFieldType","typeToArrayConstructor","parse","parseInputFieldType","fieldName","fieldType","res","parseFieldType","name","type","byteLength","isArray","arrayLength","typeStr","arrayMatch","match","baseType","parseInt","Object","keys","includes","Error","getProjectNameFromConfigPath","configPath","projectName","split","slice","toUpperCase","replace","letter","parseYamlConfig","configContent","rawConfig","components","singletons","simulationType","Transform3d","positionX","positionY","positionZ","rotationX","rotationY","rotationZ","rotationW","prevPositionX","prevPositionY","prevPositionZ","prevRotationX","prevRotationY","prevRotationZ","prevRotationW","entries","transform3dIdx","findIndex","insertIdx","splice","bodyHandle","colliderHandle","bodyType","collisionLayer","fromEntries","Transform2d","rotation","prevRotation","transform2dIdx","componentIdx","componentName","rawComponentFields","componentFields","fields","isTag","length","push","id","singletonName","singletonFields","playerResources","Array","resourceName","resourceFields","filters","filterName","filterComponents","include","exclude","component","find","c","hasPhysicsFilter","some","f","physicsRefs","transform3d","transform2d","inputs","inputIdx","inputName","inputFields","schema"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,SACEA,gBAAgB,EAEhBC,qBAAqB,EACrBC,sBAAsB,QACjB,kBAAkB;AAUzB,SAASC,KAAK,QAAQ,OAAO;AAc7B,OAAO,SAASC,oBAAoBC,SAAiB,EAAEC,SAAiB;IACtE,MAAMC,MAAMC,eAAeF;IAE3B,OAAO;QACLG,MAAMJ;OACHE;QACHG,MAAMT,qBAAqB,CAACM,IAAIG,IAAI,CAAuC;QAC3EC,YAAYJ,IAAIK,OAAO,IAAIL,IAAIM,WAAW,GAAGb,iBAAiBO,IAAIG,IAAI,IAAIH,IAAIM,WAAW,GAAGb,iBAAiBO,IAAIG,IAAI;;AAEzH;AAEA,OAAO,SAASF,eAAeM,OAAe;IAC5C,MAAMC,aAAaD,QAAQE,KAAK,CAAC;IACjC,IAAID,YAAY;QACd,MAAME,WAAWF,UAAU,CAAC,EAAE;QAC9B,MAAMF,cAAcK,SAASH,UAAU,CAAC,EAAE,EAAE;QAE5C,IAAI,CAACI,OAAOC,IAAI,CAAClB,wBAAwBmB,QAAQ,CAACJ,WAAW;YAC3D,MAAM,IAAIK,MAAM,CAAC,6BAA6B,EAAEL,SAAS,CAAC;QAC5D;QAEA,IAAIJ,eAAe,GAAG;YACpB,MAAM,IAAIS,MAAM,CAAC,+BAA+B,EAAET,YAAY,CAAC;QACjE;QAEA,OAAO;YACLH,MAAMO;YACNL,SAAS;YACTC;QACF;IACF,OAAO;QACL,IAAI,CAACM,OAAOC,IAAI,CAAClB,wBAAwBmB,QAAQ,CAACP,UAAU;YAC1D,MAAM,IAAIQ,MAAM,CAAC,kBAAkB,EAAER,QAAQ,CAAC;QAChD;QAEA,OAAO;YACLJ,MAAMI;YACNF,SAAS;QACX;IACF;AACF;AAEA,OAAO,SAASW,6BAA6BC,UAAkB;IAC7D,IAAIC,cAAcD,WAAWE,KAAK,CAAC,KAAKC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE;IACpDF,cAAcA,YAAYE,KAAK,CAAC,GAAG,GAAGC,WAAW,KAAKH,YAAYE,KAAK,CAAC;IACxE,sBAAsB;IACtBF,cAAcA,YAAYI,OAAO,CAAC,aAAa,CAACb,OAAOc,SAAWA,OAAOF,WAAW;IACpF,OAAOH;AACT;AAEA,OAAO,SAASM,gBACdC,aAAqB,EACrBR,UAAmB;IAEnB,MAAMS,YAAY9B,MAAM6B;IAExB,IAAI,CAACC,UAAUC,UAAU,IAAI,CAACD,UAAUE,UAAU,EAAE;QAClD,MAAM,IAAIb,MAAM;IAClB;QAEuCW;IAAvC,MAAMG,iBAAiCH,CAAAA,4BAAAA,UAAUG,cAAc,YAAxBH,4BAA4B;IAEnE,mDAAmD;IACnD,IAAIR;IACJ,IAAIQ,UAAUR,WAAW,EAAE;QACzBA,cAAcQ,UAAUR,WAAW;IACrC,OAAO,IAAID,YAAY;QACrBC,cAAcF,6BAA6BC;IAC7C,OAAO;QACL,MAAM,IAAIF,MAAM;IAClB;IAEA,4CAA4C;IAC5C,IAAIc,mBAAmB,aAAa;QAClC,IAAI,CAACH,UAAUC,UAAU,EAAED,UAAUC,UAAU,GAAG,CAAC;QAEnD,IAAI,CAACD,UAAUC,UAAU,CAAC,cAAc,EAAE;YACxCD,UAAUC,UAAU,GAAG;gBACrBG,aAAa;oBACXC,WAAW;oBACXC,WAAW;oBACXC,WAAW;oBACXC,WAAW;oBACXC,WAAW;oBACXC,WAAW;oBACXC,WAAW;oBACXC,eAAe;oBACfC,eAAe;oBACfC,eAAe;oBACfC,eAAe;oBACfC,eAAe;oBACfC,eAAe;oBACfC,eAAe;gBACjB;eACGlB,UAAUC,UAAU;QAE3B;QAEA,IAAI,CAACD,UAAUC,UAAU,CAAC,cAAc,EAAE;YACxC,2BAA2B;YAC3B,MAAMkB,UAAUjC,OAAOiC,OAAO,CAACnB,UAAUC,UAAU;YACnD,MAAMmB,iBAAiBD,QAAQE,SAAS,CAAC,CAAC,CAAC7C,KAAK,GAAKA,SAAS;YAC9D,MAAM8C,YAAYF,kBAAkB,IAAIA,iBAAiB,IAAI;YAC7DD,QAAQI,MAAM,CAACD,WAAW,GAAG;gBAC3B;gBACA;oBACEE,YAAY;oBACZC,gBAAgB;oBAChBC,UAAU;oBACVC,gBAAgB;gBAClB;aACD;YACD3B,UAAUC,UAAU,GAAGf,OAAO0C,WAAW,CAACT;QAC5C;IACF;IAEA,8CAA8C;IAC9C,IAAIhB,mBAAmB,aAAa;QAClC,IAAI,CAACH,UAAUC,UAAU,EAAED,UAAUC,UAAU,GAAG,CAAC;QAEnD,IAAI,CAACD,UAAUC,UAAU,CAAC,cAAc,EAAE;YACxCD,UAAUC,UAAU,GAAG;gBACrB4B,aAAa;oBACXxB,WAAW;oBACXC,WAAW;oBACXwB,UAAU;oBACVlB,eAAe;oBACfC,eAAe;oBACfkB,cAAc;gBAChB;eACG/B,UAAUC,UAAU;QAE3B;QAEA,IAAI,CAACD,UAAUC,UAAU,CAAC,cAAc,EAAE;YACxC,2BAA2B;YAC3B,MAAMkB,UAAUjC,OAAOiC,OAAO,CAACnB,UAAUC,UAAU;YACnD,MAAM+B,iBAAiBb,QAAQE,SAAS,CAAC,CAAC,CAAC7C,KAAK,GAAKA,SAAS;YAC9D,MAAM8C,YAAYU,kBAAkB,IAAIA,iBAAiB,IAAI;YAC7Db,QAAQI,MAAM,CAACD,WAAW,GAAG;gBAC3B;gBACA;oBACEE,YAAY;oBACZC,gBAAgB;oBAChBC,UAAU;oBACVC,gBAAgB;gBAClB;aACD;YACD3B,UAAUC,UAAU,GAAGf,OAAO0C,WAAW,CAACT;QAC5C;IACF;IAEA,MAAMlB,aAAoC,EAAE;IAC5C,MAAMC,aAAoC,EAAE;IAE5C,kFAAkF;IAClF,IAAI+B,eAAe;IACnB,IAAIjC,UAAUC,UAAU,EAAE;QACxB,KAAK,MAAM,CAACiC,eAAeC,mBAAmB,IAAIjD,OAAOiC,OAAO,CAACnB,UAAUC,UAAU,EAAG;YACtF,MAAMmC,kBAAmBD,6BAAAA,qBAAsB,CAAC;YAChD,MAAME,SAA0C,CAAC;YAEjD,KAAK,MAAM,CAACjE,WAAWC,UAAU,IAAIa,OAAOiC,OAAO,CAASiB,iBAAkB;gBAC5EC,MAAM,CAACjE,UAAU,GAAGG,eAAeF;YACrC;YAEA,MAAMiE,QAAQpD,OAAOC,IAAI,CAACkD,QAAQE,MAAM,KAAK;YAE7CtC,WAAWuC,IAAI,CAAC;gBACdhE,MAAM0D;gBACNO,IAAIR;gBACJI;gBACAC;YACF;QACF;IACF;IAEA,yEAAyE;IACzE,IAAIrC,WAAWsC,MAAM,GAAG,IAAI;QAC1B,MAAM,IAAIlD,MAAM,CAAC,qBAAqB,EAAEY,WAAWsC,MAAM,CAAC,2BAA2B,CAAC;IACxF;IAEA,mBAAmB;IACnB,IAAIvC,UAAUE,UAAU,EAAE;QACxB,KAAK,MAAM,CAACwC,eAAeC,gBAAgB,IAAIzD,OAAOiC,OAAO,CAAyBnB,UAAUE,UAAU,EAAG;YAC3G,MAAMmC,SAA0C,CAAC;YAEjD,KAAK,MAAM,CAACjE,WAAWC,UAAU,IAAIa,OAAOiC,OAAO,CAASwB,iBAAkB;gBAC5EN,MAAM,CAACjE,UAAU,GAAGG,eAAeF;YACrC;YAEA6B,WAAWsC,IAAI,CAAC;gBACdhE,MAAMkE;gBACNL;YACF;QACF;IACF;IAEA,MAAMO,kBAAkB,IAAIC;IAC5B,yBAAyB;IACzB,IAAI7C,UAAU4C,eAAe,EAAE;QAC7B,KAAK,MAAM,CAACE,cAAcC,eAAe,IAAI7D,OAAOiC,OAAO,CAAyBnB,UAAU4C,eAAe,EAAG;YAC9G,MAAMP,SAA0C,CAAC;YAEjD,KAAK,MAAM,CAACjE,WAAWC,UAAU,IAAIa,OAAOiC,OAAO,CAAS4B,gBAAiB;gBAC3EV,MAAM,CAACjE,UAAU,GAAGG,eAAeF;YACrC;YAEAuE,gBAAgBJ,IAAI,CAAC;gBACnBhE,MAAMsE;gBACNT;YACF;QACF;IACF;IAEA,MAAMW,UAAU,IAAIH;IACpB,gBAAgB;IAChB,IAAI7C,UAAUgD,OAAO,EAAE;QACrB,KAAK,MAAM,CAACC,YAAYC,iBAAiB,IAAIhE,OAAOiC,OAAO,CAACnB,UAAUgD,OAAO,EAAG;YAC9E,MAAMG,UAAiC,EAAE;YACzC,MAAMC,UAAiC,EAAE;YAEzC,KAAK,MAAMlB,iBAAiBgB,iBAAiBC,OAAO,IAAI,EAAE,CAAE;gBAC1D,MAAME,YAAYpD,WAAWqD,IAAI,CAACC,CAAAA,IAAKA,EAAE/E,IAAI,KAAK0D;gBAClD,IAAI,CAACmB,WAAW;oBACd,MAAM,IAAIhE,MAAM,CAAC,+BAA+B,EAAE6C,cAAc,CAAC;gBACnE;gBACAiB,QAAQX,IAAI,CAACa;YACf;YAEA,KAAK,MAAMnB,iBAAiBgB,iBAAiBE,OAAO,IAAI,EAAE,CAAE;gBAC1D,MAAMC,YAAYpD,WAAWqD,IAAI,CAACC,CAAAA,IAAKA,EAAE/E,IAAI,KAAK0D;gBAClD,IAAI,CAACmB,WAAW;oBACd,MAAM,IAAIhE,MAAM,CAAC,+BAA+B,EAAE6C,cAAc,CAAC;gBACnE;gBACAkB,QAAQZ,IAAI,CAACa;YACf;YAEAL,QAAQR,IAAI,CAAC;gBACXhE,MAAMyE;gBACNE;gBACAC;YACF;QACF;IACF;IAEA,2CAA2C;IAC3C,IAAIjD,mBAAmB,aAAa;QAClC,MAAMqD,mBAAmBR,QAAQS,IAAI,CAAC,CAACC,IAAMA,EAAElF,IAAI,KAAK;QACxD,IAAI,CAACgF,kBAAkB;YACrB,MAAMG,cAAc1D,WAAWqD,IAAI,CAAC,CAACC,IAAMA,EAAE/E,IAAI,KAAK;YACtD,MAAMoF,cAAc3D,WAAWqD,IAAI,CAAC,CAACC,IAAMA,EAAE/E,IAAI,KAAK;YACtD,IAAImF,eAAeC,aAAa;gBAC9BZ,QAAQR,IAAI,CAAC;oBACXhE,MAAM;oBACN2E,SAAS;wBAACQ;wBAAaC;qBAAY;oBACnCR,SAAS,EAAE;gBACb;YACF;QACF;IACF;IAEA,2CAA2C;IAC3C,IAAIjD,mBAAmB,aAAa;QAClC,MAAMqD,mBAAmBR,QAAQS,IAAI,CAAC,CAACC,IAAMA,EAAElF,IAAI,KAAK;QACxD,IAAI,CAACgF,kBAAkB;YACrB,MAAMG,cAAc1D,WAAWqD,IAAI,CAAC,CAACC,IAAMA,EAAE/E,IAAI,KAAK;YACtD,MAAMqF,cAAc5D,WAAWqD,IAAI,CAAC,CAACC,IAAMA,EAAE/E,IAAI,KAAK;YACtD,IAAImF,eAAeE,aAAa;gBAC9Bb,QAAQR,IAAI,CAAC;oBACXhE,MAAM;oBACN2E,SAAS;wBAACQ;wBAAaE;qBAAY;oBACnCT,SAAS,EAAE;gBACb;YACF;QACF;IACF;IAEA,MAAMU,SAAS,IAAIjB;IACnB,eAAe;IACf,IAAI7C,UAAU8D,MAAM,EAAE;QACpB,IAAIC,WAAW;QACf,KAAK,MAAM,CAACC,WAAWC,YAAY,IAAI/E,OAAOiC,OAAO,CAAyBnB,UAAU8D,MAAM,EAAG;YAC/F,MAAMzB,SAAS,IAAIQ;YAEnB,KAAK,MAAM,CAACzE,WAAWC,UAAU,IAAIa,OAAOiC,OAAO,CAAS8C,aAAc;gBACxE5B,OAAOG,IAAI,CAACrE,oBAAoBC,WAAWC;YAC7C;YAEAyF,OAAOtB,IAAI,CAAC;gBACVhE,MAAMwF;gBACNvB,IAAIsB;gBACJ1B;YACF;QACF;IACF;IAEA,MAAM6B,SAAS;QAAEjE;QAAYC;QAAY8C;QAASJ;QAAiBkB;IAAO;IAC1E,OAAO;QAAEI;QAAQ1E;QAAaW;IAAe;AAC/C"}
@@ -0,0 +1,31 @@
1
+ export interface FileOperations {
2
+ readFile: (path: string) => string;
3
+ writeFile: (path: string, content: string) => void;
4
+ joinPath: (...segments: string[]) => string;
5
+ exists: (path: string) => boolean;
6
+ readDir?: (path: string) => string[];
7
+ isDirectory?: (path: string) => boolean;
8
+ }
9
+ export interface TemplateOptions {
10
+ templateDir: string;
11
+ outputDir: string;
12
+ data: any;
13
+ fileOperations: FileOperations;
14
+ }
15
+ export interface TemplateFile {
16
+ fullPath: string;
17
+ relativePath: string;
18
+ outputPath: string;
19
+ }
20
+ export declare class TemplateEngine {
21
+ private fileOps;
22
+ constructor(fileOperations: FileOperations);
23
+ generateFromTemplate(options: TemplateOptions): Promise<void>;
24
+ private findTemplateFiles;
25
+ private isTemplateFile;
26
+ private getOutputPath;
27
+ private processTemplateFile;
28
+ private processFileName;
29
+ }
30
+ export declare function generateFromTemplate(options: TemplateOptions): Promise<void>;
31
+ //# sourceMappingURL=template-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-engine.d.ts","sourceRoot":"","sources":["../src/template-engine.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACrC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,GAAG,CAAC;IACV,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiB;gBAEpB,cAAc,EAAE,cAAc;IAIpC,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBnE,OAAO,CAAC,iBAAiB;IA4DzB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,aAAa;YAaP,mBAAmB;IA6BjC,OAAO,CAAC,eAAe;CAmBxB;AAGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5E"}
@@ -1,6 +1,19 @@
1
1
  // Generated by @lagless/codegen. Do not edit manually.
2
2
  import { MemoryTracker } from '@lagless/binary';
3
+ <% if (component.isTag) { %>
4
+ /* eslint-disable @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars */
5
+ export class <%= component.name %> {
6
+ public static readonly ID = <%= component.id %>;
7
+ public static readonly IS_TAG = true;
8
+ public static readonly schema = {};
9
+
10
+ public readonly unsafe = {} as Record<string, never>;
3
11
 
12
+ constructor(_maxEntities: number, _buffer: ArrayBuffer, _memTracker: MemoryTracker) {}
13
+
14
+ public static calculateSize(_maxEntities: number, _memTracker: MemoryTracker): void {}
15
+ }
16
+ <% } else { %>
4
17
  export class <%= component.name %> {
5
18
  public static readonly ID = <%= component.id %>;
6
19
  public static readonly schema = {
@@ -29,11 +42,10 @@ export class <%= component.name %> {
29
42
  }
30
43
 
31
44
  constructor(maxEntities: number, buffer: ArrayBuffer, memTracker: MemoryTracker) {
32
- for (const [fieldName, TypedArrayConstructor] of Object.entries(<%= component.name %>.schema)) {
33
- const typedArray = new TypedArrayConstructor(buffer, memTracker.ptr, maxEntities);
34
- this.unsafe[fieldName as keyof typeof <%= component.name %>.schema] = typedArray as <%= component.name %>['unsafe'][keyof <%= component.name %>['unsafe']];
35
- memTracker.add(typedArray.byteLength);
36
- }
45
+ <% for (const [fieldName, field] of Object.entries(fields)) { %>
46
+ this.unsafe.<%= fieldName %> = new <%= typeToArrayConstructor[field.type].name %>(buffer, memTracker.ptr, maxEntities);
47
+ memTracker.add(this.unsafe.<%= fieldName %>.byteLength);
48
+ <% } %>
37
49
 
38
50
  // eslint-disable-next-line @typescript-eslint/no-this-alias
39
51
  const self = this;
@@ -61,5 +73,5 @@ export class <%= component.name %> {
61
73
  }
62
74
  }
63
75
  }
64
-
76
+ <% } %>
65
77
  Object.defineProperty(<%= component.name %>, 'name', { value: '<%= component.name %>' });
@@ -6,8 +6,8 @@ export class <%= filter.name %> extends AbstractFilter {
6
6
  public static readonly include: Array<IComponentConstructor> = [<%= filter.include.map(({ name }) => name).join(',') %>];
7
7
  public static readonly exclude: Array<IComponentConstructor> = [<%= filter.exclude.map(({ name }) => name).join(',') %>];
8
8
 
9
- public readonly includeMask: number = <%= includeMask %>;
10
- public readonly excludeMask: number = <%= excludeMask %>;
9
+ public readonly includeMask: number[] = [<%= includeMaskWords.join(', ') %>];
10
+ public readonly excludeMask: number[] = [<%= excludeMaskWords.join(', ') %>];
11
11
  }
12
12
 
13
13
  Object.defineProperty(<%= filter.name %>, 'name', { value: '<%= filter.name %>' });
@@ -0,0 +1,19 @@
1
+ // Generated by @lagless/codegen. Do not edit manually.
2
+ import { AbstractInputProvider, ECSConfig } from '@lagless/core';
3
+ import { IECSSystemConstructor, ISignalConstructor } from '@lagless/core';
4
+ import { PhysicsRunner2d, PhysicsConfig2d, RapierModule2d } from '@lagless/physics2d';
5
+
6
+ import { <%= projectName %>Core } from './<%= projectName %>.core.js';
7
+
8
+ export class <%= projectName %>Runner extends PhysicsRunner2d {
9
+ constructor(
10
+ Config: ECSConfig,
11
+ InputProviderInstance: AbstractInputProvider,
12
+ Systems: Array<IECSSystemConstructor>,
13
+ Signals: Array<ISignalConstructor> = [],
14
+ rapier: RapierModule2d,
15
+ physicsConfig?: PhysicsConfig2d,
16
+ ) {
17
+ super(Config, InputProviderInstance, Systems, Signals, <%= projectName %>Core, rapier, physicsConfig);
18
+ }
19
+ }
@@ -0,0 +1,22 @@
1
+ // Generated by @lagless/codegen. Do not edit manually.
2
+ import { AbstractInputProvider, ECSConfig } from '@lagless/core';
3
+ import { IECSSystemConstructor, ISignalConstructor } from '@lagless/core';
4
+ import { PhysicsRunner3d, PhysicsConfig3d, RapierModule3d } from '@lagless/physics3d';
5
+ import { CollisionLayers } from '@lagless/physics-shared';
6
+
7
+ import { <%= projectName %>Core } from './<%= projectName %>.core.js';
8
+
9
+ export class <%= projectName %>Runner extends PhysicsRunner3d {
10
+ constructor(
11
+ Config: ECSConfig,
12
+ InputProviderInstance: AbstractInputProvider,
13
+ Systems: Array<IECSSystemConstructor>,
14
+ Signals: Array<ISignalConstructor> = [],
15
+ rapier: RapierModule3d,
16
+ physicsConfig?: PhysicsConfig3d,
17
+ collisionLayers?: CollisionLayers,
18
+ extraRegistrations?: Array<[unknown, unknown]>,
19
+ ) {
20
+ super(Config, InputProviderInstance, Systems, Signals, <%= projectName %>Core, rapier, physicsConfig, collisionLayers, extraRegistrations);
21
+ }
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lagless/codegen",
3
- "version": "0.0.35",
3
+ "version": "0.0.38",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -43,20 +43,19 @@
43
43
  "outputPath": "tools/codegen/dist",
44
44
  "main": "tools/codegen/src/index.ts",
45
45
  "tsConfig": "tools/codegen/tsconfig.lib.json",
46
- "skipTypeCheck": true,
47
46
  "stripLeadingPaths": true
48
47
  }
49
48
  }
50
49
  }
51
50
  },
52
51
  "dependencies": {
53
- "tslib": "^2.3.0",
52
+ "@nx/devkit": "^21.6.4",
54
53
  "commander": "^14.0.1",
55
54
  "yaml": "^2.8.1",
56
55
  "ejs": "^3.1.10",
57
56
  "@swc/helpers": "~0.5.11",
58
- "@lagless/binary": "0.0.35",
59
- "@lagless/core": "0.0.35"
57
+ "@lagless/binary": "0.0.38",
58
+ "@lagless/core": "0.0.38"
60
59
  },
61
60
  "devDependencies": {
62
61
  "@types/ejs": "^3.1.5"