@whatever-engine/api 0.1.1-3 → 0.2.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 +51 -14
- package/dist/index.d.ts +375 -0
- package/dist/index.js +600 -0
- package/package.json +13 -9
- package/index.d.ts +0 -144
- package/index.ts +0 -443
- package/tsconfig.json +0 -12
package/dist/index.js
ADDED
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
// src/ipc.ts
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
|
|
4
|
+
// src/shared.ts
|
|
5
|
+
var _handlers = new Map;
|
|
6
|
+
var _fileCallbacks = new Map;
|
|
7
|
+
var _modListCallbacks = new Map;
|
|
8
|
+
var _modGetCallbacks = new Map;
|
|
9
|
+
var _msgCallbacks = new Map;
|
|
10
|
+
var _entityCallbacks = new Map;
|
|
11
|
+
var _entityListCallbacks = new Map;
|
|
12
|
+
var _componentGetCallbacks = new Map;
|
|
13
|
+
var _componentQueryCallbacks = new Map;
|
|
14
|
+
var _counter = { n: 0 };
|
|
15
|
+
function nextReqId() {
|
|
16
|
+
return String(++_counter.n);
|
|
17
|
+
}
|
|
18
|
+
function _send(msg) {
|
|
19
|
+
process.stdout.write(JSON.stringify(msg) + `
|
|
20
|
+
`);
|
|
21
|
+
}
|
|
22
|
+
var _EVENT_SUBSCRIBE = {
|
|
23
|
+
init: "Init",
|
|
24
|
+
exit: "Shutdown",
|
|
25
|
+
tick: "Tick"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/components/console.ts
|
|
29
|
+
var _cmdHandlers = new Map;
|
|
30
|
+
var _cmdArgSpecs = new Map;
|
|
31
|
+
function _specToInternal(spec, pathPrefix) {
|
|
32
|
+
const path = pathPrefix ? `${pathPrefix}.${spec.name}` : spec.name;
|
|
33
|
+
const mappedArgs = (spec.args ?? []).map((a) => ({
|
|
34
|
+
name: a.name,
|
|
35
|
+
type: a.type,
|
|
36
|
+
required: a.required ?? false,
|
|
37
|
+
description: a.description ?? ""
|
|
38
|
+
}));
|
|
39
|
+
if (spec.handler) {
|
|
40
|
+
_cmdHandlers.set(path, spec.handler);
|
|
41
|
+
_cmdArgSpecs.set(path, mappedArgs);
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
name: spec.name,
|
|
45
|
+
description: spec.description ?? "",
|
|
46
|
+
subcommands: (spec.subcommands ?? []).map((s) => _specToInternal(s, path)),
|
|
47
|
+
args: mappedArgs,
|
|
48
|
+
has_handler: !!spec.handler
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async function _handleCommandInvoke(msg) {
|
|
52
|
+
const handlerKey = msg.command_path.join(".");
|
|
53
|
+
const handler = _cmdHandlers.get(handlerKey);
|
|
54
|
+
const argSpecs = _cmdArgSpecs.get(handlerKey) ?? [];
|
|
55
|
+
const argsRecord = {};
|
|
56
|
+
msg.args.forEach((v, i) => {
|
|
57
|
+
const name = argSpecs[i]?.name ?? String(i);
|
|
58
|
+
argsRecord[name] = v;
|
|
59
|
+
});
|
|
60
|
+
if (!handler) {
|
|
61
|
+
_send({ type: "CommandResponse", request_id: msg.request_id, output: [], error: `no handler registered for '${handlerKey}'` });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const result = await handler(argsRecord);
|
|
66
|
+
const lines = Array.isArray(result) ? result : [result];
|
|
67
|
+
_send({ type: "CommandResponse", request_id: msg.request_id, output: lines, error: null });
|
|
68
|
+
} catch (error) {
|
|
69
|
+
const message = error instanceof Error ? error.message + `
|
|
70
|
+
` + error.stack : String(error);
|
|
71
|
+
_send({ type: "CommandResponse", request_id: msg.request_id, output: [], error: message });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
var Console = {
|
|
75
|
+
register(spec) {
|
|
76
|
+
if (!/^[a-z_]+$/.test(spec.name)) {
|
|
77
|
+
throw new Error(`Console.register: command name '${spec.name}' must match [a-z_]+`);
|
|
78
|
+
}
|
|
79
|
+
const internal = _specToInternal(spec, "");
|
|
80
|
+
_send({
|
|
81
|
+
type: "RegisterCommand",
|
|
82
|
+
name: internal.name,
|
|
83
|
+
description: internal.description,
|
|
84
|
+
subcommands: internal.subcommands,
|
|
85
|
+
args: internal.args,
|
|
86
|
+
has_handler: internal.has_handler
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// src/ipc.ts
|
|
92
|
+
function _dispatch(msg) {
|
|
93
|
+
if (msg.type === "CommandInvoke") {
|
|
94
|
+
_handleCommandInvoke(msg);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (msg.type === "Tick") {
|
|
98
|
+
const handlers = _handlers.get("tick");
|
|
99
|
+
const promises = [];
|
|
100
|
+
if (handlers) {
|
|
101
|
+
for (const fn_ of handlers) {
|
|
102
|
+
const r = fn_(msg);
|
|
103
|
+
if (r instanceof Promise)
|
|
104
|
+
promises.push(r);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
Promise.all(promises).then(() => process.stdout.write(JSON.stringify({ type: "TickDone", tick_number: msg.tick_number }) + `
|
|
108
|
+
`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (msg.type === "FileResponse") {
|
|
112
|
+
const cb = _fileCallbacks.get(msg.request_id);
|
|
113
|
+
if (cb) {
|
|
114
|
+
_fileCallbacks.delete(msg.request_id);
|
|
115
|
+
msg.error ? cb.reject(new Error(msg.error)) : cb.resolve(msg.data_base64);
|
|
116
|
+
}
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (msg.type === "ModListResponse") {
|
|
120
|
+
const cb = _modListCallbacks.get(msg.request_id);
|
|
121
|
+
if (cb) {
|
|
122
|
+
_modListCallbacks.delete(msg.request_id);
|
|
123
|
+
cb.resolve(msg.mods);
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (msg.type === "ModGetResponse") {
|
|
128
|
+
const cb = _modGetCallbacks.get(msg.request_id);
|
|
129
|
+
if (cb) {
|
|
130
|
+
_modGetCallbacks.delete(msg.request_id);
|
|
131
|
+
msg.error ? cb.reject(new Error(msg.error)) : cb.resolve(msg.manifest);
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (msg.type === "ModMessageReplyDelivered") {
|
|
136
|
+
const cb = _msgCallbacks.get(msg.request_id);
|
|
137
|
+
if (cb) {
|
|
138
|
+
_msgCallbacks.delete(msg.request_id);
|
|
139
|
+
cb.resolve(msg.payload);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (msg.type === "ModMessageReceived") {
|
|
144
|
+
const handlers = _handlers.get("mod_message");
|
|
145
|
+
if (handlers) {
|
|
146
|
+
const payload = {
|
|
147
|
+
source_mod_id: msg.source_mod_id,
|
|
148
|
+
message: msg.payload,
|
|
149
|
+
...msg.request_id !== null && { request_id: msg.request_id }
|
|
150
|
+
};
|
|
151
|
+
for (const fn_ of handlers)
|
|
152
|
+
fn_(payload);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (msg.type === "EntityCreated") {
|
|
157
|
+
const cb = _entityCallbacks.get(msg.request_id);
|
|
158
|
+
if (cb) {
|
|
159
|
+
_entityCallbacks.delete(msg.request_id);
|
|
160
|
+
cb.resolve(msg.entity_id);
|
|
161
|
+
}
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (msg.type === "EntityListResponse") {
|
|
165
|
+
const cb = _entityListCallbacks.get(msg.request_id);
|
|
166
|
+
if (cb) {
|
|
167
|
+
_entityListCallbacks.delete(msg.request_id);
|
|
168
|
+
cb.resolve(msg.entity_ids);
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (msg.type === "ComponentGetResponse") {
|
|
173
|
+
const cb = _componentGetCallbacks.get(msg.request_id);
|
|
174
|
+
if (cb) {
|
|
175
|
+
_componentGetCallbacks.delete(msg.request_id);
|
|
176
|
+
msg.error ? cb.reject(new Error(msg.error)) : cb.resolve(msg.data);
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (msg.type === "ComponentQueryResponse") {
|
|
181
|
+
const cb = _componentQueryCallbacks.get(msg.request_id);
|
|
182
|
+
if (cb) {
|
|
183
|
+
_componentQueryCallbacks.delete(msg.request_id);
|
|
184
|
+
cb.resolve(msg.results);
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
for (const [event, msgType] of Object.entries(_EVENT_SUBSCRIBE)) {
|
|
189
|
+
if (msg.type !== msgType)
|
|
190
|
+
continue;
|
|
191
|
+
const handlers = _handlers.get(event);
|
|
192
|
+
if (handlers) {
|
|
193
|
+
for (const fn_ of handlers)
|
|
194
|
+
fn_(msg);
|
|
195
|
+
}
|
|
196
|
+
if (event === "exit") {
|
|
197
|
+
process.exit(msg.exit_code);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
var _rl = createInterface({ input: process.stdin, terminal: false });
|
|
202
|
+
_rl.on("line", (line) => {
|
|
203
|
+
try {
|
|
204
|
+
_dispatch(JSON.parse(line));
|
|
205
|
+
} catch {}
|
|
206
|
+
});
|
|
207
|
+
_rl.on("close", () => process.exit(0));
|
|
208
|
+
|
|
209
|
+
// src/components/engine.ts
|
|
210
|
+
var Engine = {
|
|
211
|
+
on(event, handler) {
|
|
212
|
+
if (!_handlers.has(event))
|
|
213
|
+
_handlers.set(event, new Set);
|
|
214
|
+
_handlers.get(event).add(handler);
|
|
215
|
+
const msgType = _EVENT_SUBSCRIBE[event];
|
|
216
|
+
if (msgType)
|
|
217
|
+
_send({ type: "Subscribe", events: [msgType] });
|
|
218
|
+
},
|
|
219
|
+
log(level, message) {
|
|
220
|
+
_send({ type: "Log", level, message });
|
|
221
|
+
},
|
|
222
|
+
setTickRate(ticks_per_second) {
|
|
223
|
+
_send({ type: "SetTickRate", ticks_per_second });
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
// src/components/window.ts
|
|
227
|
+
var Window = {
|
|
228
|
+
setTitle(title) {
|
|
229
|
+
_send({ type: "SetWindowTitle", title });
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
// src/components/file.ts
|
|
233
|
+
var File = {
|
|
234
|
+
write(path, data) {
|
|
235
|
+
return new Promise((resolve, reject) => {
|
|
236
|
+
const request_id = nextReqId();
|
|
237
|
+
_fileCallbacks.set(request_id, { resolve: () => resolve(), reject });
|
|
238
|
+
_send({ type: "FileWrite", request_id, path, data_base64: Buffer.from(data, "utf8").toString("base64") });
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
read(path) {
|
|
242
|
+
return new Promise((resolve, reject) => {
|
|
243
|
+
const request_id = nextReqId();
|
|
244
|
+
_fileCallbacks.set(request_id, {
|
|
245
|
+
resolve: (b64) => resolve(Buffer.from(b64, "base64").toString("utf8")),
|
|
246
|
+
reject
|
|
247
|
+
});
|
|
248
|
+
_send({ type: "FileRead", request_id, path });
|
|
249
|
+
});
|
|
250
|
+
},
|
|
251
|
+
delete(path) {
|
|
252
|
+
return new Promise((resolve, reject) => {
|
|
253
|
+
const request_id = nextReqId();
|
|
254
|
+
_fileCallbacks.set(request_id, { resolve: () => resolve(), reject });
|
|
255
|
+
_send({ type: "FileDelete", request_id, path });
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
// src/components/ecs.ts
|
|
260
|
+
var BuiltInComponents;
|
|
261
|
+
((BuiltInComponents) => {
|
|
262
|
+
BuiltInComponents.TRANSFORM_ID = "core:transform";
|
|
263
|
+
BuiltInComponents.SPRITE_RENDERER_ID = "core:sprite_renderer";
|
|
264
|
+
|
|
265
|
+
class Transform {
|
|
266
|
+
id = BuiltInComponents.TRANSFORM_ID;
|
|
267
|
+
position;
|
|
268
|
+
rotation;
|
|
269
|
+
scale;
|
|
270
|
+
constructor(init = {}) {
|
|
271
|
+
this.position = init.position ?? [0, 0, 0];
|
|
272
|
+
this.rotation = init.rotation ?? [0, 0, 0, 1];
|
|
273
|
+
this.scale = init.scale ?? [1, 1, 1];
|
|
274
|
+
}
|
|
275
|
+
getX() {
|
|
276
|
+
return this.position[0];
|
|
277
|
+
}
|
|
278
|
+
setX(x) {
|
|
279
|
+
this.position[0] = x;
|
|
280
|
+
return this;
|
|
281
|
+
}
|
|
282
|
+
addX(x) {
|
|
283
|
+
this.position[0] += x;
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
getY() {
|
|
287
|
+
return this.position[1];
|
|
288
|
+
}
|
|
289
|
+
setY(y) {
|
|
290
|
+
this.position[1] = y;
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
addY(y) {
|
|
294
|
+
this.position[1] += y;
|
|
295
|
+
return this;
|
|
296
|
+
}
|
|
297
|
+
getZ() {
|
|
298
|
+
return this.position[2];
|
|
299
|
+
}
|
|
300
|
+
setZ(z) {
|
|
301
|
+
this.position[2] = z;
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
304
|
+
addZ(z) {
|
|
305
|
+
this.position[2] += z;
|
|
306
|
+
return this;
|
|
307
|
+
}
|
|
308
|
+
getPosition() {
|
|
309
|
+
return [this.position[0], this.position[1], this.position[2]];
|
|
310
|
+
}
|
|
311
|
+
setPosition(x, y, z) {
|
|
312
|
+
this.position = [x, y, z];
|
|
313
|
+
return this;
|
|
314
|
+
}
|
|
315
|
+
getScaleX() {
|
|
316
|
+
return this.scale[0];
|
|
317
|
+
}
|
|
318
|
+
setScaleX(x) {
|
|
319
|
+
this.scale[0] = x;
|
|
320
|
+
return this;
|
|
321
|
+
}
|
|
322
|
+
getScaleY() {
|
|
323
|
+
return this.scale[1];
|
|
324
|
+
}
|
|
325
|
+
setScaleY(y) {
|
|
326
|
+
this.scale[1] = y;
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
getScaleZ() {
|
|
330
|
+
return this.scale[2];
|
|
331
|
+
}
|
|
332
|
+
setScaleZ(z) {
|
|
333
|
+
this.scale[2] = z;
|
|
334
|
+
return this;
|
|
335
|
+
}
|
|
336
|
+
getScale() {
|
|
337
|
+
return [this.scale[0], this.scale[1], this.scale[2]];
|
|
338
|
+
}
|
|
339
|
+
setScale(x, y, z) {
|
|
340
|
+
this.scale = [x, y, z];
|
|
341
|
+
return this;
|
|
342
|
+
}
|
|
343
|
+
setScaleUniform(s) {
|
|
344
|
+
this.scale = [s, s, s];
|
|
345
|
+
return this;
|
|
346
|
+
}
|
|
347
|
+
distance(other) {
|
|
348
|
+
const dx = this.position[0] - other.position[0];
|
|
349
|
+
const dy = this.position[1] - other.position[1];
|
|
350
|
+
const dz = this.position[2] - other.position[2];
|
|
351
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
352
|
+
}
|
|
353
|
+
getRotation() {
|
|
354
|
+
return [this.rotation[0], this.rotation[1], this.rotation[2], this.rotation[3]];
|
|
355
|
+
}
|
|
356
|
+
setRotation(x, y, z, w) {
|
|
357
|
+
this.rotation = [x, y, z, w];
|
|
358
|
+
return this;
|
|
359
|
+
}
|
|
360
|
+
getEulerRadians() {
|
|
361
|
+
const [qx, qy, qz, qw] = this.rotation;
|
|
362
|
+
const rx = Math.atan2(2 * (qw * qx + qy * qz), 1 - 2 * (qx * qx + qy * qy));
|
|
363
|
+
const sinPitch = Math.max(-1, Math.min(1, 2 * (qw * qy - qz * qx)));
|
|
364
|
+
const ry = Math.asin(sinPitch);
|
|
365
|
+
const rz = Math.atan2(2 * (qw * qz + qx * qy), 1 - 2 * (qy * qy + qz * qz));
|
|
366
|
+
return [rx, ry, rz];
|
|
367
|
+
}
|
|
368
|
+
setEulerRadians(rx, ry, rz) {
|
|
369
|
+
const cx = Math.cos(rx / 2), sx = Math.sin(rx / 2);
|
|
370
|
+
const cy = Math.cos(ry / 2), sy = Math.sin(ry / 2);
|
|
371
|
+
const cz = Math.cos(rz / 2), sz = Math.sin(rz / 2);
|
|
372
|
+
this.rotation = [
|
|
373
|
+
sx * cy * cz - cx * sy * sz,
|
|
374
|
+
cx * sy * cz + sx * cy * sz,
|
|
375
|
+
cx * cy * sz - sx * sy * cz,
|
|
376
|
+
cx * cy * cz + sx * sy * sz
|
|
377
|
+
];
|
|
378
|
+
return this;
|
|
379
|
+
}
|
|
380
|
+
getEulerDegrees() {
|
|
381
|
+
const r = this.getEulerRadians();
|
|
382
|
+
return [r[0] * 180 / Math.PI, r[1] * 180 / Math.PI, r[2] * 180 / Math.PI];
|
|
383
|
+
}
|
|
384
|
+
setEulerDegrees(x, y, z) {
|
|
385
|
+
return this.setEulerRadians(x * Math.PI / 180, y * Math.PI / 180, z * Math.PI / 180);
|
|
386
|
+
}
|
|
387
|
+
rotateX(degrees) {
|
|
388
|
+
const r = degrees * Math.PI / 180;
|
|
389
|
+
const s = Math.sin(r / 2), c = Math.cos(r / 2);
|
|
390
|
+
return this._leftMultiply(s, 0, 0, c);
|
|
391
|
+
}
|
|
392
|
+
rotateY(degrees) {
|
|
393
|
+
const r = degrees * Math.PI / 180;
|
|
394
|
+
const s = Math.sin(r / 2), c = Math.cos(r / 2);
|
|
395
|
+
return this._leftMultiply(0, s, 0, c);
|
|
396
|
+
}
|
|
397
|
+
rotateZ(degrees) {
|
|
398
|
+
const r = degrees * Math.PI / 180;
|
|
399
|
+
const s = Math.sin(r / 2), c = Math.cos(r / 2);
|
|
400
|
+
return this._leftMultiply(0, 0, s, c);
|
|
401
|
+
}
|
|
402
|
+
_leftMultiply(ax, ay, az, aw) {
|
|
403
|
+
const [bx, by, bz, bw] = this.rotation;
|
|
404
|
+
this.rotation = [
|
|
405
|
+
aw * bx + ax * bw + ay * bz - az * by,
|
|
406
|
+
aw * by - ax * bz + ay * bw + az * bx,
|
|
407
|
+
aw * bz + ax * by - ay * bx + az * bw,
|
|
408
|
+
aw * bw - ax * bx - ay * by - az * bz
|
|
409
|
+
];
|
|
410
|
+
return this;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
BuiltInComponents.Transform = Transform;
|
|
414
|
+
|
|
415
|
+
class SpriteRenderer {
|
|
416
|
+
id = BuiltInComponents.SPRITE_RENDERER_ID;
|
|
417
|
+
texture;
|
|
418
|
+
z_index;
|
|
419
|
+
constructor(init = {}) {
|
|
420
|
+
this.texture = init.texture ?? "";
|
|
421
|
+
this.z_index = init.z_index ?? 0;
|
|
422
|
+
}
|
|
423
|
+
getTexture() {
|
|
424
|
+
return this.texture;
|
|
425
|
+
}
|
|
426
|
+
setTexture(texture) {
|
|
427
|
+
this.texture = texture;
|
|
428
|
+
return this;
|
|
429
|
+
}
|
|
430
|
+
getZIndex() {
|
|
431
|
+
return this.z_index;
|
|
432
|
+
}
|
|
433
|
+
setZIndex(z) {
|
|
434
|
+
this.z_index = z;
|
|
435
|
+
return this;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
BuiltInComponents.SpriteRenderer = SpriteRenderer;
|
|
439
|
+
})(BuiltInComponents ||= {});
|
|
440
|
+
var _componentHydrators = {
|
|
441
|
+
"core:transform": (data) => new BuiltInComponents.Transform(data),
|
|
442
|
+
"core:sprite_renderer": (data) => new BuiltInComponents.SpriteRenderer(data)
|
|
443
|
+
};
|
|
444
|
+
function _setComponentImpl(entity_id, component_type, data) {
|
|
445
|
+
const { id: _id, ...rest } = data;
|
|
446
|
+
_send({ type: "ComponentSet", entity_id, component_type, data: rest });
|
|
447
|
+
}
|
|
448
|
+
function _getComponentImpl(entity_id, component_type) {
|
|
449
|
+
return new Promise((resolve, reject) => {
|
|
450
|
+
const request_id = nextReqId();
|
|
451
|
+
_componentGetCallbacks.set(request_id, { resolve, reject });
|
|
452
|
+
_send({ type: "ComponentGet", request_id, entity_id, component_type });
|
|
453
|
+
}).then((data) => {
|
|
454
|
+
if (data === null)
|
|
455
|
+
return null;
|
|
456
|
+
const hydrator = _componentHydrators[component_type];
|
|
457
|
+
return hydrator ? hydrator(data) : data;
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
class Entity {
|
|
462
|
+
id;
|
|
463
|
+
constructor(id) {
|
|
464
|
+
this.id = id;
|
|
465
|
+
}
|
|
466
|
+
destroy() {
|
|
467
|
+
_send({ type: "EntityDestroy", entity_id: this.id });
|
|
468
|
+
}
|
|
469
|
+
setComponent(component_type, data) {
|
|
470
|
+
_setComponentImpl(this.id, component_type, data);
|
|
471
|
+
}
|
|
472
|
+
removeComponent(component_type) {
|
|
473
|
+
_send({ type: "ComponentRemove", entity_id: this.id, component_type });
|
|
474
|
+
}
|
|
475
|
+
getComponent(component_type) {
|
|
476
|
+
return _getComponentImpl(this.id, component_type);
|
|
477
|
+
}
|
|
478
|
+
async move(position) {
|
|
479
|
+
const existing = await this.getComponent("core:transform");
|
|
480
|
+
this.setComponent("core:transform", {
|
|
481
|
+
position,
|
|
482
|
+
rotation: existing?.rotation ?? [0, 0, 0, 1],
|
|
483
|
+
scale: existing?.scale ?? [1, 1, 1]
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
var Scene = {
|
|
488
|
+
createEntity() {
|
|
489
|
+
return new Promise((resolve, reject) => {
|
|
490
|
+
const request_id = nextReqId();
|
|
491
|
+
_entityCallbacks.set(request_id, { resolve: (id) => resolve(new Entity(id)), reject });
|
|
492
|
+
_send({ type: "EntityCreate", request_id });
|
|
493
|
+
});
|
|
494
|
+
},
|
|
495
|
+
destroyEntity(entity_id) {
|
|
496
|
+
_send({ type: "EntityDestroy", entity_id });
|
|
497
|
+
},
|
|
498
|
+
listEntities() {
|
|
499
|
+
return new Promise((resolve, reject) => {
|
|
500
|
+
const request_id = nextReqId();
|
|
501
|
+
_entityListCallbacks.set(request_id, { resolve: (ids) => resolve(ids.map((id) => new Entity(id))), reject });
|
|
502
|
+
_send({ type: "EntityListRequest", request_id });
|
|
503
|
+
});
|
|
504
|
+
},
|
|
505
|
+
setComponent: _setComponentImpl,
|
|
506
|
+
removeComponent(entity_id, component_type) {
|
|
507
|
+
_send({ type: "ComponentRemove", entity_id, component_type });
|
|
508
|
+
},
|
|
509
|
+
getComponent: _getComponentImpl,
|
|
510
|
+
query(component_types) {
|
|
511
|
+
return new Promise((resolve, reject) => {
|
|
512
|
+
const request_id = nextReqId();
|
|
513
|
+
_componentQueryCallbacks.set(request_id, {
|
|
514
|
+
resolve: (results) => resolve(results.map((r) => ({
|
|
515
|
+
entity: new Entity(r.entity_id),
|
|
516
|
+
components: Object.fromEntries(Object.entries(r.components).map(([k, v]) => {
|
|
517
|
+
const hydrator = _componentHydrators[k];
|
|
518
|
+
return [k, hydrator ? hydrator(v) : v];
|
|
519
|
+
}))
|
|
520
|
+
}))),
|
|
521
|
+
reject
|
|
522
|
+
});
|
|
523
|
+
_send({ type: "ComponentQuery", request_id, component_types });
|
|
524
|
+
});
|
|
525
|
+
},
|
|
526
|
+
async spawnSprite(texture, position, scale = [1, 1, 1]) {
|
|
527
|
+
const entity = await Scene.createEntity();
|
|
528
|
+
entity.setComponent("core:transform", { position, rotation: [0, 0, 0, 1], scale });
|
|
529
|
+
entity.setComponent("core:sprite_renderer", { texture, z_index: 0 });
|
|
530
|
+
return entity;
|
|
531
|
+
},
|
|
532
|
+
async moveEntity(entity_id, position) {
|
|
533
|
+
const existing = await Scene.getComponent(entity_id, "core:transform");
|
|
534
|
+
Scene.setComponent(entity_id, "core:transform", {
|
|
535
|
+
position,
|
|
536
|
+
rotation: existing?.rotation ?? [0, 0, 0, 1],
|
|
537
|
+
scale: existing?.scale ?? [1, 1, 1]
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
// src/components/mods.ts
|
|
542
|
+
var Mods = {
|
|
543
|
+
list() {
|
|
544
|
+
return new Promise((resolve, reject) => {
|
|
545
|
+
const request_id = nextReqId();
|
|
546
|
+
_modListCallbacks.set(request_id, { resolve, reject });
|
|
547
|
+
_send({ type: "ModListRequest", request_id });
|
|
548
|
+
});
|
|
549
|
+
},
|
|
550
|
+
get(id) {
|
|
551
|
+
return new Promise((resolve, reject) => {
|
|
552
|
+
const request_id = nextReqId();
|
|
553
|
+
_modGetCallbacks.set(request_id, { resolve, reject });
|
|
554
|
+
_send({ type: "ModGetRequest", request_id, mod_id: id });
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
var Message = {
|
|
559
|
+
sendAndForget(id, message) {
|
|
560
|
+
_send({ type: "ModMessageSend", target_mod_id: id, request_id: null, payload: message });
|
|
561
|
+
},
|
|
562
|
+
send(id, message, timeout) {
|
|
563
|
+
return new Promise((resolve, reject) => {
|
|
564
|
+
const request_id = nextReqId();
|
|
565
|
+
const timer = setTimeout(() => {
|
|
566
|
+
_msgCallbacks.delete(request_id);
|
|
567
|
+
reject(new Error(`Message to '${id}' timed out after ${timeout}ms`));
|
|
568
|
+
}, timeout);
|
|
569
|
+
_msgCallbacks.set(request_id, {
|
|
570
|
+
resolve: (v) => {
|
|
571
|
+
clearTimeout(timer);
|
|
572
|
+
resolve(v);
|
|
573
|
+
},
|
|
574
|
+
reject
|
|
575
|
+
});
|
|
576
|
+
_send({ type: "ModMessageSend", target_mod_id: id, request_id, payload: message });
|
|
577
|
+
});
|
|
578
|
+
},
|
|
579
|
+
registerMessageHandler(handler) {
|
|
580
|
+
Engine.on("mod_message", (payload) => {
|
|
581
|
+
const result = handler(payload);
|
|
582
|
+
if (payload.request_id !== undefined && result !== null) {
|
|
583
|
+
_send({ type: "ModMessageReply", request_id: payload.request_id, payload: result });
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
export {
|
|
589
|
+
Window,
|
|
590
|
+
Scene,
|
|
591
|
+
Mods,
|
|
592
|
+
Message,
|
|
593
|
+
File,
|
|
594
|
+
Entity,
|
|
595
|
+
Engine,
|
|
596
|
+
Console,
|
|
597
|
+
BuiltInComponents
|
|
598
|
+
};
|
|
599
|
+
// With love from the Whatever team <3
|
|
600
|
+
// https://github.com/MesterMan03/Whatever
|
package/package.json
CHANGED
|
@@ -3,20 +3,21 @@
|
|
|
3
3
|
"author": "Mester",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "TypeScript scripting API for Whatever Engine mods",
|
|
6
|
-
"version": "0.
|
|
7
|
-
"module": "./index.
|
|
8
|
-
"types": "./index.d.ts",
|
|
6
|
+
"version": "0.2.0",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
|
-
".":
|
|
11
|
-
"bun": "./index.ts",
|
|
12
|
-
"types": "./index.d.ts"
|
|
13
|
-
}
|
|
10
|
+
".": "./dist/index.js"
|
|
14
11
|
},
|
|
15
12
|
"scripts": {
|
|
16
|
-
"build:
|
|
13
|
+
"build:bundle": "bun build src/index.ts --outfile dist/index.js --external=node --target=node --footer=\"// With love from the Whatever team <3\n// https://github.com/MesterMan03/Whatever\"",
|
|
14
|
+
"build:types": "dts-bundle-generator --project tsconfig.dts.json --out-file dist/index.d.ts src/index.ts",
|
|
15
|
+
"build": "bun run build:bundle && bun run build:types",
|
|
16
|
+
"prepublishOnly": "bun run build"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/node": "^22",
|
|
20
|
+
"dts-bundle-generator": "^9.5.1",
|
|
20
21
|
"typescript": "^5"
|
|
21
22
|
},
|
|
22
23
|
"publishConfig": {
|
|
@@ -26,5 +27,8 @@
|
|
|
26
27
|
"type": "git",
|
|
27
28
|
"url": "git+https://github.com/MesterMan03/Whatever.git",
|
|
28
29
|
"directory": "runtime"
|
|
29
|
-
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
]
|
|
30
34
|
}
|