game-data-gen 2.2.0 → 3.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 +116 -106
- package/dist/consts.js +0 -1
- package/dist/lib/aos.js +18 -17
- package/dist/lib/fields.js +1 -1
- package/dist/lib/group.js +71 -6
- package/dist/lib/soa.js +69 -17
- package/dist/lib/struct.js +32 -44
- package/dist/lib/utils.js +11 -4
- package/dist/main.js +12 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ If you're making a game in Javascript then you might (this was actually me):
|
|
|
16
16
|
|
|
17
17
|
This library:
|
|
18
18
|
|
|
19
|
-
- creates data structures based on
|
|
19
|
+
- creates data structures based on Markdown file (see example below)
|
|
20
20
|
- each data structure gets associated functions to zero out its memory so it can be reused
|
|
21
21
|
|
|
22
22
|
## Installation
|
|
@@ -31,122 +31,98 @@ npm i -D game-data-gen
|
|
|
31
31
|
npx game-data-gen <input-file-path> <optional-output-file-path>
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
## Format
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
name type? length? struct?
|
|
38
|
-
fieldName fieldType fieldArrayType? fieldArrayLength?
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
`name`
|
|
42
|
-
|
|
43
|
-
The name of the data structure.
|
|
44
|
-
|
|
45
|
-
`type`
|
|
46
|
-
|
|
47
|
-
Supported data structure types:
|
|
48
|
-
|
|
49
|
-
- group
|
|
50
|
-
- struct
|
|
51
|
-
- soa (Structure of Arrays)
|
|
52
|
-
- aos (Array of Structures)
|
|
53
|
-
|
|
54
|
-
`length` (optional)
|
|
55
|
-
|
|
56
|
-
The length of the arrays within the Structure of Arrays data structure.
|
|
57
|
-
|
|
58
|
-
If no length is given to the type and no length is given to a field it is considered a dynamic array and zeroing will set the array's length back to zero (emptying it).
|
|
59
|
-
|
|
60
|
-
`struct` (optional, required if type=aos)
|
|
61
|
-
|
|
62
|
-
The struct to use for this Array of Structures.
|
|
63
|
-
|
|
64
|
-
`fieldName`
|
|
65
|
-
|
|
66
|
-
The name of one of the fields within the data structure.
|
|
67
|
-
|
|
68
|
-
`fieldType`
|
|
69
|
-
|
|
70
|
-
Supported field types:
|
|
71
|
-
|
|
72
|
-
- string
|
|
73
|
-
- number
|
|
74
|
-
- boolean
|
|
75
|
-
- array
|
|
76
|
-
- a struct (see entity struct in example below)
|
|
77
|
-
|
|
78
|
-
`fieldArrayType` (required if fieldType=array)
|
|
79
|
-
|
|
80
|
-
Supported array field types:
|
|
81
|
-
|
|
82
|
-
- string
|
|
83
|
-
- boolean
|
|
84
|
-
- number
|
|
85
|
-
|
|
86
|
-
`fieldArrayLength` (optional)
|
|
87
|
-
|
|
88
|
-
The length of the array field, leave empty to use a dynamically sized array instead of a fixed size array.
|
|
89
|
-
|
|
90
|
-
In case of a Structure of Arrays data structure (type=soa), setting the length on the type instead is recommended so that all arrays have the same length.
|
|
91
|
-
|
|
92
|
-
|
|
93
34
|
## Example
|
|
94
35
|
|
|
95
|
-
Create a
|
|
36
|
+
Create a Markdown file somewhere in your source code (without a file extension).
|
|
96
37
|
|
|
97
|
-
For example `src/data
|
|
38
|
+
For example `src/data.md`:
|
|
98
39
|
|
|
99
|
-
```
|
|
100
|
-
game group
|
|
101
|
-
activeEntities array
|
|
40
|
+
```md
|
|
41
|
+
# game group
|
|
42
|
+
- activeEntities array entity
|
|
43
|
+
- activeEntityIds array number
|
|
44
|
+
- playerId number
|
|
102
45
|
|
|
103
|
-
vector struct
|
|
104
|
-
x number
|
|
105
|
-
y number
|
|
46
|
+
# vector struct
|
|
47
|
+
- x number
|
|
48
|
+
- y number
|
|
106
49
|
|
|
107
|
-
entity struct
|
|
108
|
-
position vector
|
|
109
|
-
velocity vector
|
|
110
|
-
|
|
111
|
-
|
|
50
|
+
# entity struct
|
|
51
|
+
- position vector
|
|
52
|
+
- velocity vector
|
|
53
|
+
<!-- stats -->
|
|
54
|
+
- health number
|
|
55
|
+
<!-- inventory -->
|
|
56
|
+
- items array number
|
|
57
|
+
<!-- flags -->
|
|
58
|
+
- isActive boolean
|
|
112
59
|
|
|
113
|
-
entities aos 2048 entity
|
|
60
|
+
# entities aos 2048 entity
|
|
114
61
|
|
|
115
|
-
particle soa
|
|
116
|
-
|
|
117
|
-
|
|
62
|
+
# particle soa 10_000
|
|
63
|
+
- type string
|
|
64
|
+
- pos Vector
|
|
118
65
|
```
|
|
119
66
|
|
|
120
67
|
Run the package with (consider making this a script in your package.json):
|
|
121
68
|
|
|
122
69
|
```shell
|
|
123
|
-
npx game-data-gen src/data
|
|
70
|
+
npx game-data-gen src/data.md
|
|
124
71
|
```
|
|
125
72
|
|
|
126
|
-
This will create or update the `src/data
|
|
73
|
+
This will create or update the `src/data.ts` file (see below). The data and functions can then be imported from this file into your code.
|
|
127
74
|
|
|
128
75
|
```typescript
|
|
129
76
|
/*
|
|
130
77
|
* --------------------------------------------------
|
|
131
|
-
* game (
|
|
78
|
+
* game (Group)
|
|
132
79
|
* --------------------------------------------------
|
|
133
80
|
*/
|
|
134
81
|
|
|
135
|
-
export
|
|
82
|
+
export let activeEntities = new Array<Entity>()
|
|
83
|
+
export let activeEntityIds = new Array<number>()
|
|
84
|
+
export let playerId = 0
|
|
85
|
+
|
|
86
|
+
/** Set the value of the activeEntities field within the game group. */
|
|
87
|
+
export function setActiveEntities(value: Array<Entity>) {
|
|
88
|
+
activeEntities = value
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Set the value of the activeEntityIds field within the game group. */
|
|
92
|
+
export function setActiveEntityIds(value: Array<number>) {
|
|
93
|
+
activeEntityIds = value
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Set the value of the playerId field within the game group. */
|
|
97
|
+
export function setPlayerId(value: number) {
|
|
98
|
+
playerId = value
|
|
99
|
+
}
|
|
136
100
|
|
|
137
101
|
/** Zero the activeEntities field within the game group. */
|
|
138
102
|
export function zeroActiveEntities() {
|
|
139
103
|
activeEntities.length = 0
|
|
140
104
|
}
|
|
141
105
|
|
|
106
|
+
/** Zero the activeEntityIds field within the game group. */
|
|
107
|
+
export function zeroActiveEntityIds() {
|
|
108
|
+
activeEntityIds.length = 0
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Zero the playerId field within the game group. */
|
|
112
|
+
export function zeroPlayerId() {
|
|
113
|
+
playerId = 0
|
|
114
|
+
}
|
|
115
|
+
|
|
142
116
|
/** Zero all fields within the game group. */
|
|
143
117
|
export function zeroGameData() {
|
|
144
118
|
activeEntities.length = 0
|
|
119
|
+
activeEntityIds.length = 0
|
|
120
|
+
playerId = 0
|
|
145
121
|
}
|
|
146
122
|
|
|
147
123
|
/*
|
|
148
124
|
* --------------------------------------------------
|
|
149
|
-
* vector (
|
|
125
|
+
* vector (Struct)
|
|
150
126
|
* --------------------------------------------------
|
|
151
127
|
*/
|
|
152
128
|
|
|
@@ -156,13 +132,26 @@ export type Vector = {
|
|
|
156
132
|
}
|
|
157
133
|
|
|
158
134
|
/** Create a new Vector object. */
|
|
159
|
-
export function createVector()
|
|
160
|
-
const obj = Object.create(null)
|
|
135
|
+
export function createVector() {
|
|
136
|
+
const obj: Vector = Object.create(null)
|
|
161
137
|
obj.x = 0
|
|
162
138
|
obj.y = 0
|
|
163
139
|
return obj
|
|
164
140
|
}
|
|
165
141
|
|
|
142
|
+
/** Copy the values of Vector object b into Vector object a. */
|
|
143
|
+
export function copyVector(a: Vector, b: Vector) {
|
|
144
|
+
a.x = b.x
|
|
145
|
+
a.y = b.y
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Clone the given Vector object. */
|
|
149
|
+
export function cloneVector(obj: Vector) {
|
|
150
|
+
const clone = createVector()
|
|
151
|
+
copyVector(clone, obj)
|
|
152
|
+
return clone
|
|
153
|
+
}
|
|
154
|
+
|
|
166
155
|
/** Zero the given Vector object. */
|
|
167
156
|
export function zeroVector(obj: Vector) {
|
|
168
157
|
obj.x = 0
|
|
@@ -171,7 +160,7 @@ export function zeroVector(obj: Vector) {
|
|
|
171
160
|
|
|
172
161
|
/*
|
|
173
162
|
* --------------------------------------------------
|
|
174
|
-
* entity (
|
|
163
|
+
* entity (Struct)
|
|
175
164
|
* --------------------------------------------------
|
|
176
165
|
*/
|
|
177
166
|
|
|
@@ -179,40 +168,56 @@ export type Entity = {
|
|
|
179
168
|
position: Vector
|
|
180
169
|
velocity: Vector
|
|
181
170
|
health: number
|
|
171
|
+
items: Array<number>
|
|
182
172
|
isActive: boolean
|
|
183
173
|
}
|
|
184
174
|
|
|
185
175
|
/** Create a new Entity object. */
|
|
186
|
-
export function createEntity()
|
|
187
|
-
const obj = Object.create(null)
|
|
176
|
+
export function createEntity() {
|
|
177
|
+
const obj: Entity = Object.create(null)
|
|
188
178
|
obj.position = createVector()
|
|
189
179
|
obj.velocity = createVector()
|
|
190
180
|
obj.health = 0
|
|
181
|
+
obj.items = new Array<number>()
|
|
191
182
|
obj.isActive = false
|
|
192
183
|
return obj
|
|
193
184
|
}
|
|
194
185
|
|
|
186
|
+
/** Copy the values of Entity object b into Entity object a. */
|
|
187
|
+
export function copyEntity(a: Entity, b: Entity) {
|
|
188
|
+
a.position = b.position
|
|
189
|
+
a.velocity = b.velocity
|
|
190
|
+
a.health = b.health
|
|
191
|
+
a.items = b.items
|
|
192
|
+
a.isActive = b.isActive
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Clone the given Entity object. */
|
|
196
|
+
export function cloneEntity(obj: Entity) {
|
|
197
|
+
const clone = createEntity()
|
|
198
|
+
copyEntity(clone, obj)
|
|
199
|
+
return clone
|
|
200
|
+
}
|
|
201
|
+
|
|
195
202
|
/** Zero the given Entity object. */
|
|
196
203
|
export function zeroEntity(obj: Entity) {
|
|
197
204
|
zeroVector(obj.position)
|
|
198
205
|
zeroVector(obj.velocity)
|
|
199
206
|
obj.health = 0
|
|
207
|
+
obj.items.length = 0
|
|
200
208
|
obj.isActive = false
|
|
201
209
|
}
|
|
202
210
|
|
|
203
211
|
/*
|
|
204
212
|
* --------------------------------------------------
|
|
205
|
-
* entities (
|
|
213
|
+
* entities (Array Of Structures)
|
|
206
214
|
* --------------------------------------------------
|
|
207
215
|
*/
|
|
208
216
|
|
|
209
217
|
export const MAX_ENTITIES_COUNT = 2048
|
|
210
218
|
|
|
211
219
|
/** An array of Entity objects (structures). */
|
|
212
|
-
export const entities =
|
|
213
|
-
for (let i=0; i<2048; i++) {
|
|
214
|
-
entities[i] = createEntity()
|
|
215
|
-
}
|
|
220
|
+
export const entities = Array.from({ length: 2048 }, createEntity)
|
|
216
221
|
|
|
217
222
|
/** Zero all objects within the entities array of structures. */
|
|
218
223
|
export function zeroEntities() {
|
|
@@ -221,36 +226,41 @@ export function zeroEntities() {
|
|
|
221
226
|
}
|
|
222
227
|
}
|
|
223
228
|
|
|
229
|
+
/** Zero an object at a specific index within the entities array of structures. */
|
|
230
|
+
export function zeroEntitiesAt(index: number) {
|
|
231
|
+
zeroEntity(entities[index])
|
|
232
|
+
}
|
|
233
|
+
|
|
224
234
|
/*
|
|
225
235
|
* --------------------------------------------------
|
|
226
|
-
* particle (
|
|
236
|
+
* particle (Structure Of Arrays)
|
|
227
237
|
* --------------------------------------------------
|
|
228
238
|
*/
|
|
229
239
|
|
|
230
|
-
export const MAX_PARTICLE_COUNT =
|
|
240
|
+
export const MAX_PARTICLE_COUNT = 10_000
|
|
231
241
|
|
|
232
|
-
export const
|
|
233
|
-
export const
|
|
242
|
+
export const type = new Array(10_000).fill("")
|
|
243
|
+
export const pos = Array.from({ length: 10_000 }, createVector)
|
|
234
244
|
|
|
235
245
|
/** Zero an index within the particle structure of arrays. */
|
|
236
246
|
export function zeroParticle(idx: number) {
|
|
237
|
-
|
|
238
|
-
|
|
247
|
+
type[idx] = ""
|
|
248
|
+
zeroVector(pos[idx])
|
|
239
249
|
}
|
|
240
250
|
|
|
241
|
-
/** Zero the
|
|
242
|
-
export function
|
|
243
|
-
|
|
251
|
+
/** Zero the type field within the particle structure of arrays. */
|
|
252
|
+
export function zeroType() {
|
|
253
|
+
type.fill("")
|
|
244
254
|
}
|
|
245
255
|
|
|
246
|
-
/** Zero the
|
|
247
|
-
export function
|
|
248
|
-
|
|
256
|
+
/** Zero the pos field within the particle structure of arrays. */
|
|
257
|
+
export function zeroPos() {
|
|
258
|
+
pos.forEach(zeroVector)
|
|
249
259
|
}
|
|
250
260
|
|
|
251
261
|
/** Zero all fields within the particle structure of arrays. */
|
|
252
262
|
export function zeroParticleData() {
|
|
253
|
-
|
|
254
|
-
|
|
263
|
+
type.fill("")
|
|
264
|
+
pos.forEach(zeroVector)
|
|
255
265
|
}
|
|
256
266
|
```
|
package/dist/consts.js
CHANGED
package/dist/lib/aos.js
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { capitalize, getName } from "./utils.js";
|
|
1
|
+
import { addHeader, capitalize } from "./utils.js";
|
|
3
2
|
export function addArrayOfStructures(header, output) {
|
|
4
|
-
const [name, , length,
|
|
3
|
+
const [name, , length, type] = header.split(" ");
|
|
4
|
+
addHeader(`${name} (Array Of Structures)`, output);
|
|
5
5
|
addFieldMaxLengthConstant(name, length, output);
|
|
6
|
-
addArrayOfStructuresDefinition(name,
|
|
7
|
-
addArrayOfStructuresZeroFunction(name,
|
|
8
|
-
addArrayOfStructuresZeroAtIndexFunction(name,
|
|
6
|
+
addArrayOfStructuresDefinition(name, type, length, output);
|
|
7
|
+
addArrayOfStructuresZeroFunction(name, type, length, output);
|
|
8
|
+
addArrayOfStructuresZeroAtIndexFunction(name, type, output);
|
|
9
9
|
}
|
|
10
|
-
function
|
|
11
|
-
output.push(
|
|
12
|
-
output.push(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
output.push(
|
|
10
|
+
function addFieldMaxLengthConstant(name, length, output) {
|
|
11
|
+
output.push(`export const MAX_${name.toUpperCase()}_COUNT = ${length}`);
|
|
12
|
+
output.push("");
|
|
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)})`);
|
|
16
17
|
}
|
|
17
|
-
function addArrayOfStructuresZeroFunction(name,
|
|
18
|
+
function addArrayOfStructuresZeroFunction(name, type, length, output) {
|
|
18
19
|
output.push("");
|
|
19
20
|
output.push(`/** Zero all objects within the ${name} array of structures. */`);
|
|
20
21
|
output.push(`export function zero${capitalize(name)}() {`);
|
|
21
22
|
output.push(` for (let i=0; i<${length}; i++) {`);
|
|
22
|
-
output.push(` zero${capitalize(
|
|
23
|
+
output.push(` zero${capitalize(type)}(${name}[i])`);
|
|
23
24
|
output.push(" }");
|
|
24
25
|
output.push("}");
|
|
25
26
|
}
|
|
26
|
-
function addArrayOfStructuresZeroAtIndexFunction(name,
|
|
27
|
+
function addArrayOfStructuresZeroAtIndexFunction(name, type, output) {
|
|
27
28
|
output.push("");
|
|
28
29
|
output.push(`/** Zero an object at a specific index within the ${name} array of structures. */`);
|
|
29
|
-
output.push(`export function zero${capitalize(
|
|
30
|
-
output.push(` zero${capitalize(
|
|
30
|
+
output.push(`export function zero${capitalize(name)}At(i: number) {`);
|
|
31
|
+
output.push(` zero${capitalize(type)}(${name}[i])`);
|
|
31
32
|
output.push("}");
|
|
32
33
|
}
|
package/dist/lib/fields.js
CHANGED
|
@@ -101,6 +101,6 @@ function zeroField(name, type, arrayType, length, output) {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
export function addFieldMaxLengthConstant(name, length, output) {
|
|
104
|
-
output.push(`export const MAX_${name.toUpperCase()}
|
|
104
|
+
output.push(`export const MAX_${name.toUpperCase()} = ${length}`);
|
|
105
105
|
output.push("");
|
|
106
106
|
}
|
package/dist/lib/group.js
CHANGED
|
@@ -1,14 +1,79 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldType } from "../consts.js";
|
|
2
|
+
import { addHeader, capitalize, getTypeName } from "./utils.js";
|
|
2
3
|
export function addGroup(header, fields, output) {
|
|
3
|
-
const [name
|
|
4
|
+
const [name] = header.split(" ");
|
|
5
|
+
addHeader(`${name} (Group)`, output);
|
|
4
6
|
for (const field of fields) {
|
|
5
|
-
addFieldDefinition(field,
|
|
7
|
+
addFieldDefinition(field, output);
|
|
6
8
|
}
|
|
7
9
|
for (const field of fields) {
|
|
8
|
-
addFieldSetFunction(name,
|
|
10
|
+
addFieldSetFunction(name, field, output);
|
|
9
11
|
}
|
|
10
12
|
for (const field of fields) {
|
|
11
|
-
addFieldZeroFunction(name,
|
|
13
|
+
addFieldZeroFunction(name, field, output);
|
|
14
|
+
}
|
|
15
|
+
addZeroFunction(name, fields, output);
|
|
16
|
+
}
|
|
17
|
+
function addFieldDefinition(field, output) {
|
|
18
|
+
const [fieldName, fieldType, fieldArrayType] = field.split(" ");
|
|
19
|
+
switch (fieldType) {
|
|
20
|
+
case FieldType.STRING:
|
|
21
|
+
output.push(`export let ${fieldName} = ""`);
|
|
22
|
+
break;
|
|
23
|
+
case FieldType.NUMBER:
|
|
24
|
+
output.push(`export let ${fieldName} = 0`);
|
|
25
|
+
break;
|
|
26
|
+
case FieldType.BOOLEAN:
|
|
27
|
+
output.push(`export let ${fieldName} = false`);
|
|
28
|
+
break;
|
|
29
|
+
case FieldType.ARRAY:
|
|
30
|
+
output.push(`export let ${fieldName} = new Array<${getTypeName(fieldArrayType)}>()`);
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
output.push(`export let ${fieldName} = create${capitalize(fieldType)}()`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
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("}");
|
|
43
|
+
}
|
|
44
|
+
function addFieldZeroFunction(name, field, output) {
|
|
45
|
+
const [fieldName, fieldType] = field.split(" ");
|
|
46
|
+
output.push("");
|
|
47
|
+
output.push(`/** Zero the ${fieldName} field within the ${name} group. */`);
|
|
48
|
+
output.push(`export function zero${capitalize(fieldName)}() {`);
|
|
49
|
+
zeroField(fieldName, fieldType, output);
|
|
50
|
+
output.push("}");
|
|
51
|
+
}
|
|
52
|
+
function addZeroFunction(name, fields, output) {
|
|
53
|
+
output.push("");
|
|
54
|
+
output.push(`/** Zero all fields within the ${name} group. */`);
|
|
55
|
+
output.push(`export function zero${capitalize(name)}Data() {`);
|
|
56
|
+
for (const field of fields) {
|
|
57
|
+
const [fieldName, fieldType] = field.split(" ");
|
|
58
|
+
zeroField(fieldName, fieldType, output);
|
|
59
|
+
}
|
|
60
|
+
output.push("}");
|
|
61
|
+
}
|
|
62
|
+
function zeroField(name, type, output) {
|
|
63
|
+
switch (type) {
|
|
64
|
+
case FieldType.STRING:
|
|
65
|
+
output.push(` ${name} = ""`);
|
|
66
|
+
break;
|
|
67
|
+
case FieldType.NUMBER:
|
|
68
|
+
output.push(` ${name} = 0`);
|
|
69
|
+
break;
|
|
70
|
+
case FieldType.BOOLEAN:
|
|
71
|
+
output.push(` ${name} = false`);
|
|
72
|
+
break;
|
|
73
|
+
case FieldType.ARRAY:
|
|
74
|
+
output.push(` ${name}.length = 0`);
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
output.push(` zero${capitalize(type)}(${name})`);
|
|
12
78
|
}
|
|
13
|
-
addZeroFunction(name, type, fields, baseLength, output);
|
|
14
79
|
}
|
package/dist/lib/soa.js
CHANGED
|
@@ -1,37 +1,89 @@
|
|
|
1
1
|
import { ArrayType } from "../consts.js";
|
|
2
|
-
import {
|
|
3
|
-
import { capitalize, getName } from "./utils.js";
|
|
2
|
+
import { addHeader, capitalize } from "./utils.js";
|
|
4
3
|
export function addStructureOfArrays(header, fields, output) {
|
|
5
|
-
const [name,
|
|
6
|
-
|
|
4
|
+
const [name, _, length] = header.split(" ");
|
|
5
|
+
addHeader(`${name} (Structure Of Arrays)`, output);
|
|
6
|
+
addFieldMaxLengthConstant(name, length, output);
|
|
7
7
|
for (const field of fields) {
|
|
8
|
-
addFieldDefinition(field,
|
|
8
|
+
addFieldDefinition(field, length, output);
|
|
9
9
|
}
|
|
10
|
+
addFieldZeroAtIndexFunction(name, fields, output);
|
|
10
11
|
for (const field of fields) {
|
|
11
|
-
|
|
12
|
+
addFieldZeroFunction(name, field, output);
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
+
addZeroFunction(name, fields, output);
|
|
15
|
+
}
|
|
16
|
+
function addFieldMaxLengthConstant(name, length, output) {
|
|
17
|
+
output.push(`export const MAX_${name.toUpperCase()}_COUNT = ${length}`);
|
|
18
|
+
output.push("");
|
|
19
|
+
}
|
|
20
|
+
function addFieldDefinition(field, length, output) {
|
|
21
|
+
const [fieldName, fieldType] = field.split(" ");
|
|
22
|
+
switch (fieldType) {
|
|
23
|
+
case ArrayType.STRING:
|
|
24
|
+
output.push(`export const ${fieldName} = new Array(${length}).fill("")`);
|
|
25
|
+
break;
|
|
26
|
+
case ArrayType.NUMBER:
|
|
27
|
+
output.push(`export const ${fieldName} = new Array(${length}).fill(0)`);
|
|
28
|
+
break;
|
|
29
|
+
case ArrayType.BOOLEAN:
|
|
30
|
+
output.push(`export const ${fieldName} = new Array(${length}).fill(false)`);
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
output.push(`export const ${fieldName} = Array.from({ length: ${length} }, create${capitalize(fieldType)})`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function addFieldZeroFunction(name, field, output) {
|
|
37
|
+
const [fieldName, fieldType] = field.split(" ");
|
|
38
|
+
output.push("");
|
|
39
|
+
output.push(`/** Zero the ${fieldName} field within the ${name} structure of arrays. */`);
|
|
40
|
+
output.push(`export function zero${capitalize(fieldName)}() {`);
|
|
41
|
+
zeroField(fieldName, fieldType, output);
|
|
42
|
+
output.push("}");
|
|
43
|
+
}
|
|
44
|
+
function addZeroFunction(name, fields, output) {
|
|
45
|
+
output.push("");
|
|
46
|
+
output.push(`/** Zero all fields within the ${name} structure of arrays. */`);
|
|
47
|
+
output.push(`export function zero${capitalize(name)}Data() {`);
|
|
14
48
|
for (const field of fields) {
|
|
15
|
-
|
|
49
|
+
const [fieldName, fieldType] = field.split(" ");
|
|
50
|
+
zeroField(fieldName, fieldType, output);
|
|
51
|
+
}
|
|
52
|
+
output.push("}");
|
|
53
|
+
}
|
|
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)})`);
|
|
16
67
|
}
|
|
17
|
-
addZeroFunction(name, type, fields, baseLength, output);
|
|
18
68
|
}
|
|
19
|
-
function addFieldZeroAtIndexFunction(name,
|
|
69
|
+
function addFieldZeroAtIndexFunction(name, fields, output) {
|
|
20
70
|
output.push("");
|
|
21
|
-
output.push(`/** Zero an index within the ${name}
|
|
22
|
-
output.push(`export function zero${capitalize(name)}(
|
|
71
|
+
output.push(`/** Zero an index within the ${name} structure of arrays. */`);
|
|
72
|
+
output.push(`export function zero${capitalize(name)}(i: number) {`);
|
|
23
73
|
for (const field of fields) {
|
|
24
|
-
const [fieldName,
|
|
25
|
-
switch (
|
|
74
|
+
const [fieldName, fieldType] = field.split(" ");
|
|
75
|
+
switch (fieldType) {
|
|
26
76
|
case ArrayType.STRING:
|
|
27
|
-
output.push(` ${fieldName}[
|
|
77
|
+
output.push(` ${fieldName}[i] = ""`);
|
|
28
78
|
break;
|
|
29
79
|
case ArrayType.NUMBER:
|
|
30
|
-
output.push(` ${fieldName}[
|
|
80
|
+
output.push(` ${fieldName}[i] = 0`);
|
|
31
81
|
break;
|
|
32
82
|
case ArrayType.BOOLEAN:
|
|
33
|
-
output.push(` ${fieldName}[
|
|
83
|
+
output.push(` ${fieldName}[i] = false`);
|
|
34
84
|
break;
|
|
85
|
+
default:
|
|
86
|
+
output.push(` zero${capitalize(fieldType)}(${fieldName}[i])`);
|
|
35
87
|
}
|
|
36
88
|
}
|
|
37
89
|
output.push("}");
|
package/dist/lib/struct.js
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { capitalize,
|
|
1
|
+
import { FieldType } from "../consts.js";
|
|
2
|
+
import { addHeader, capitalize, getTypeName } from "./utils.js";
|
|
3
3
|
export function addStruct(header, fields, output) {
|
|
4
4
|
const [name] = header.split(" ");
|
|
5
|
+
addHeader(`${name} (Struct)`, output);
|
|
5
6
|
addStructTypeDefinition(name, fields, output);
|
|
6
7
|
addStructCreateFunction(name, fields, output);
|
|
8
|
+
addStructCopyFunction(name, fields, output);
|
|
9
|
+
addStructCloneFunction(name, output);
|
|
7
10
|
addStructZeroFunction(name, fields, output);
|
|
8
11
|
}
|
|
9
12
|
function addStructTypeDefinition(name, fields, output) {
|
|
10
13
|
output.push(`export type ${capitalize(name)} = {`);
|
|
11
14
|
for (const field of fields) {
|
|
12
15
|
const [fieldName, fieldType, fieldArrayType] = field.split(" ");
|
|
13
|
-
output.push(` ${fieldName}: ${
|
|
16
|
+
output.push(` ${fieldName}: ${getTypeName(fieldType, fieldArrayType)}`);
|
|
14
17
|
}
|
|
15
18
|
output.push("}");
|
|
16
19
|
}
|
|
17
20
|
function addStructCreateFunction(name, fields, output) {
|
|
18
21
|
output.push("");
|
|
19
22
|
output.push(`/** Create a new ${capitalize(name)} object. */`);
|
|
20
|
-
output.push(`export function create${capitalize(name)}()
|
|
21
|
-
output.push(` const obj = Object.create(null)`);
|
|
23
|
+
output.push(`export function create${capitalize(name)}() {`);
|
|
24
|
+
output.push(` const obj: ${getTypeName(name)} = Object.create(null)`);
|
|
22
25
|
for (const field of fields) {
|
|
23
|
-
const [fieldName, fieldType, fieldArrayType
|
|
26
|
+
const [fieldName, fieldType, fieldArrayType] = field.split(" ");
|
|
24
27
|
switch (fieldType) {
|
|
25
28
|
case FieldType.STRING:
|
|
26
29
|
output.push(` obj.${fieldName} = ""`);
|
|
@@ -32,24 +35,7 @@ function addStructCreateFunction(name, fields, output) {
|
|
|
32
35
|
output.push(` obj.${fieldName} = false`);
|
|
33
36
|
break;
|
|
34
37
|
case FieldType.ARRAY:
|
|
35
|
-
{
|
|
36
|
-
switch (fieldArrayType) {
|
|
37
|
-
case ArrayType.STRING:
|
|
38
|
-
output.push(` obj.${fieldName} = new Array<string>(${fieldArrayLength})${fieldArrayLength ? '.fill("")' : ""}`);
|
|
39
|
-
break;
|
|
40
|
-
case ArrayType.NUMBER:
|
|
41
|
-
output.push(` obj.${fieldName} = new Array<number>(${fieldArrayLength})${fieldArrayLength ? ".fill(0)" : ""}`);
|
|
42
|
-
break;
|
|
43
|
-
case ArrayType.BOOLEAN:
|
|
44
|
-
output.push(` obj.${fieldName} = new Array<boolean>(${fieldArrayLength})${fieldArrayLength ? ".fill(false)" : ""}`);
|
|
45
|
-
break;
|
|
46
|
-
default:
|
|
47
|
-
output.push(` obj.${fieldName} = new Array<${getName(fieldArrayType)}>()`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
break;
|
|
51
|
-
case FieldType.SET:
|
|
52
|
-
output.push(` obj.${fieldName} = new Set<${getName(fieldArrayType)}>()`);
|
|
38
|
+
output.push(` obj.${fieldName} = new Array<${getTypeName(fieldArrayType)}>()`);
|
|
53
39
|
break;
|
|
54
40
|
default: {
|
|
55
41
|
output.push(` obj.${fieldName} = create${capitalize(fieldType)}()`);
|
|
@@ -59,12 +45,31 @@ function addStructCreateFunction(name, fields, output) {
|
|
|
59
45
|
output.push(" return obj");
|
|
60
46
|
output.push("}");
|
|
61
47
|
}
|
|
48
|
+
function addStructCopyFunction(name, fields, output) {
|
|
49
|
+
output.push("");
|
|
50
|
+
output.push(`/** Copy the values of ${capitalize(name)} object b into ${capitalize(name)} object a. */`);
|
|
51
|
+
output.push(`export function copy${capitalize(name)}(a: ${getTypeName(name)}, b: ${getTypeName(name)}) {`);
|
|
52
|
+
for (const field of fields) {
|
|
53
|
+
const [fieldName] = field.split(" ");
|
|
54
|
+
output.push(` a.${fieldName} = b.${fieldName}`);
|
|
55
|
+
}
|
|
56
|
+
output.push("}");
|
|
57
|
+
}
|
|
58
|
+
function addStructCloneFunction(name, output) {
|
|
59
|
+
output.push("");
|
|
60
|
+
output.push(`/** Clone the given ${capitalize(name)} object. */`);
|
|
61
|
+
output.push(`export function clone${capitalize(name)}(obj: ${getTypeName(name)}) {`);
|
|
62
|
+
output.push(` const clone = create${capitalize(name)}()`);
|
|
63
|
+
output.push(` copy${capitalize(name)}(clone, obj)`);
|
|
64
|
+
output.push(" return clone");
|
|
65
|
+
output.push("}");
|
|
66
|
+
}
|
|
62
67
|
function addStructZeroFunction(name, fields, output) {
|
|
63
68
|
output.push("");
|
|
64
69
|
output.push(`/** Zero the given ${capitalize(name)} object. */`);
|
|
65
|
-
output.push(`export function zero${capitalize(name)}(obj: ${
|
|
70
|
+
output.push(`export function zero${capitalize(name)}(obj: ${getTypeName(name)}) {`);
|
|
66
71
|
for (const field of fields) {
|
|
67
|
-
const [fieldName, fieldType
|
|
72
|
+
const [fieldName, fieldType] = field.split(" ");
|
|
68
73
|
switch (fieldType) {
|
|
69
74
|
case FieldType.STRING:
|
|
70
75
|
output.push(` obj.${fieldName} = ""`);
|
|
@@ -76,24 +81,7 @@ function addStructZeroFunction(name, fields, output) {
|
|
|
76
81
|
output.push(` obj.${fieldName} = false`);
|
|
77
82
|
break;
|
|
78
83
|
case FieldType.ARRAY:
|
|
79
|
-
{
|
|
80
|
-
switch (fieldArrayType) {
|
|
81
|
-
case ArrayType.STRING:
|
|
82
|
-
output.push(` obj.${fieldName}.${fieldArrayLength ? 'fill("")' : "length = 0"}`);
|
|
83
|
-
break;
|
|
84
|
-
case ArrayType.NUMBER:
|
|
85
|
-
output.push(` obj.${fieldName}.${fieldArrayLength ? "fill(0)" : "length = 0"}`);
|
|
86
|
-
break;
|
|
87
|
-
case ArrayType.BOOLEAN:
|
|
88
|
-
output.push(` obj.${fieldName}.${fieldArrayLength ? "fill(false)" : "length = 0"}`);
|
|
89
|
-
break;
|
|
90
|
-
default:
|
|
91
|
-
output.push(` obj.${fieldName}.length = 0`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
break;
|
|
95
|
-
case FieldType.SET:
|
|
96
|
-
output.push(` obj.${fieldName}.clear()`);
|
|
84
|
+
output.push(` obj.${fieldName}.length = 0`);
|
|
97
85
|
break;
|
|
98
86
|
default:
|
|
99
87
|
output.push(` zero${capitalize(fieldType)}(obj.${fieldName})`);
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { FieldType, Type } from "../consts.js";
|
|
2
|
+
export function addHeader(name, output) {
|
|
3
|
+
output.push("");
|
|
4
|
+
output.push("/*");
|
|
5
|
+
output.push(` * ${"-".repeat(50)}`);
|
|
6
|
+
output.push(` * ${name}`);
|
|
7
|
+
output.push(` * ${"-".repeat(50)}`);
|
|
8
|
+
output.push(" */");
|
|
9
|
+
output.push("");
|
|
10
|
+
}
|
|
2
11
|
/**
|
|
3
12
|
* Get the name based on the type of the data structure.
|
|
4
13
|
*/
|
|
5
|
-
export function
|
|
14
|
+
export function getTypeName(type, arrayType = "") {
|
|
6
15
|
switch (type) {
|
|
7
16
|
case Type.SOA:
|
|
8
17
|
return "structure of arrays";
|
|
@@ -19,9 +28,7 @@ export function getName(type, arrayType = "") {
|
|
|
19
28
|
case FieldType.BOOLEAN:
|
|
20
29
|
return "boolean";
|
|
21
30
|
case FieldType.ARRAY:
|
|
22
|
-
return `Array<${
|
|
23
|
-
case FieldType.SET:
|
|
24
|
-
return `Set<${getName(arrayType)}>`;
|
|
31
|
+
return `Array<${getTypeName(arrayType)}>`;
|
|
25
32
|
default:
|
|
26
33
|
return capitalize(type);
|
|
27
34
|
}
|
package/dist/main.js
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var _a;
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import { Type } from "./consts.js";
|
|
4
5
|
import { addArrayOfStructures } from "./lib/aos.js";
|
|
5
6
|
import { addGroup } from "./lib/group.js";
|
|
6
7
|
import { addStructureOfArrays } from "./lib/soa.js";
|
|
7
8
|
import { addStruct } from "./lib/struct.js";
|
|
8
|
-
import { getName } from "./lib/utils.js";
|
|
9
9
|
const inputFile = process.argv[2];
|
|
10
|
-
const outputFile = process.argv[3] || `${inputFile}.ts`;
|
|
10
|
+
const outputFile = process.argv[3] || `${inputFile.replace(/\.md$/, "")}.ts`;
|
|
11
11
|
const input = fs.readFileSync(inputFile, "utf-8");
|
|
12
12
|
const output = [];
|
|
13
13
|
output.push("/*");
|
|
14
14
|
output.push(` * Generated with game-data-gen on ${new Date().toLocaleString()}. DO NOT MODIFY THIS FILE!`);
|
|
15
15
|
output.push(" */");
|
|
16
|
-
const blocks = input
|
|
16
|
+
const blocks = input
|
|
17
|
+
.split("\n")
|
|
18
|
+
.filter((line) => !line.startsWith("<!--"))
|
|
19
|
+
.join("\n")
|
|
20
|
+
.trim()
|
|
21
|
+
.split("\n\n");
|
|
17
22
|
for (const block of blocks) {
|
|
18
|
-
const
|
|
19
|
-
const header =
|
|
23
|
+
const lines = block.split("\n");
|
|
24
|
+
const header = (_a = lines.shift()) === null || _a === void 0 ? void 0 : _a.replace(/^#\s*/, "");
|
|
20
25
|
if (!header)
|
|
21
26
|
continue;
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
output.push("/*");
|
|
25
|
-
output.push(` * ${"-".repeat(50)}`);
|
|
26
|
-
output.push(` * ${name} (${getName(type)})`);
|
|
27
|
-
output.push(` * ${"-".repeat(50)}`);
|
|
28
|
-
output.push(" */");
|
|
29
|
-
output.push("");
|
|
27
|
+
const fields = lines.map((line) => line.replace(/^-\s*/, ""));
|
|
28
|
+
const [_, type] = header.split(" ");
|
|
30
29
|
switch (type) {
|
|
31
30
|
case Type.STRUCT:
|
|
32
31
|
addStruct(header, fields, output);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "game-data-gen",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"game-data-gen": "dist/main.js"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
|
-
"start": "tsc && node dist/main.js tests/data",
|
|
12
|
+
"start": "tsc && node dist/main.js tests/data.md",
|
|
13
13
|
"build": "biome check && tsc"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|