game-data-gen 3.0.2 → 4.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,41 +31,54 @@ 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
35
+
36
+ ### group
37
+
38
+ | Field type | Example |
39
+ | --------------- | ------------------------------ |
40
+ | `number` | `- health number` |
41
+ | `array int8` | `- ids array int8 64` |
42
+ | `array int16` | `- ids array int16 64` |
43
+ | `array int32` | `- ids array int32 64` |
44
+ | `array uint8` | `- ids array uint8 64` |
45
+ | `array uint16` | `- ids array uint16 64` |
46
+ | `array uint32` | `- ids array uint32 64` |
47
+ | `array float32` | `- positions array float32 64` |
48
+ | `array float64` | `- positions array float64 64` |
49
+
50
+ Array fields without a length generate a `count` variable and `push`/`pop` functions.
51
+
52
+ ### soa (Structure of Arrays)
53
+
54
+ | Field type | Example |
55
+ | ---------- | -------------- |
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` |
64
+
34
65
  ## Example
35
66
 
36
- Create a Markdown file somewhere in your source code (without a file extension).
67
+ Create a Markdown file somewhere in your source code.
37
68
 
38
69
  For example `src/data.md`:
39
70
 
40
71
  ```md
41
72
  # game group
42
73
 
43
- - activeEntities array entity
44
- - activeEntityIds array number
45
74
  - playerId number
46
-
47
- # vector struct
48
-
49
- - x number
50
- - y number
51
-
52
- # entity struct
53
-
54
- - position vector
55
- - velocity vector
56
- <!-- stats -->
57
- - health number
58
- <!-- inventory -->
59
- - items array number
60
- <!-- flags -->
61
- - isActive boolean
62
-
63
- # entities aos 2048 entity
75
+ - entityIds array uint16
64
76
 
65
77
  # particle soa 10_000
66
78
 
67
- - type string
68
- - pos Vector
79
+ - active uint8
80
+ - x float32
81
+ - y float32
69
82
  ```
70
83
 
71
84
  Run the package with (consider making this a script in your package.json):
@@ -83,156 +96,39 @@ This will create or update the `src/data.ts` file (see below). The data and func
83
96
  * --------------------------------------------------
84
97
  */
85
98
 
86
- export let activeEntities = new Array<Entity>()
87
- export let activeEntityIds = new Array<number>()
88
- export let playerId = 0
89
-
90
- /** Set the value of the activeEntities field within the game group. */
91
- export function setActiveEntities(v: Array<Entity>) {
92
- activeEntities = v
93
- }
94
-
95
- /** Set the value of the activeEntityIds field within the game group. */
96
- export function setActiveEntityIds(v: Array<number>) {
97
- activeEntityIds = v
98
- }
99
+ export let playerId = 0;
100
+ export const entityIds = new Uint16Array();
101
+ export let entityIdsCount = 0;
99
102
 
100
103
  /** Set the value of the playerId field within the game group. */
101
104
  export function setPlayerId(v: number) {
102
- playerId = v
105
+ playerId = v;
103
106
  }
104
107
 
105
- /** Zero the activeEntities field within the game group. */
106
- export function zeroActiveEntities() {
107
- activeEntities.length = 0
108
+ /** Push a value onto the entityIds field within the game group. */
109
+ export function pushEntityIds(v: number) {
110
+ entityIds[entityIdsCount++] = v;
108
111
  }
109
112
 
110
- /** Zero the activeEntityIds field within the game group. */
111
- export function zeroActiveEntityIds() {
112
- activeEntityIds.length = 0
113
+ /** Pop a value from the entityIds field within the game group. */
114
+ export function popEntityIds() {
115
+ return entityIds[--entityIdsCount];
113
116
  }
114
117
 
115
118
  /** Zero the playerId field within the game group. */
116
119
  export function zeroPlayerId() {
117
- playerId = 0
120
+ playerId = 0;
118
121
  }
119
122
 
120
- /** Zero all fields within the game group. */
121
- export function zeroGameData() {
122
- activeEntities.length = 0
123
- activeEntityIds.length = 0
124
- playerId = 0
123
+ /** Zero the entityIds field within the game group. */
124
+ export function zeroEntityIds() {
125
+ entityIdsCount = 0;
125
126
  }
126
127
 
127
- /*
128
- * --------------------------------------------------
129
- * vector (Struct)
130
- * --------------------------------------------------
131
- */
132
-
133
- export type Vector = {
134
- x: number
135
- y: number
136
- }
137
-
138
- /** Create a new Vector object. */
139
- export function createVector() {
140
- const obj: Vector = Object.create(null)
141
- obj.x = 0
142
- obj.y = 0
143
- return obj
144
- }
145
-
146
- /** Copy the values of Vector object b into Vector object a. */
147
- export function copyVector(a: Vector, b: Vector) {
148
- a.x = b.x
149
- a.y = b.y
150
- }
151
-
152
- /** Clone the given Vector object. */
153
- export function cloneVector(obj: Vector) {
154
- const clone = createVector()
155
- copyVector(clone, obj)
156
- return clone
157
- }
158
-
159
- /** Zero the given Vector object. */
160
- export function zeroVector(obj: Vector) {
161
- obj.x = 0
162
- obj.y = 0
163
- }
164
-
165
- /*
166
- * --------------------------------------------------
167
- * entity (Struct)
168
- * --------------------------------------------------
169
- */
170
-
171
- export type Entity = {
172
- position: Vector
173
- velocity: Vector
174
- health: number
175
- items: Array<number>
176
- isActive: boolean
177
- }
178
-
179
- /** Create a new Entity object. */
180
- export function createEntity() {
181
- const obj: Entity = Object.create(null)
182
- obj.position = createVector()
183
- obj.velocity = createVector()
184
- obj.health = 0
185
- obj.items = new Array<number>()
186
- obj.isActive = false
187
- return obj
188
- }
189
-
190
- /** Copy the values of Entity object b into Entity object a. */
191
- export function copyEntity(a: Entity, b: Entity) {
192
- a.position = b.position
193
- a.velocity = b.velocity
194
- a.health = b.health
195
- a.items = b.items
196
- a.isActive = b.isActive
197
- }
198
-
199
- /** Clone the given Entity object. */
200
- export function cloneEntity(obj: Entity) {
201
- const clone = createEntity()
202
- copyEntity(clone, obj)
203
- return clone
204
- }
205
-
206
- /** Zero the given Entity object. */
207
- export function zeroEntity(obj: Entity) {
208
- zeroVector(obj.position)
209
- zeroVector(obj.velocity)
210
- obj.health = 0
211
- obj.items.length = 0
212
- obj.isActive = false
213
- }
214
-
215
- /*
216
- * --------------------------------------------------
217
- * entities (Array Of Structures)
218
- * --------------------------------------------------
219
- */
220
-
221
- export const MAX_ENTITIES_COUNT = 2048
222
-
223
- /** An array of Entity objects (structures). */
224
- export const entities = Array.from({ length: 2048 }, createEntity)
225
-
226
- /** Zero all objects within the entities array of structures. */
227
- export function zeroEntities() {
228
- for (let i=0; i<2048; i++) {
229
- zeroEntity(entities[i])
230
- }
231
- }
232
-
233
- /** Zero an object at a specific index within the entities array of structures. */
234
- export function zeroEntitiesAt(i: number) {
235
- zeroEntity(entities[i])
128
+ /** Zero all fields within the game group. */
129
+ export function zeroGame() {
130
+ playerId = 0;
131
+ entityIdsCount = 0;
236
132
  }
237
133
 
238
134
  /*
@@ -241,30 +137,38 @@ export function zeroEntitiesAt(i: number) {
241
137
  * --------------------------------------------------
242
138
  */
243
139
 
244
- export const MAX_PARTICLE_COUNT = 10_000
140
+ export const MAX_PARTICLE_COUNT = 10_000;
245
141
 
246
- export const type = new Array(10_000).fill("")
247
- export const pos = Array.from({ length: 10_000 }, createVector)
142
+ export const active = new Uint8Array(10_000);
143
+ export const x = new Float32Array(10_000);
144
+ export const y = new Float32Array(10_000);
248
145
 
249
146
  /** Zero an index within the particle structure of arrays. */
250
- export function zeroParticle(i: number) {
251
- type[i] = ""
252
- zeroVector(pos[i])
147
+ export function zeroParticleAt(i: number) {
148
+ active[i] = 0;
149
+ x[i] = 0;
150
+ y[i] = 0;
151
+ }
152
+
153
+ /** Zero the active field within the particle structure of arrays. */
154
+ export function zeroActive() {
155
+ active.fill(0);
253
156
  }
254
157
 
255
- /** Zero the type field within the particle structure of arrays. */
256
- export function zeroType() {
257
- type.fill("")
158
+ /** Zero the x field within the particle structure of arrays. */
159
+ export function zeroX() {
160
+ x.fill(0);
258
161
  }
259
162
 
260
- /** Zero the pos field within the particle structure of arrays. */
261
- export function zeroPos() {
262
- pos.forEach(zeroVector)
163
+ /** Zero the y field within the particle structure of arrays. */
164
+ export function zeroY() {
165
+ y.fill(0);
263
166
  }
264
167
 
265
168
  /** Zero all fields within the particle structure of arrays. */
266
- export function zeroParticleData() {
267
- type.fill("")
268
- pos.forEach(zeroVector)
169
+ export function zeroParticle() {
170
+ active.fill(0);
171
+ x.fill(0);
172
+ y.fill(0);
269
173
  }
270
174
  ```
package/dist/consts.js CHANGED
@@ -1,20 +1,21 @@
1
1
  export var Type;
2
2
  (function (Type) {
3
3
  Type["SOA"] = "soa";
4
- Type["AOS"] = "aos";
5
- Type["STRUCT"] = "struct";
6
4
  Type["GROUP"] = "group";
7
5
  })(Type || (Type = {}));
8
6
  export var FieldType;
9
7
  (function (FieldType) {
10
- FieldType["STRING"] = "string";
11
8
  FieldType["NUMBER"] = "number";
12
- FieldType["BOOLEAN"] = "boolean";
13
9
  FieldType["ARRAY"] = "array";
14
10
  })(FieldType || (FieldType = {}));
15
11
  export var ArrayType;
16
12
  (function (ArrayType) {
17
- ArrayType["STRING"] = "string";
18
- ArrayType["NUMBER"] = "number";
19
- ArrayType["BOOLEAN"] = "boolean";
13
+ ArrayType["INT_8"] = "int8";
14
+ ArrayType["INT_16"] = "int16";
15
+ ArrayType["INT_32"] = "int32";
16
+ ArrayType["UINT_8"] = "uint8";
17
+ ArrayType["UINT_16"] = "uint16";
18
+ ArrayType["UINT_32"] = "uint32";
19
+ ArrayType["FLOAT_32"] = "float32";
20
+ ArrayType["FLOAT_64"] = "float64";
20
21
  })(ArrayType || (ArrayType = {}));
package/dist/lib/aos.js CHANGED
@@ -4,7 +4,7 @@ export function addArrayOfStructures(header, output) {
4
4
  addHeader(`${name} (Array Of Structures)`, output);
5
5
  addFieldMaxLengthConstant(name, length, output);
6
6
  addArrayOfStructuresDefinition(name, type, length, output);
7
- addArrayOfStructuresZeroFunction(name, type, length, output);
7
+ addArrayOfStructuresZeroFunction(name, type, output);
8
8
  addArrayOfStructuresZeroAtIndexFunction(name, type, output);
9
9
  }
10
10
  function addFieldMaxLengthConstant(name, length, output) {
@@ -15,13 +15,11 @@ function addArrayOfStructuresDefinition(name, type, length, output) {
15
15
  output.push(`/** An array of ${capitalize(type)} objects (structures). */`);
16
16
  output.push(`export const ${name} = Array.from({ length: ${length} }, create${capitalize(type)})`);
17
17
  }
18
- function addArrayOfStructuresZeroFunction(name, type, length, output) {
18
+ function addArrayOfStructuresZeroFunction(name, type, 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(` for (let i=0; i<${length}; i++) {`);
23
- output.push(` zero${capitalize(type)}(${name}[i])`);
24
- output.push(" }");
22
+ output.push(` ${name}.forEach(zero${capitalize(type)})`);
25
23
  output.push("}");
26
24
  }
27
25
  function addArrayOfStructuresZeroAtIndexFunction(name, type, output) {
package/dist/lib/group.js CHANGED
@@ -1,5 +1,5 @@
1
- import { FieldType } from "../consts.js";
2
- import { addHeader, capitalize, getTypeName } from "./utils.js";
1
+ import { ArrayType, FieldType } from "../consts.js";
2
+ import { addHeader, capitalize } from "./utils.js";
3
3
  export function addGroup(header, fields, output) {
4
4
  const [name] = header.split(" ");
5
5
  addHeader(`${name} (Group)`, output);
@@ -9,71 +9,121 @@ 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
+ }
12
18
  for (const field of fields) {
13
19
  addFieldZeroFunction(name, field, output);
14
20
  }
15
21
  addZeroFunction(name, fields, output);
16
22
  }
17
23
  function addFieldDefinition(field, output) {
18
- const [fieldName, fieldType, fieldArrayType] = field.split(" ");
24
+ const [fieldName, fieldType, fieldArrayType, fieldArrayLength = ""] = field.split(" ");
19
25
  switch (fieldType) {
20
- case FieldType.STRING:
21
- output.push(`export let ${fieldName} = ""`);
22
- break;
23
26
  case FieldType.NUMBER:
24
27
  output.push(`export let ${fieldName} = 0`);
25
28
  break;
26
- case FieldType.BOOLEAN:
27
- output.push(`export let ${fieldName} = false`);
28
- break;
29
29
  case FieldType.ARRAY:
30
- output.push(`export let ${fieldName} = new Array<${getTypeName(fieldArrayType)}>()`);
30
+ {
31
+ switch (fieldArrayType) {
32
+ case ArrayType.INT_8:
33
+ output.push(`export const ${fieldName} = new Int8Array(${fieldArrayLength})`);
34
+ break;
35
+ case ArrayType.INT_16:
36
+ output.push(`export const ${fieldName} = new Int16Array(${fieldArrayLength})`);
37
+ break;
38
+ case ArrayType.INT_32:
39
+ output.push(`export const ${fieldName} = new Int32Array(${fieldArrayLength})`);
40
+ break;
41
+ case ArrayType.UINT_8:
42
+ output.push(`export const ${fieldName} = new Uint8Array(${fieldArrayLength})`);
43
+ break;
44
+ case ArrayType.UINT_16:
45
+ output.push(`export const ${fieldName} = new Uint16Array(${fieldArrayLength})`);
46
+ break;
47
+ case ArrayType.UINT_32:
48
+ output.push(`export const ${fieldName} = new Uint32Array(${fieldArrayLength})`);
49
+ break;
50
+ case ArrayType.FLOAT_32:
51
+ output.push(`export const ${fieldName} = new Float32Array(${fieldArrayLength})`);
52
+ break;
53
+ case ArrayType.FLOAT_64:
54
+ output.push(`export const ${fieldName} = new Float64Array(${fieldArrayLength})`);
55
+ break;
56
+ }
57
+ if (isDynamicArray(fieldType, fieldArrayLength)) {
58
+ output.push(`export let ${fieldName}Count = 0`);
59
+ }
60
+ }
31
61
  break;
32
- default:
33
- output.push(`export let ${fieldName} = create${capitalize(fieldType)}()`);
34
62
  }
35
63
  }
36
64
  function addFieldSetFunction(name, field, output) {
37
- const [fieldName, fieldType, fieldArrayType] = field.split(" ");
38
- output.push("");
39
- output.push(`/** Set the value of the ${fieldName} field within the ${name} group. */`);
40
- output.push(`export function set${capitalize(fieldName)}(v: ${getTypeName(fieldType, fieldArrayType)}) {`);
41
- output.push(` ${fieldName} = v`);
42
- output.push("}");
65
+ const [fieldName, fieldType] = field.split(" ");
66
+ if (fieldType === FieldType.NUMBER) {
67
+ output.push("");
68
+ output.push(`/** Set the value of the ${fieldName} field within the ${name} group. */`);
69
+ output.push(`export function set${capitalize(fieldName)}(v: number) {`);
70
+ output.push(` ${fieldName} = v`);
71
+ output.push("}");
72
+ }
73
+ }
74
+ function addFieldPushFunction(name, field, output) {
75
+ const [fieldName, fieldType, , fieldArrayLength] = field.split(" ");
76
+ if (isDynamicArray(fieldType, fieldArrayLength)) {
77
+ output.push("");
78
+ output.push(`/** Push a value onto the ${fieldName} field within the ${name} group. */`);
79
+ output.push(`export function push${capitalize(fieldName)}(v: number) {`);
80
+ output.push(` ${fieldName}[${fieldName}Count++] = v`);
81
+ output.push("}");
82
+ }
83
+ }
84
+ function addFieldPopFunction(name, field, output) {
85
+ const [fieldName, fieldType, , fieldArrayLength] = field.split(" ");
86
+ if (isDynamicArray(fieldType, fieldArrayLength)) {
87
+ output.push("");
88
+ output.push(`/** Pop a value from the ${fieldName} field within the ${name} group. */`);
89
+ output.push(`export function pop${capitalize(fieldName)}() {`);
90
+ output.push(` return ${fieldName}[--${fieldName}Count]`);
91
+ output.push("}");
92
+ }
43
93
  }
44
94
  function addFieldZeroFunction(name, field, output) {
45
- const [fieldName, fieldType] = field.split(" ");
95
+ const [fieldName, fieldType, , fieldArrayLength = ""] = field.split(" ");
46
96
  output.push("");
47
97
  output.push(`/** Zero the ${fieldName} field within the ${name} group. */`);
48
98
  output.push(`export function zero${capitalize(fieldName)}() {`);
49
- zeroField(fieldName, fieldType, output);
99
+ zeroField(fieldName, fieldType, fieldArrayLength, output);
50
100
  output.push("}");
51
101
  }
52
102
  function addZeroFunction(name, fields, output) {
53
103
  output.push("");
54
104
  output.push(`/** Zero all fields within the ${name} group. */`);
55
- output.push(`export function zero${capitalize(name)}Data() {`);
105
+ output.push(`export function zero${capitalize(name)}() {`);
56
106
  for (const field of fields) {
57
- const [fieldName, fieldType] = field.split(" ");
58
- zeroField(fieldName, fieldType, output);
107
+ const [fieldName, fieldType, , fieldArrayLength = ""] = field.split(" ");
108
+ zeroField(fieldName, fieldType, fieldArrayLength, output);
59
109
  }
60
110
  output.push("}");
61
111
  }
62
- function zeroField(name, type, output) {
112
+ function zeroField(name, type, arrayLength, output) {
63
113
  switch (type) {
64
- case FieldType.STRING:
65
- output.push(` ${name} = ""`);
66
- break;
67
114
  case FieldType.NUMBER:
68
115
  output.push(` ${name} = 0`);
69
116
  break;
70
- case FieldType.BOOLEAN:
71
- output.push(` ${name} = false`);
72
- break;
73
117
  case FieldType.ARRAY:
74
- output.push(` ${name}.length = 0`);
118
+ if (isDynamicArray(type, arrayLength)) {
119
+ output.push(` ${name}Count = 0`);
120
+ }
121
+ else {
122
+ output.push(` ${name}.fill(0)`);
123
+ }
75
124
  break;
76
- default:
77
- output.push(` zero${capitalize(type)}(${name})`);
78
125
  }
79
126
  }
127
+ function isDynamicArray(fieldType, fieldArrayLength) {
128
+ return fieldType === FieldType.ARRAY && !fieldArrayLength;
129
+ }
package/dist/lib/soa.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ArrayType } 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) {
@@ -20,71 +20,57 @@ function addFieldMaxLengthConstant(name, length, output) {
20
20
  function addFieldDefinition(field, length, output) {
21
21
  const [fieldName, fieldType] = field.split(" ");
22
22
  switch (fieldType) {
23
- case ArrayType.STRING:
24
- output.push(`export const ${fieldName} = new Array<string>(${length}).fill("")`);
23
+ case ArrayType.INT_8:
24
+ output.push(`export const ${fieldName} = new Int8Array(${length})`);
25
25
  break;
26
- case ArrayType.NUMBER:
27
- output.push(`export const ${fieldName} = new Array<number>(${length}).fill(0)`);
26
+ case ArrayType.INT_16:
27
+ output.push(`export const ${fieldName} = new Int16Array(${length})`);
28
28
  break;
29
- case ArrayType.BOOLEAN:
30
- output.push(`export const ${fieldName} = new Array<boolean>(${length}).fill(false)`);
29
+ case ArrayType.INT_32:
30
+ output.push(`export const ${fieldName} = new Int32Array(${length})`);
31
+ break;
32
+ case ArrayType.UINT_8:
33
+ output.push(`export const ${fieldName} = new Uint8Array(${length})`);
34
+ break;
35
+ case ArrayType.UINT_16:
36
+ output.push(`export const ${fieldName} = new Uint16Array(${length})`);
37
+ break;
38
+ case ArrayType.UINT_32:
39
+ output.push(`export const ${fieldName} = new Uint32Array(${length})`);
40
+ break;
41
+ case ArrayType.FLOAT_32:
42
+ output.push(`export const ${fieldName} = new Float32Array(${length})`);
43
+ break;
44
+ case ArrayType.FLOAT_64:
45
+ output.push(`export const ${fieldName} = new Float64Array(${length})`);
31
46
  break;
32
- default:
33
- output.push(`export const ${fieldName} = Array.from({ length: ${length} }, create${capitalize(fieldType)})`);
34
47
  }
35
48
  }
36
49
  function addFieldZeroFunction(name, field, output) {
37
- const [fieldName, fieldType] = field.split(" ");
50
+ const [fieldName] = field.split(" ");
38
51
  output.push("");
39
52
  output.push(`/** Zero the ${fieldName} field within the ${name} structure of arrays. */`);
40
53
  output.push(`export function zero${capitalize(fieldName)}() {`);
41
- zeroField(fieldName, fieldType, output);
54
+ output.push(` ${fieldName}.fill(0)`);
42
55
  output.push("}");
43
56
  }
44
57
  function addZeroFunction(name, fields, output) {
45
58
  output.push("");
46
59
  output.push(`/** Zero all fields within the ${name} structure of arrays. */`);
47
- output.push(`export function zero${capitalize(name)}Data() {`);
60
+ output.push(`export function zero${capitalize(name)}() {`);
48
61
  for (const field of fields) {
49
- const [fieldName, fieldType] = field.split(" ");
50
- zeroField(fieldName, fieldType, output);
62
+ const [fieldName] = field.split(" ");
63
+ output.push(` ${fieldName}.fill(0)`);
51
64
  }
52
65
  output.push("}");
53
66
  }
54
- function zeroField(name, type, output) {
55
- switch (type) {
56
- case ArrayType.STRING:
57
- output.push(` ${name}.fill("")`);
58
- break;
59
- case ArrayType.NUMBER:
60
- output.push(` ${name}.fill(0)`);
61
- break;
62
- case ArrayType.BOOLEAN:
63
- output.push(` ${name}.fill(false)`);
64
- break;
65
- default:
66
- output.push(` ${name}.forEach(zero${capitalize(type)})`);
67
- }
68
- }
69
67
  function addFieldZeroAtIndexFunction(name, fields, output) {
70
68
  output.push("");
71
69
  output.push(`/** Zero an index within the ${name} structure of arrays. */`);
72
- output.push(`export function zero${capitalize(name)}(i: number) {`);
70
+ output.push(`export function zero${capitalize(name)}At(i: number) {`);
73
71
  for (const field of fields) {
74
- const [fieldName, fieldType] = field.split(" ");
75
- switch (fieldType) {
76
- case ArrayType.STRING:
77
- output.push(` ${fieldName}[i] = ""`);
78
- break;
79
- case ArrayType.NUMBER:
80
- output.push(` ${fieldName}[i] = 0`);
81
- break;
82
- case ArrayType.BOOLEAN:
83
- output.push(` ${fieldName}[i] = false`);
84
- break;
85
- default:
86
- output.push(` zero${capitalize(fieldType)}(${fieldName}[i])`);
87
- }
72
+ const [fieldName] = field.split(" ");
73
+ output.push(` ${fieldName}[i] = 0`);
88
74
  }
89
75
  output.push("}");
90
76
  }
@@ -12,8 +12,8 @@ export function addStruct(header, fields, output) {
12
12
  function addStructTypeDefinition(name, fields, output) {
13
13
  output.push(`export type ${capitalize(name)} = {`);
14
14
  for (const field of fields) {
15
- const [fieldName, fieldType, fieldArrayType] = field.split(" ");
16
- output.push(` ${fieldName}: ${getTypeName(fieldType, fieldArrayType)}`);
15
+ const [fieldName, fieldType] = field.split(" ");
16
+ output.push(` ${fieldName}: ${getTypeName(fieldType)}`);
17
17
  }
18
18
  output.push("}");
19
19
  }
@@ -23,23 +23,19 @@ function addStructCreateFunction(name, fields, output) {
23
23
  output.push(`export function create${capitalize(name)}() {`);
24
24
  output.push(` const obj: ${getTypeName(name)} = Object.create(null)`);
25
25
  for (const field of fields) {
26
- const [fieldName, fieldType, fieldArrayType] = field.split(" ");
26
+ const [fieldName, fieldType] = field.split(" ");
27
27
  switch (fieldType) {
28
28
  case FieldType.STRING:
29
29
  output.push(` obj.${fieldName} = ""`);
30
30
  break;
31
- case FieldType.NUMBER:
32
- output.push(` obj.${fieldName} = 0`);
33
- break;
34
31
  case FieldType.BOOLEAN:
35
32
  output.push(` obj.${fieldName} = false`);
36
33
  break;
37
- case FieldType.ARRAY:
38
- output.push(` obj.${fieldName} = new Array<${getTypeName(fieldArrayType)}>()`);
34
+ case FieldType.NUMBER:
35
+ output.push(` obj.${fieldName} = 0`);
39
36
  break;
40
- default: {
37
+ default:
41
38
  output.push(` obj.${fieldName} = create${capitalize(fieldType)}()`);
42
- }
43
39
  }
44
40
  }
45
41
  output.push(" return obj");
@@ -74,14 +70,11 @@ function addStructZeroFunction(name, fields, output) {
74
70
  case FieldType.STRING:
75
71
  output.push(` obj.${fieldName} = ""`);
76
72
  break;
77
- case FieldType.NUMBER:
78
- output.push(` obj.${fieldName} = 0`);
79
- break;
80
73
  case FieldType.BOOLEAN:
81
74
  output.push(` obj.${fieldName} = false`);
82
75
  break;
83
- case FieldType.ARRAY:
84
- output.push(` obj.${fieldName}.length = 0`);
76
+ case FieldType.NUMBER:
77
+ output.push(` obj.${fieldName} = 0`);
85
78
  break;
86
79
  default:
87
80
  output.push(` zero${capitalize(fieldType)}(obj.${fieldName})`);
package/dist/lib/utils.js CHANGED
@@ -1,4 +1,3 @@
1
- import { FieldType, Type } from "../consts.js";
2
1
  export function addHeader(name, output) {
3
2
  output.push("");
4
3
  output.push("/*");
@@ -8,34 +7,6 @@ export function addHeader(name, output) {
8
7
  output.push(" */");
9
8
  output.push("");
10
9
  }
11
- /**
12
- * Get the name based on the type of the data structure.
13
- */
14
- export function getTypeName(type, arrayType = "") {
15
- switch (type) {
16
- case Type.SOA:
17
- return "structure of arrays";
18
- case Type.AOS:
19
- return "array of structures";
20
- case Type.STRUCT:
21
- return "struct";
22
- case Type.GROUP:
23
- return "group";
24
- case FieldType.STRING:
25
- return "string";
26
- case FieldType.NUMBER:
27
- return "number";
28
- case FieldType.BOOLEAN:
29
- return "boolean";
30
- case FieldType.ARRAY:
31
- return `Array<${getTypeName(arrayType)}>`;
32
- default:
33
- return capitalize(type);
34
- }
35
- }
36
- /**
37
- * Capitalize the first letter of a string.
38
- */
39
10
  export function capitalize(str) {
40
11
  return `${str.substring(0, 1).toUpperCase()}${str.substring(1)}`;
41
12
  }
package/dist/main.js CHANGED
@@ -1,45 +1,51 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "node:fs";
3
+ import { marked } from "marked";
3
4
  import { Type } from "./consts.js";
4
- import { addArrayOfStructures } from "./lib/aos.js";
5
5
  import { addGroup } from "./lib/group.js";
6
6
  import { addStructureOfArrays } from "./lib/soa.js";
7
- import { addStruct } from "./lib/struct.js";
8
7
  const inputFile = process.argv[2];
9
- const outputFile = process.argv[3] || `${inputFile.replace(/\.md$/, "")}.ts`;
8
+ const outputFile = process.argv[3] || inputFile.replace(".md", ".ts");
10
9
  const input = fs.readFileSync(inputFile, "utf-8");
11
10
  const output = [];
12
11
  output.push("/*");
13
12
  output.push(` * Generated with game-data-gen on ${new Date().toLocaleString()}. DO NOT MODIFY THIS FILE!`);
14
13
  output.push(" */");
15
- const blocks = input
16
- .replace(/^# (.+)\n\n- /gm, "$1\n")
17
- .replace(/^# /gm, "")
18
- .replace(/^- /gm, "")
19
- .split("\n")
20
- .filter((line) => !line.startsWith("<!--"))
21
- .join("\n")
22
- .trim()
23
- .split("\n\n");
24
- for (const block of blocks) {
25
- const fields = block.split("\n");
26
- const header = fields.shift();
27
- if (!header)
28
- continue;
29
- const [_, type] = header.split(" ");
30
- switch (type) {
31
- case Type.STRUCT:
32
- addStruct(header, fields, output);
14
+ const tokens = marked.lexer(input);
15
+ const blocks = [];
16
+ let block = {
17
+ header: "",
18
+ fields: [],
19
+ };
20
+ for (const token of tokens) {
21
+ switch (token.type) {
22
+ case "heading":
23
+ {
24
+ block = {
25
+ header: token.text,
26
+ fields: [],
27
+ };
28
+ blocks.push(block);
29
+ }
30
+ break;
31
+ case "list":
32
+ {
33
+ for (const item of token.items) {
34
+ block.fields.push(item.text);
35
+ }
36
+ }
33
37
  break;
38
+ }
39
+ }
40
+ for (const { header, fields } of blocks) {
41
+ const [, type] = header.split(" ");
42
+ switch (type) {
34
43
  case Type.GROUP:
35
44
  addGroup(header, fields, output);
36
45
  break;
37
46
  case Type.SOA:
38
47
  addStructureOfArrays(header, fields, output);
39
48
  break;
40
- case Type.AOS:
41
- addArrayOfStructures(header, output);
42
- break;
43
49
  }
44
50
  }
45
51
  fs.writeFileSync(outputFile, output.join("\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "game-data-gen",
3
- "version": "3.0.2",
3
+ "version": "4.0.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -20,5 +20,8 @@
20
20
  "@biomejs/biome": "^2.4.11",
21
21
  "@types/node": "^24.12.2",
22
22
  "typescript": "^6.0.2"
23
+ },
24
+ "dependencies": {
25
+ "marked": "^18.0.2"
23
26
  }
24
27
  }
@@ -1,106 +0,0 @@
1
- import { ArrayType, FieldType } from "../consts.js";
2
- import { capitalize, getName } from "./utils.js";
3
- export function addFieldDefinition(field, baseLength, output) {
4
- const [fieldName, fieldType, fieldArrayType, fieldLength] = field.split(" ");
5
- const fieldArrayLength = baseLength || fieldLength || "";
6
- switch (fieldType) {
7
- case FieldType.STRING:
8
- output.push(`export let ${fieldName} = ""`);
9
- break;
10
- case FieldType.NUMBER:
11
- output.push(`export let ${fieldName} = 0`);
12
- break;
13
- case FieldType.BOOLEAN:
14
- output.push(`export let ${fieldName} = false`);
15
- break;
16
- case FieldType.ARRAY:
17
- {
18
- switch (fieldArrayType) {
19
- case ArrayType.STRING:
20
- output.push(`export let ${fieldName} = new Array<string>(${fieldArrayLength})${fieldArrayLength ? '.fill("")' : ""}`);
21
- break;
22
- case ArrayType.NUMBER:
23
- output.push(`export let ${fieldName} = new Array<number>(${fieldArrayLength})${fieldArrayLength ? ".fill(0)" : ""}`);
24
- break;
25
- case ArrayType.BOOLEAN:
26
- output.push(`export let ${fieldName} = new Array<boolean>(${fieldArrayLength})${fieldArrayLength ? ".fill(false)" : ""}`);
27
- break;
28
- default:
29
- output.push(`export let ${fieldName} = new Array<${getName(fieldArrayType)}>()`);
30
- }
31
- }
32
- break;
33
- case FieldType.SET:
34
- output.push(`export let ${fieldName} = new Set<${getName(fieldArrayType)}>()`);
35
- break;
36
- default:
37
- output.push(`export let ${fieldName} = create${capitalize(fieldType)}()`);
38
- }
39
- }
40
- export function addFieldSetFunction(name, type, field, output) {
41
- const [fieldName, fieldType, fieldArrayType] = field.split(" ");
42
- output.push("");
43
- output.push(`/** Set the value of the ${fieldName} field within the ${name} ${getName(type)}. */`);
44
- output.push(`export function set${capitalize(fieldName)}(value: ${getName(fieldType, fieldArrayType)}) {`);
45
- output.push(` ${fieldName} = value`);
46
- output.push("}");
47
- }
48
- export function addFieldZeroFunction(name, type, field, baseLength, output) {
49
- const [fieldName, fieldType, fieldArrayType, fieldLength] = field.split(" ");
50
- const length = baseLength || fieldLength || "";
51
- output.push("");
52
- output.push(`/** Zero the ${fieldName} field within the ${name} ${getName(type)}. */`);
53
- output.push(`export function zero${capitalize(fieldName)}() {`);
54
- zeroField(fieldName, fieldType, fieldArrayType, length, output);
55
- output.push("}");
56
- }
57
- export function addZeroFunction(name, type, fields, baseLength, output) {
58
- output.push("");
59
- output.push(`/** Zero all fields within the ${name} ${getName(type)}. */`);
60
- output.push(`export function zero${capitalize(name)}Data() {`);
61
- for (const field of fields) {
62
- const [fieldName, fieldType, fieldArrayType, fieldLength] = field.split(" ");
63
- const length = baseLength || fieldLength || "";
64
- zeroField(fieldName, fieldType, fieldArrayType, length, output);
65
- }
66
- output.push("}");
67
- }
68
- function zeroField(name, type, arrayType, length, output) {
69
- switch (type) {
70
- case FieldType.STRING:
71
- output.push(` ${name} = ""`);
72
- break;
73
- case FieldType.NUMBER:
74
- output.push(` ${name} = 0`);
75
- break;
76
- case FieldType.BOOLEAN:
77
- output.push(` ${name} = false`);
78
- break;
79
- case FieldType.ARRAY:
80
- {
81
- switch (arrayType) {
82
- case ArrayType.STRING:
83
- output.push(` ${name}.${length ? 'fill("")' : "length = 0"}`);
84
- break;
85
- case ArrayType.NUMBER:
86
- output.push(` ${name}.${length ? "fill(0)" : "length = 0"}`);
87
- break;
88
- case ArrayType.BOOLEAN:
89
- output.push(` ${name}.${length ? "fill(false)" : "length = 0"}`);
90
- break;
91
- default:
92
- output.push(` ${name}.length = 0`);
93
- }
94
- }
95
- break;
96
- case FieldType.SET:
97
- output.push(` ${name}.clear()`);
98
- break;
99
- default:
100
- output.push(` zero${capitalize(type)}(${name})`);
101
- }
102
- }
103
- export function addFieldMaxLengthConstant(name, length, output) {
104
- output.push(`export const MAX_${name.toUpperCase()} = ${length}`);
105
- output.push("");
106
- }