game-data-gen 5.0.0 → 6.0.0

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/README.md CHANGED
@@ -31,55 +31,105 @@ npm i -D game-data-gen
31
31
  npx game-data-gen <input-file-path> <optional-output-file-path>
32
32
  ```
33
33
 
34
- ## Supported fields
34
+ ## Types
35
35
 
36
- ### group
36
+ Each block in the Markdown file starts with a heading that defines the type, followed by a list of fields.
37
37
 
38
- | Field type | Example |
39
- | ------------------ | ------------------------ |
40
- | (none) | `- health` |
41
- | `int8 <length>` | `- ids int8 64` |
42
- | `int16 <length>` | `- ids int16 64` |
43
- | `int32 <length>` | `- ids int32 64` |
44
- | `uint8 <length>` | `- ids uint8 64` |
45
- | `uint16 <length>` | `- ids uint16 64` |
46
- | `uint32 <length>` | `- ids uint32 64` |
47
- | `float32 <length>` | `- positions float32 64` |
48
- | `float64 <length>` | `- positions float64 64` |
38
+ ### Group
49
39
 
50
- Whether a field is a scalar or an array is derived from whether a length is provided. A scalar field generates a plain `number`. An array field generates a typed array with a `count` variable and `push`/`pop` functions to simulate a dynamic array within the fixed capacity.
40
+ ```
41
+ # <name> group
42
+ ```
43
+
44
+ A set of module-level variables with individual setter and zero functions, plus a combined zero function.
45
+
46
+ | Field type | Description |
47
+ | ----------- | --------------------------- |
48
+ | `string` | A string primitive |
49
+ | `number` | A number primitive |
50
+ | `boolean` | A boolean primitive |
51
+ | `string[]` | A dynamic array of strings |
52
+ | `number[]` | A dynamic array of numbers |
53
+ | `boolean[]` | A dynamic array of booleans |
54
+
55
+ ### Structure of Arrays (SOA)
56
+
57
+ ```
58
+ # <name> soa <capacity>
59
+ ```
51
60
 
52
- ### soa (Structure of Arrays)
61
+ A set of typed arrays of fixed capacity, ideal for cache-friendly iteration over many elements.
53
62
 
54
- | Field type | Example |
63
+ | Field type | Typed array |
55
64
  | ---------- | -------------- |
56
- | `int8` | `- val int8` |
57
- | `int16` | `- val int16` |
58
- | `int32` | `- val int32` |
59
- | `uint8` | `- val uint8` |
60
- | `uint16` | `- val uint16` |
61
- | `uint32` | `- val uint32` |
62
- | `float32` | `- x float32` |
63
- | `float64` | `- x float64` |
65
+ | `int8` | `Int8Array` |
66
+ | `int16` | `Int16Array` |
67
+ | `int32` | `Int32Array` |
68
+ | `uint8` | `Uint8Array` |
69
+ | `uint16` | `Uint16Array` |
70
+ | `uint32` | `Uint32Array` |
71
+ | `float32` | `Float32Array` |
72
+ | `float64` | `Float64Array` |
64
73
 
65
- ## Example
74
+ ### Struct
75
+
76
+ ```
77
+ # <name> struct
78
+ ```
79
+
80
+ A TypeScript type with create, copy, and zero functions. Fields can be primitives, primitive arrays, or other structs.
81
+
82
+ | Field type | Description |
83
+ | ----------- | ---------------------------------------------------- |
84
+ | `string` | A string primitive |
85
+ | `number` | A number primitive |
86
+ | `boolean` | A boolean primitive |
87
+ | `string[]` | A dynamic array of strings |
88
+ | `number[]` | A dynamic array of numbers |
89
+ | `boolean[]` | A dynamic array of booleans |
90
+ | `<name>` | A nested struct (must be defined before this struct) |
91
+
92
+ ### Array of Structures (AOS)
66
93
 
67
- Create a Markdown file somewhere in your source code.
94
+ ```
95
+ # <name> aos <capacity> <struct>
96
+ ```
97
+
98
+ A pre-allocated fixed-length array of struct objects.
99
+
100
+ ## Example
68
101
 
69
- For example `src/data.md`:
102
+ Create a Markdown file somewhere in your source code, for example `src/data.md`:
70
103
 
71
104
  ```md
72
- # game
105
+ # game group
106
+
107
+ - score number
108
+ - name string
109
+ - isPaused boolean
110
+ - enemies number[]
111
+
112
+ # particles soa 256
113
+
114
+ - x float32
115
+ - y float32
116
+ - lifetime float32
117
+ - type int8
73
118
 
74
- - playerId
75
- - enemies uint16 64
119
+ # Vector2 struct
76
120
 
77
- # entity 1000
121
+ - x number
122
+ - y number
78
123
 
79
- - type uint8
80
- - posX float32
81
- - posY float32
82
- - health uint16
124
+ # Entity struct
125
+
126
+ - name string
127
+ - health number
128
+ - isActive boolean
129
+ - position Vector2
130
+ - tags string[]
131
+
132
+ # entities aos 64 Entity
83
133
  ```
84
134
 
85
135
  Run the package with (consider making this a script in your package.json):
@@ -97,78 +147,180 @@ This will create or update the `src/data.ts` file (see below). The data and func
97
147
  * --------------------------------------------------
98
148
  */
99
149
 
100
- export let playerId = 0;
101
- export const enemies = new Uint16Array(64);
102
- export let enemiesCount = 0;
150
+ export let score = 0;
151
+ export let name = "";
152
+ export let isPaused = false;
153
+ export const enemies: Array<number> = [];
154
+
155
+ /** Set the value of the score field within the game group. */
156
+ export function setScore(v: number) {
157
+ score = v;
158
+ }
103
159
 
104
- /** Set the value of the playerId field within the game group. */
105
- export function setPlayerId(v: number) {
106
- playerId = v;
160
+ /** Set the value of the name field within the game group. */
161
+ export function setName(v: string) {
162
+ name = v;
107
163
  }
108
164
 
109
- /** Push a value onto the enemies field within the game group. */
110
- export function pushEnemies(v: number) {
111
- enemies[enemiesCount++] = v;
165
+ /** Set the value of the isPaused field within the game group. */
166
+ export function setIsPaused(v: boolean) {
167
+ isPaused = v;
112
168
  }
113
169
 
114
- /** Pop a value from the enemies field within the game group. */
115
- export function popEnemies() {
116
- return enemies[--enemiesCount];
170
+ /** Zero the score field within the game group. */
171
+ export function zeroScore() {
172
+ score = 0;
117
173
  }
118
174
 
119
- /** Zero the playerId field within the game group. */
120
- export function zeroPlayerId() {
121
- playerId = 0;
175
+ /** Zero the name field within the game group. */
176
+ export function zeroName() {
177
+ name = "";
178
+ }
179
+
180
+ /** Zero the isPaused field within the game group. */
181
+ export function zeroIsPaused() {
182
+ isPaused = false;
122
183
  }
123
184
 
124
185
  /** Zero the enemies field within the game group. */
125
186
  export function zeroEnemies() {
126
- enemiesCount = 0;
187
+ enemies.length = 0;
127
188
  }
128
189
 
129
190
  /** Zero all fields within the game group. */
130
191
  export function zeroGame() {
131
- playerId = 0;
132
- enemiesCount = 0;
192
+ score = 0;
193
+ name = "";
194
+ isPaused = false;
195
+ enemies.length = 0;
133
196
  }
134
197
 
135
198
  /*
136
199
  * --------------------------------------------------
137
- * entity (Structure Of Arrays)
200
+ * particles (Structure Of Arrays)
138
201
  * --------------------------------------------------
139
202
  */
140
203
 
141
- export const MAX_ENTITY_COUNT = 1000;
204
+ export const MAX_PARTICLES_COUNT = 256;
142
205
 
143
- export const type = new Uint8Array(1000);
144
- export const posX = new Float32Array(1000);
145
- export const posY = new Float32Array(1000);
146
- export const health = new Uint16Array(1000);
206
+ export const x = new Float32Array(256);
207
+ export const y = new Float32Array(256);
208
+ export const lifetime = new Float32Array(256);
209
+ export const type = new Int8Array(256);
147
210
 
148
- /** Zero an index within the entity structure of arrays. */
149
- export function zeroEntityAt(i: number) {
211
+ /** Zero an index within the particles structure of arrays. */
212
+ export function zeroParticlesAt(i: number) {
213
+ x[i] = 0;
214
+ y[i] = 0;
215
+ lifetime[i] = 0;
150
216
  type[i] = 0;
151
- posX[i] = 0;
152
- posY[i] = 0;
153
- health[i] = 0;
154
217
  }
155
218
 
156
- /** Zero all fields within the entity structure of arrays. */
157
- export function zeroEntity() {
219
+ /** Zero all fields within the particles structure of arrays. */
220
+ export function zeroParticles() {
221
+ x.fill(0);
222
+ y.fill(0);
223
+ lifetime.fill(0);
158
224
  type.fill(0);
159
- posX.fill(0);
160
- posY.fill(0);
161
- health.fill(0);
162
225
  }
163
- ```
164
226
 
165
- The `enemies` array in the group acts as a dynamic list within its fixed capacity. Iterate only the active entries using the generated `count`:
227
+ /*
228
+ * --------------------------------------------------
229
+ * Vector2 (Struct)
230
+ * --------------------------------------------------
231
+ */
166
232
 
167
- ```typescript
168
- import { enemies, enemiesCount } from "./data.ts";
233
+ export type Vector2 = {
234
+ x: number;
235
+ y: number;
236
+ };
237
+
238
+ /** Create a new Vector2 object. */
239
+ export function createVector2() {
240
+ const obj: Vector2 = Object.create(null);
241
+ obj.x = 0;
242
+ obj.y = 0;
243
+ return obj;
244
+ }
245
+
246
+ /** Copy the values of Vector2 object b into Vector2 object a. */
247
+ export function copyVector2(a: Vector2, b: Vector2) {
248
+ a.x = b.x;
249
+ a.y = b.y;
250
+ }
251
+
252
+ /** Zero the given Vector2 object. */
253
+ export function zeroVector2(obj: Vector2) {
254
+ obj.x = 0;
255
+ obj.y = 0;
256
+ }
257
+
258
+ /*
259
+ * --------------------------------------------------
260
+ * Entity (Struct)
261
+ * --------------------------------------------------
262
+ */
263
+
264
+ export type Entity = {
265
+ name: string;
266
+ health: number;
267
+ isActive: boolean;
268
+ position: Vector2;
269
+ tags: string[];
270
+ };
271
+
272
+ /** Create a new Entity object. */
273
+ export function createEntity() {
274
+ const obj: Entity = Object.create(null);
275
+ obj.name = "";
276
+ obj.health = 0;
277
+ obj.isActive = false;
278
+ obj.position = createVector2();
279
+ obj.tags = [];
280
+ return obj;
281
+ }
282
+
283
+ /** Copy the values of Entity object b into Entity object a. */
284
+ export function copyEntity(a: Entity, b: Entity) {
285
+ a.name = b.name;
286
+ a.health = b.health;
287
+ a.isActive = b.isActive;
288
+ copyVector2(a.position, b.position);
289
+ a.tags.length = b.tags.length;
290
+ for (let i = 0; i < b.tags.length; i++) {
291
+ a.tags[i] = b.tags[i];
292
+ }
293
+ }
294
+
295
+ /** Zero the given Entity object. */
296
+ export function zeroEntity(obj: Entity) {
297
+ obj.name = "";
298
+ obj.health = 0;
299
+ obj.isActive = false;
300
+ zeroVector2(obj.position);
301
+ obj.tags.length = 0;
302
+ }
303
+
304
+ /*
305
+ * --------------------------------------------------
306
+ * entities (Array Of Structures)
307
+ * --------------------------------------------------
308
+ */
309
+
310
+ export const MAX_ENTITIES_COUNT = 64;
311
+
312
+ /** An array of Entity objects (structures). */
313
+ export const entities = Array.from({ length: 64 }, createEntity);
314
+
315
+ /** Zero all objects within the entities array of structures. */
316
+ export function zeroEntities() {
317
+ for (let i = 0; i < 64; i++) {
318
+ zeroEntity(entities[i]);
319
+ }
320
+ }
169
321
 
170
- for (let i = 0; i < enemiesCount; i++) {
171
- const id = enemies[i];
172
- // ...
322
+ /** Zero an object at a specific index within the entities array of structures. */
323
+ export function zeroEntitiesAt(index: number) {
324
+ zeroEntity(entities[index]);
173
325
  }
174
326
  ```
package/dist/consts.js CHANGED
@@ -1,5 +1,13 @@
1
+ export var Type;
2
+ (function (Type) {
3
+ Type["GROUP"] = "group";
4
+ Type["STRUCT"] = "struct";
5
+ Type["STRUCTURE_OF_ARRAYS"] = "soa";
6
+ Type["ARRAY_OF_STRUCTURES"] = "aos";
7
+ })(Type || (Type = {}));
1
8
  export var FieldType;
2
9
  (function (FieldType) {
10
+ // Structure of Arrays
3
11
  FieldType["INT_8"] = "int8";
4
12
  FieldType["INT_16"] = "int16";
5
13
  FieldType["INT_32"] = "int32";
@@ -8,4 +16,12 @@ export var FieldType;
8
16
  FieldType["UINT_32"] = "uint32";
9
17
  FieldType["FLOAT_32"] = "float32";
10
18
  FieldType["FLOAT_64"] = "float64";
19
+ // Struct / Group
20
+ FieldType["STRING"] = "string";
21
+ FieldType["NUMBER"] = "number";
22
+ FieldType["BOOLEAN"] = "boolean";
23
+ // Primitive arrays (Group and Struct)
24
+ FieldType["ARRAY_STRING"] = "string[]";
25
+ FieldType["ARRAY_NUMBER"] = "number[]";
26
+ FieldType["ARRAY_BOOLEAN"] = "boolean[]";
11
27
  })(FieldType || (FieldType = {}));
package/dist/lib/aos.js CHANGED
@@ -1,31 +1,33 @@
1
1
  import { addHeader, capitalize } from "./utils.js";
2
2
  export function addArrayOfStructures(header, output) {
3
- const [name, , length, type] = header.split(" ");
3
+ const [name, , length, struct] = header.split(" ");
4
4
  addHeader(`${name} (Array Of Structures)`, output);
5
5
  addFieldMaxLengthConstant(name, length, output);
6
- addArrayOfStructuresDefinition(name, type, length, output);
7
- addArrayOfStructuresZeroFunction(name, type, output);
8
- addArrayOfStructuresZeroAtIndexFunction(name, type, output);
6
+ addArrayOfStructuresDefinition(name, struct, length, output);
7
+ addArrayOfStructuresZeroFunction(name, struct, length, output);
8
+ addArrayOfStructuresZeroAtIndexFunction(name, struct, output);
9
9
  }
10
10
  function addFieldMaxLengthConstant(name, length, output) {
11
11
  output.push(`export const MAX_${name.toUpperCase()}_COUNT = ${length}`);
12
12
  output.push("");
13
13
  }
14
- function addArrayOfStructuresDefinition(name, type, length, output) {
15
- output.push(`/** An array of ${capitalize(type)} objects (structures). */`);
16
- output.push(`export const ${name} = Array.from({ length: ${length} }, create${capitalize(type)})`);
14
+ function addArrayOfStructuresDefinition(name, struct, length, output) {
15
+ output.push(`/** An array of ${struct} objects (structures). */`);
16
+ output.push(`export const ${name} = Array.from({ length: ${length} }, create${capitalize(struct)})`);
17
17
  }
18
- function addArrayOfStructuresZeroFunction(name, type, output) {
18
+ function addArrayOfStructuresZeroFunction(name, struct, length, output) {
19
19
  output.push("");
20
20
  output.push(`/** Zero all objects within the ${name} array of structures. */`);
21
21
  output.push(`export function zero${capitalize(name)}() {`);
22
- output.push(` ${name}.forEach(zero${capitalize(type)})`);
22
+ output.push(` for (let i=0; i<${length}; i++) {`);
23
+ output.push(` zero${capitalize(struct)}(${name}[i])`);
24
+ output.push(" }");
23
25
  output.push("}");
24
26
  }
25
- function addArrayOfStructuresZeroAtIndexFunction(name, type, output) {
27
+ function addArrayOfStructuresZeroAtIndexFunction(name, struct, output) {
26
28
  output.push("");
27
29
  output.push(`/** Zero an object at a specific index within the ${name} array of structures. */`);
28
- output.push(`export function zero${capitalize(name)}At(i: number) {`);
29
- output.push(` zero${capitalize(type)}(${name}[i])`);
30
+ output.push(`export function zero${capitalize(name)}At(index: number) {`);
31
+ output.push(` zero${capitalize(struct)}(${name}[index])`);
30
32
  output.push("}");
31
33
  }
package/dist/lib/group.js CHANGED
@@ -9,92 +9,66 @@ export function addGroup(header, fields, output) {
9
9
  for (const field of fields) {
10
10
  addFieldSetFunction(name, field, output);
11
11
  }
12
- for (const field of fields) {
13
- addFieldPushFunction(name, field, output);
14
- }
15
- for (const field of fields) {
16
- addFieldPopFunction(name, field, output);
17
- }
18
12
  for (const field of fields) {
19
13
  addFieldZeroFunction(name, field, output);
20
14
  }
21
15
  addZeroFunction(name, fields, output);
22
16
  }
23
17
  function addFieldDefinition(field, output) {
24
- const [fieldName, fieldType, fieldLength] = field.split(" ");
18
+ const [fieldName, fieldType] = field.split(" ");
25
19
  switch (fieldType) {
26
- case FieldType.INT_8:
27
- output.push(`export const ${fieldName} = new Int8Array(${fieldLength})`);
28
- output.push(`export let ${fieldName}Count = 0`);
29
- break;
30
- case FieldType.INT_16:
31
- output.push(`export const ${fieldName} = new Int16Array(${fieldLength})`);
32
- output.push(`export let ${fieldName}Count = 0`);
33
- break;
34
- case FieldType.INT_32:
35
- output.push(`export const ${fieldName} = new Int32Array(${fieldLength})`);
36
- output.push(`export let ${fieldName}Count = 0`);
20
+ case FieldType.STRING:
21
+ output.push(`export let ${fieldName} = ""`);
37
22
  break;
38
- case FieldType.UINT_8:
39
- output.push(`export const ${fieldName} = new Uint8Array(${fieldLength})`);
40
- output.push(`export let ${fieldName}Count = 0`);
23
+ case FieldType.NUMBER:
24
+ output.push(`export let ${fieldName} = 0`);
41
25
  break;
42
- case FieldType.UINT_16:
43
- output.push(`export const ${fieldName} = new Uint16Array(${fieldLength})`);
44
- output.push(`export let ${fieldName}Count = 0`);
26
+ case FieldType.BOOLEAN:
27
+ output.push(`export let ${fieldName} = false`);
45
28
  break;
46
- case FieldType.UINT_32:
47
- output.push(`export const ${fieldName} = new Uint32Array(${fieldLength})`);
48
- output.push(`export let ${fieldName}Count = 0`);
29
+ case FieldType.ARRAY_STRING:
30
+ output.push(`export const ${fieldName}: Array<string> = []`);
49
31
  break;
50
- case FieldType.FLOAT_32:
51
- output.push(`export const ${fieldName} = new Float32Array(${fieldLength})`);
52
- output.push(`export let ${fieldName}Count = 0`);
32
+ case FieldType.ARRAY_NUMBER:
33
+ output.push(`export const ${fieldName}: Array<number> = []`);
53
34
  break;
54
- case FieldType.FLOAT_64:
55
- output.push(`export const ${fieldName} = new Float64Array(${fieldLength})`);
56
- output.push(`export let ${fieldName}Count = 0`);
35
+ case FieldType.ARRAY_BOOLEAN:
36
+ output.push(`export const ${fieldName}: Array<boolean> = []`);
57
37
  break;
58
- default:
59
- output.push(`export let ${fieldName} = 0`);
60
38
  }
61
39
  }
62
40
  function addFieldSetFunction(name, field, output) {
63
- const [fieldName, , fieldLength] = field.split(" ");
64
- if (!fieldLength) {
65
- output.push("");
66
- output.push(`/** Set the value of the ${fieldName} field within the ${name} group. */`);
67
- output.push(`export function set${capitalize(fieldName)}(v: number) {`);
68
- output.push(` ${fieldName} = v`);
69
- output.push("}");
70
- }
71
- }
72
- function addFieldPushFunction(name, field, output) {
73
- const [fieldName, , fieldLength] = field.split(" ");
74
- if (fieldLength) {
75
- output.push("");
76
- output.push(`/** Push a value onto the ${fieldName} field within the ${name} group. */`);
77
- output.push(`export function push${capitalize(fieldName)}(v: number) {`);
78
- output.push(` ${fieldName}[${fieldName}Count++] = v`);
79
- output.push("}");
80
- }
81
- }
82
- function addFieldPopFunction(name, field, output) {
83
- const [fieldName, , fieldLength] = field.split(" ");
84
- if (fieldLength) {
85
- output.push("");
86
- output.push(`/** Pop a value from the ${fieldName} field within the ${name} group. */`);
87
- output.push(`export function pop${capitalize(fieldName)}() {`);
88
- output.push(` return ${fieldName}[--${fieldName}Count]`);
89
- output.push("}");
41
+ const [fieldName, fieldType] = field.split(" ");
42
+ switch (fieldType) {
43
+ case FieldType.STRING:
44
+ output.push("");
45
+ output.push(`/** Set the value of the ${fieldName} field within the ${name} group. */`);
46
+ output.push(`export function set${capitalize(fieldName)}(v: string) {`);
47
+ output.push(` ${fieldName} = v`);
48
+ output.push("}");
49
+ break;
50
+ case FieldType.NUMBER:
51
+ output.push("");
52
+ output.push(`/** Set the value of the ${fieldName} field within the ${name} group. */`);
53
+ output.push(`export function set${capitalize(fieldName)}(v: number) {`);
54
+ output.push(` ${fieldName} = v`);
55
+ output.push("}");
56
+ break;
57
+ case FieldType.BOOLEAN:
58
+ output.push("");
59
+ output.push(`/** Set the value of the ${fieldName} field within the ${name} group. */`);
60
+ output.push(`export function set${capitalize(fieldName)}(v: boolean) {`);
61
+ output.push(` ${fieldName} = v`);
62
+ output.push("}");
63
+ break;
90
64
  }
91
65
  }
92
66
  function addFieldZeroFunction(name, field, output) {
93
- const [fieldName, , fieldLength] = field.split(" ");
67
+ const [fieldName, fieldType] = field.split(" ");
94
68
  output.push("");
95
69
  output.push(`/** Zero the ${fieldName} field within the ${name} group. */`);
96
70
  output.push(`export function zero${capitalize(fieldName)}() {`);
97
- zeroField(fieldName, !!fieldLength, output);
71
+ zeroField(fieldName, fieldType, output);
98
72
  output.push("}");
99
73
  }
100
74
  function addZeroFunction(name, fields, output) {
@@ -102,16 +76,26 @@ function addZeroFunction(name, fields, output) {
102
76
  output.push(`/** Zero all fields within the ${name} group. */`);
103
77
  output.push(`export function zero${capitalize(name)}() {`);
104
78
  for (const field of fields) {
105
- const [fieldName, , fieldLength] = field.split(" ");
106
- zeroField(fieldName, !!fieldLength, output);
79
+ const [fieldName, fieldType] = field.split(" ");
80
+ zeroField(fieldName, fieldType, output);
107
81
  }
108
82
  output.push("}");
109
83
  }
110
- function zeroField(name, isArray, output) {
111
- if (isArray) {
112
- output.push(` ${name}Count = 0`);
113
- }
114
- else {
115
- output.push(` ${name} = 0`);
84
+ function zeroField(name, type, output) {
85
+ switch (type) {
86
+ case FieldType.STRING:
87
+ output.push(` ${name} = ""`);
88
+ break;
89
+ case FieldType.NUMBER:
90
+ output.push(` ${name} = 0`);
91
+ break;
92
+ case FieldType.BOOLEAN:
93
+ output.push(` ${name} = false`);
94
+ break;
95
+ case FieldType.ARRAY_STRING:
96
+ case FieldType.ARRAY_NUMBER:
97
+ case FieldType.ARRAY_BOOLEAN:
98
+ output.push(` ${name}.length = 0`);
99
+ break;
116
100
  }
117
101
  }
package/dist/lib/soa.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FieldType } from "../consts.js";
2
2
  import { addHeader, capitalize } from "./utils.js";
3
3
  export function addStructureOfArrays(header, fields, output) {
4
- const [name, length] = header.split(" ");
4
+ const [name, , length] = header.split(" ");
5
5
  addHeader(`${name} (Structure Of Arrays)`, output);
6
6
  addFieldMaxLengthConstant(name, length, output);
7
7
  for (const field of fields) {
@@ -9,7 +9,6 @@ export function addStructureOfArrays(header, fields, output) {
9
9
  }
10
10
  addZeroAtIndexFunction(name, fields, output);
11
11
  addZeroFunction(name, fields, output);
12
- addPrintAtIndexFunction(name, fields, output);
13
12
  }
14
13
  function addFieldMaxLengthConstant(name, length, output) {
15
14
  output.push(`export const MAX_${name.toUpperCase()}_COUNT = ${length}`);
@@ -64,15 +63,3 @@ function addZeroAtIndexFunction(name, fields, output) {
64
63
  }
65
64
  output.push("}");
66
65
  }
67
- function addPrintAtIndexFunction(name, fields, output) {
68
- output.push("");
69
- output.push(`/** Print an index within the ${name} structure of arrays to the console. */`);
70
- output.push(`export function print${capitalize(name)}At(i: number) {`);
71
- output.push(" console.table({");
72
- for (const field of fields) {
73
- const [fieldName] = field.split(" ");
74
- output.push(` ${fieldName}: ${fieldName}[i],`);
75
- }
76
- output.push(" })");
77
- output.push("}");
78
- }
@@ -1,19 +1,18 @@
1
1
  import { FieldType } from "../consts.js";
2
- import { addHeader, capitalize, getTypeName } from "./utils.js";
2
+ import { addHeader, capitalize } from "./utils.js";
3
3
  export function addStruct(header, fields, output) {
4
4
  const [name] = header.split(" ");
5
5
  addHeader(`${name} (Struct)`, output);
6
6
  addStructTypeDefinition(name, fields, output);
7
7
  addStructCreateFunction(name, fields, output);
8
8
  addStructCopyFunction(name, fields, output);
9
- addStructCloneFunction(name, output);
10
9
  addStructZeroFunction(name, fields, output);
11
10
  }
12
11
  function addStructTypeDefinition(name, fields, output) {
13
12
  output.push(`export type ${capitalize(name)} = {`);
14
13
  for (const field of fields) {
15
14
  const [fieldName, fieldType] = field.split(" ");
16
- output.push(` ${fieldName}: ${getTypeName(fieldType)}`);
15
+ output.push(` ${fieldName}: ${fieldType}`);
17
16
  }
18
17
  output.push("}");
19
18
  }
@@ -21,18 +20,23 @@ function addStructCreateFunction(name, fields, output) {
21
20
  output.push("");
22
21
  output.push(`/** Create a new ${capitalize(name)} object. */`);
23
22
  output.push(`export function create${capitalize(name)}() {`);
24
- output.push(` const obj: ${getTypeName(name)} = Object.create(null)`);
23
+ output.push(` const obj: ${name} = Object.create(null)`);
25
24
  for (const field of fields) {
26
25
  const [fieldName, fieldType] = field.split(" ");
27
26
  switch (fieldType) {
28
27
  case FieldType.STRING:
29
28
  output.push(` obj.${fieldName} = ""`);
30
29
  break;
30
+ case FieldType.NUMBER:
31
+ output.push(` obj.${fieldName} = 0`);
32
+ break;
31
33
  case FieldType.BOOLEAN:
32
34
  output.push(` obj.${fieldName} = false`);
33
35
  break;
34
- case FieldType.NUMBER:
35
- output.push(` obj.${fieldName} = 0`);
36
+ case FieldType.ARRAY_STRING:
37
+ case FieldType.ARRAY_NUMBER:
38
+ case FieldType.ARRAY_BOOLEAN:
39
+ output.push(` obj.${fieldName} = []`);
36
40
  break;
37
41
  default:
38
42
  output.push(` obj.${fieldName} = create${capitalize(fieldType)}()`);
@@ -44,37 +48,49 @@ function addStructCreateFunction(name, fields, output) {
44
48
  function addStructCopyFunction(name, fields, output) {
45
49
  output.push("");
46
50
  output.push(`/** Copy the values of ${capitalize(name)} object b into ${capitalize(name)} object a. */`);
47
- output.push(`export function copy${capitalize(name)}(a: ${getTypeName(name)}, b: ${getTypeName(name)}) {`);
51
+ output.push(`export function copy${capitalize(name)}(a: ${name}, b: ${name}) {`);
48
52
  for (const field of fields) {
49
- const [fieldName] = field.split(" ");
50
- output.push(` a.${fieldName} = b.${fieldName}`);
53
+ const [fieldName, fieldType] = field.split(" ");
54
+ switch (fieldType) {
55
+ case FieldType.STRING:
56
+ case FieldType.NUMBER:
57
+ case FieldType.BOOLEAN:
58
+ output.push(` a.${fieldName} = b.${fieldName}`);
59
+ break;
60
+ case FieldType.ARRAY_STRING:
61
+ case FieldType.ARRAY_NUMBER:
62
+ case FieldType.ARRAY_BOOLEAN:
63
+ output.push(` a.${fieldName}.length = b.${fieldName}.length`);
64
+ output.push(` for (let i = 0; i < b.${fieldName}.length; i++) {`);
65
+ output.push(` a.${fieldName}[i] = b.${fieldName}[i]`);
66
+ output.push(` }`);
67
+ break;
68
+ default:
69
+ output.push(` copy${capitalize(fieldType)}(a.${fieldName}, b.${fieldName})`);
70
+ }
51
71
  }
52
72
  output.push("}");
53
73
  }
54
- function addStructCloneFunction(name, output) {
55
- output.push("");
56
- output.push(`/** Clone the given ${capitalize(name)} object. */`);
57
- output.push(`export function clone${capitalize(name)}(obj: ${getTypeName(name)}) {`);
58
- output.push(` const clone = create${capitalize(name)}()`);
59
- output.push(` copy${capitalize(name)}(clone, obj)`);
60
- output.push(" return clone");
61
- output.push("}");
62
- }
63
74
  function addStructZeroFunction(name, fields, output) {
64
75
  output.push("");
65
76
  output.push(`/** Zero the given ${capitalize(name)} object. */`);
66
- output.push(`export function zero${capitalize(name)}(obj: ${getTypeName(name)}) {`);
77
+ output.push(`export function zero${capitalize(name)}(obj: ${name}) {`);
67
78
  for (const field of fields) {
68
79
  const [fieldName, fieldType] = field.split(" ");
69
80
  switch (fieldType) {
70
81
  case FieldType.STRING:
71
82
  output.push(` obj.${fieldName} = ""`);
72
83
  break;
84
+ case FieldType.NUMBER:
85
+ output.push(` obj.${fieldName} = 0`);
86
+ break;
73
87
  case FieldType.BOOLEAN:
74
88
  output.push(` obj.${fieldName} = false`);
75
89
  break;
76
- case FieldType.NUMBER:
77
- output.push(` obj.${fieldName} = 0`);
90
+ case FieldType.ARRAY_STRING:
91
+ case FieldType.ARRAY_NUMBER:
92
+ case FieldType.ARRAY_BOOLEAN:
93
+ output.push(` obj.${fieldName}.length = 0`);
78
94
  break;
79
95
  default:
80
96
  output.push(` zero${capitalize(fieldType)}(obj.${fieldName})`);
package/dist/main.js CHANGED
@@ -1,8 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "node:fs";
3
3
  import { marked } from "marked";
4
+ import { Type } from "./consts.js";
5
+ import { addArrayOfStructures } from "./lib/aos.js";
4
6
  import { addGroup } from "./lib/group.js";
5
7
  import { addStructureOfArrays } from "./lib/soa.js";
8
+ import { addStruct } from "./lib/struct.js";
6
9
  const inputFile = process.argv[2];
7
10
  const outputFile = process.argv[3] || inputFile.replace(".md", ".ts");
8
11
  const input = fs.readFileSync(inputFile, "utf-8");
@@ -37,12 +40,20 @@ for (const token of tokens) {
37
40
  }
38
41
  }
39
42
  for (const { header, fields } of blocks) {
40
- const [, length] = header.split(" ");
41
- if (length) {
42
- addStructureOfArrays(header, fields, output);
43
- }
44
- else {
45
- addGroup(header, fields, output);
43
+ const [, type] = header.split(" ");
44
+ switch (type) {
45
+ case Type.GROUP:
46
+ addGroup(header, fields, output);
47
+ break;
48
+ case Type.STRUCT:
49
+ addStruct(header, fields, output);
50
+ break;
51
+ case Type.ARRAY_OF_STRUCTURES:
52
+ addArrayOfStructures(header, output);
53
+ break;
54
+ case Type.STRUCTURE_OF_ARRAYS:
55
+ addStructureOfArrays(header, fields, output);
56
+ break;
46
57
  }
47
58
  }
48
59
  fs.writeFileSync(outputFile, output.join("\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "game-data-gen",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"