@adatechnology/game-shapes 0.0.0-stage → 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/dist/index.js ADDED
@@ -0,0 +1,276 @@
1
+ import {
2
+ SHAPE_SCHEMA,
3
+ assertValidShape,
4
+ box,
5
+ buildPrimitive,
6
+ byteSizeOf,
7
+ canonicalJson,
8
+ circle,
9
+ clearTemplateCache,
10
+ cloneBuffers,
11
+ clonePrimitive,
12
+ colorChannels,
13
+ colorHex,
14
+ compose,
15
+ computeVertexNormals,
16
+ cone,
17
+ cylinder,
18
+ defaultShapeGenerators,
19
+ difference,
20
+ extrude,
21
+ generate,
22
+ generatorsOver,
23
+ getGenerator,
24
+ hash64,
25
+ hashValue,
26
+ headingMatrix,
27
+ identity4,
28
+ installShapeWorker,
29
+ isAffine,
30
+ isPrimitiveNode,
31
+ keyOptions,
32
+ lathe,
33
+ listGenerators,
34
+ matrixOf,
35
+ mergeTransformed,
36
+ mulberry32,
37
+ multiply,
38
+ normalMatrix,
39
+ plane,
40
+ primitiveParameters,
41
+ quaternionFromEuler,
42
+ registerGenerator,
43
+ ring,
44
+ setTemplateCacheSize,
45
+ shapeKey,
46
+ sphere,
47
+ srgbToLinear,
48
+ streamFor,
49
+ templateCacheStats,
50
+ torus,
51
+ transferablesOf,
52
+ transformPoint,
53
+ unregisterGenerator,
54
+ validateShape
55
+ } from "./chunk-IFXQIDSA.js";
56
+
57
+ // src/instance.ts
58
+ import { applyPatches, mergeById, removeIds } from "@adatechnology/game-contracts";
59
+ function createShapes(options = {}) {
60
+ const entryOf = ([id, generator]) => ({ id, generator });
61
+ const entries = mergeById([], (options.packs ?? []).flatMap((pack) => Object.entries(pack).map(entryOf)));
62
+ const patches = {};
63
+ for (const [id, generator] of Object.entries(options.patch ?? {})) patches[id] = { generator };
64
+ applyPatches(entries, patches);
65
+ removeIds(entries, options.remove);
66
+ const generators = generatorsOver(new Map([...entries].map(([id, entry]) => [id, entry.generator])));
67
+ return { ...generators, generate: (schema, generateOptions = {}) => generate(schema, { ...generateOptions, generators: { ...generators.record(), ...generateOptions.generators }, isolatedGenerators: true }) };
68
+ }
69
+
70
+ // src/cache.ts
71
+ function createShapeCache(options = {}) {
72
+ const maxEntries = options.maxEntries ?? 256;
73
+ const maxBytes = options.maxBytes ?? 64 * 1024 * 1024;
74
+ const entries = /* @__PURE__ */ new Map();
75
+ let bytes = 0;
76
+ let hits = 0;
77
+ let misses = 0;
78
+ let evictions = 0;
79
+ const drop = (key) => {
80
+ const entry = entries.get(key);
81
+ if (!entry) return false;
82
+ entries.delete(key);
83
+ bytes -= entry.bytes;
84
+ return true;
85
+ };
86
+ return {
87
+ get(key) {
88
+ const entry = entries.get(key);
89
+ if (!entry) {
90
+ misses++;
91
+ return void 0;
92
+ }
93
+ hits++;
94
+ entries.delete(key);
95
+ entries.set(key, entry);
96
+ return entry.buffers;
97
+ },
98
+ set(key, buffers) {
99
+ drop(key);
100
+ const size = byteSizeOf(buffers);
101
+ if (size > maxBytes || maxEntries <= 0) return;
102
+ entries.set(key, { buffers, bytes: size });
103
+ bytes += size;
104
+ for (const oldest of entries.keys()) {
105
+ if (entries.size <= maxEntries && bytes <= maxBytes) break;
106
+ drop(oldest);
107
+ evictions++;
108
+ }
109
+ },
110
+ has: (key) => entries.has(key),
111
+ delete: drop,
112
+ clear() {
113
+ entries.clear();
114
+ bytes = 0;
115
+ },
116
+ stats: () => ({ entries: entries.size, bytes, hits, misses, evictions })
117
+ };
118
+ }
119
+
120
+ // src/pool.ts
121
+ var isRequest = (value) => value.schema !== void 0 && value.root === void 0;
122
+ function createShapePool(options = {}) {
123
+ const size = options.spawn ? Math.max(0, options.size ?? 0) : 0;
124
+ const cache = options.cache;
125
+ const slots = [];
126
+ const inFlight = /* @__PURE__ */ new Map();
127
+ let nextId = 1;
128
+ let jobs = 0;
129
+ let cacheHits = 0;
130
+ let shared = 0;
131
+ let inThread = 0;
132
+ let terminated = false;
133
+ const failAll = (slot, error) => {
134
+ for (const job of slot.pending.values()) job.reject(error);
135
+ slot.pending.clear();
136
+ };
137
+ const spawnSlot = () => {
138
+ const slot = { worker: options.spawn(), pending: /* @__PURE__ */ new Map() };
139
+ slot.worker.onmessage = (event) => {
140
+ const reply = event.data;
141
+ const job = slot.pending.get(reply.id);
142
+ if (!job) return;
143
+ slot.pending.delete(reply.id);
144
+ if (reply.ok) job.resolve(reply.buffers);
145
+ else job.reject(new Error(reply.error));
146
+ };
147
+ slot.worker.onerror = (event) => {
148
+ failAll(slot, new Error(`game-shapes worker failed: ${event?.message ?? String(event)}`));
149
+ slot.worker.terminate();
150
+ const index = slots.indexOf(slot);
151
+ if (index >= 0 && !terminated) slots[index] = spawnSlot();
152
+ };
153
+ return slot;
154
+ };
155
+ for (let i = 0; i < size; i++) slots.push(spawnSlot());
156
+ const run = (schema, generateOptions) => {
157
+ if (slots.length === 0 || generateOptions.generators || options.isolatedGenerators) {
158
+ inThread++;
159
+ try {
160
+ const generators = { ...options.generators ?? {}, ...generateOptions.generators ?? {} };
161
+ return Promise.resolve(generate(schema, { ...generateOptions, ...Object.keys(generators).length ? { generators } : {}, ...options.isolatedGenerators ? { isolatedGenerators: true } : {} }));
162
+ } catch (error) {
163
+ return Promise.reject(error);
164
+ }
165
+ }
166
+ let slot = slots[0];
167
+ for (const s of slots) if (s.pending.size < slot.pending.size) slot = s;
168
+ const id = nextId++;
169
+ const job = { id, schema, options: generateOptions };
170
+ return new Promise((resolve, reject) => {
171
+ slot.pending.set(id, { resolve, reject });
172
+ slot.worker.postMessage(job);
173
+ });
174
+ };
175
+ const pool = {
176
+ generate(schema, generateOptions = {}) {
177
+ if (terminated) return Promise.reject(new Error("createShapePool: the pool was terminated"));
178
+ jobs++;
179
+ const key = shapeKey(schema, generateOptions);
180
+ const hit = cache?.get(key);
181
+ if (hit) {
182
+ cacheHits++;
183
+ return Promise.resolve(hit);
184
+ }
185
+ const flying = inFlight.get(key);
186
+ if (flying) {
187
+ shared++;
188
+ return flying;
189
+ }
190
+ const promise = run(schema, generateOptions).then(
191
+ (buffers) => {
192
+ inFlight.delete(key);
193
+ cache?.set(key, buffers);
194
+ return buffers;
195
+ },
196
+ (error) => {
197
+ inFlight.delete(key);
198
+ throw error;
199
+ }
200
+ );
201
+ inFlight.set(key, promise);
202
+ return promise;
203
+ },
204
+ generateMany(list) {
205
+ return Promise.all(list.map((item) => isRequest(item) ? pool.generate(item.schema, item.options) : pool.generate(item)));
206
+ },
207
+ stats: () => ({ workers: slots.length, jobs, cacheHits, shared, inThread, busy: slots.reduce((n, s) => n + s.pending.size, 0) }),
208
+ terminate() {
209
+ terminated = true;
210
+ for (const slot of slots) {
211
+ failAll(slot, new Error("createShapePool: the pool was terminated"));
212
+ slot.worker.terminate();
213
+ }
214
+ slots.length = 0;
215
+ }
216
+ };
217
+ return pool;
218
+ }
219
+ export {
220
+ SHAPE_SCHEMA,
221
+ assertValidShape,
222
+ box,
223
+ buildPrimitive,
224
+ byteSizeOf,
225
+ canonicalJson,
226
+ circle,
227
+ clearTemplateCache,
228
+ cloneBuffers,
229
+ clonePrimitive,
230
+ colorChannels,
231
+ colorHex,
232
+ compose,
233
+ computeVertexNormals,
234
+ cone,
235
+ createShapeCache,
236
+ createShapePool,
237
+ createShapes,
238
+ cylinder,
239
+ defaultShapeGenerators,
240
+ difference,
241
+ extrude,
242
+ generate,
243
+ getGenerator,
244
+ hash64,
245
+ hashValue,
246
+ headingMatrix,
247
+ identity4,
248
+ installShapeWorker,
249
+ isAffine,
250
+ isPrimitiveNode,
251
+ keyOptions,
252
+ lathe,
253
+ listGenerators,
254
+ matrixOf,
255
+ mergeTransformed,
256
+ mulberry32,
257
+ multiply,
258
+ normalMatrix,
259
+ plane,
260
+ primitiveParameters,
261
+ quaternionFromEuler,
262
+ registerGenerator,
263
+ ring,
264
+ setTemplateCacheSize,
265
+ shapeKey,
266
+ sphere,
267
+ srgbToLinear,
268
+ streamFor,
269
+ templateCacheStats,
270
+ torus,
271
+ transferablesOf,
272
+ transformPoint,
273
+ unregisterGenerator,
274
+ validateShape
275
+ };
276
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/instance.ts","../src/cache.ts","../src/pool.ts"],"sourcesContent":["import { applyPatches, mergeById, removeIds } from '@adatechnology/game-contracts'\n\nimport { generate } from './generate'\nimport { generatorsOver } from './registry'\nimport type { ShapeGenerators } from './registry'\nimport type { GenerateOptions, ShapeBuffers, ShapeGenerator, ShapeSchema } from './types'\n\nexport interface ShapesOptions {\n /** Generators by name, added to the set; later packs replace earlier ones with the same name. */\n readonly packs?: readonly Readonly<Record<string, ShapeGenerator>>[]\n /** A generator replaced by name (a function is replaced as a whole). */\n readonly patch?: Readonly<Record<string, ShapeGenerator>>\n /** Names taken out. */\n readonly remove?: readonly string[]\n}\n\nexport interface Shapes extends ShapeGenerators {\n /** `generate` that looks custom nodes up in this set only (a name only the global registry has throws). */\n generate(schema: ShapeSchema, options?: Omit<GenerateOptions, 'isolatedGenerators'>): ShapeBuffers\n}\n\ntype Entry = { readonly id: string; readonly generator: ShapeGenerator }\n\n/** A set of shape generators of its own. Nothing is shared with any other set or with the global registry. */\nexport function createShapes(options: ShapesOptions = {}): Shapes {\n const entryOf = ([id, generator]: [string, ShapeGenerator]): Entry => ({ id, generator })\n const entries = mergeById<Entry>([], (options.packs ?? []).flatMap((pack) => Object.entries(pack).map(entryOf)))\n const patches: Record<string, Partial<Entry>> = {}\n for (const [id, generator] of Object.entries(options.patch ?? {})) patches[id] = { generator }\n applyPatches(entries, patches)\n removeIds(entries, options.remove)\n const generators = generatorsOver(new Map([...entries].map(([id, entry]) => [id, entry.generator])))\n return { ...generators, generate: (schema, generateOptions = {}) => generate(schema, { ...generateOptions, generators: { ...generators.record(), ...generateOptions.generators }, isolatedGenerators: true }) }\n}\n","import { byteSizeOf } from './merge'\nimport type { ShapeBuffers } from './types'\n\nexport interface ShapeCacheOptions {\n /** Most results kept (default 256). */\n readonly maxEntries?: number\n /** Most bytes of arrays kept (default 64 MiB). A result larger than this alone is not kept. */\n readonly maxBytes?: number\n}\n\nexport interface ShapeCacheStats {\n readonly entries: number\n readonly bytes: number\n readonly hits: number\n readonly misses: number\n readonly evictions: number\n}\n\n/** An LRU of results by `shapeKey`. What it returns is shared: read-only (copy with `cloneBuffers` before deforming). */\nexport interface ShapeCache {\n get(key: string): ShapeBuffers | undefined\n set(key: string, buffers: ShapeBuffers): void\n has(key: string): boolean\n delete(key: string): boolean\n clear(): void\n stats(): ShapeCacheStats\n}\n\n/** An LRU of `ShapeBuffers` by key, bounded by entries and by bytes of the arrays. Pure memoisation: a hit gives the bytes a miss would. */\nexport function createShapeCache(options: ShapeCacheOptions = {}): ShapeCache {\n const maxEntries = options.maxEntries ?? 256\n const maxBytes = options.maxBytes ?? 64 * 1024 * 1024\n const entries = new Map<string, { buffers: ShapeBuffers; bytes: number }>()\n let bytes = 0\n let hits = 0\n let misses = 0\n let evictions = 0\n const drop = (key: string): boolean => {\n const entry = entries.get(key)\n if (!entry) return false\n entries.delete(key)\n bytes -= entry.bytes\n return true\n }\n return {\n get(key) {\n const entry = entries.get(key)\n if (!entry) {\n misses++\n return undefined\n }\n hits++\n // most recently used goes last\n entries.delete(key)\n entries.set(key, entry)\n return entry.buffers\n },\n set(key, buffers) {\n drop(key)\n const size = byteSizeOf(buffers)\n if (size > maxBytes || maxEntries <= 0) return\n entries.set(key, { buffers, bytes: size })\n bytes += size\n for (const oldest of entries.keys()) {\n if (entries.size <= maxEntries && bytes <= maxBytes) break\n drop(oldest)\n evictions++\n }\n },\n has: (key) => entries.has(key),\n delete: drop,\n clear() {\n entries.clear()\n bytes = 0\n },\n stats: () => ({ entries: entries.size, bytes, hits, misses, evictions }),\n }\n}\n","import type { ShapeCache } from './cache'\nimport { generate, shapeKey } from './generate'\nimport type { GenerateOptions, ShapeBuffers, ShapeGenerator, ShapeSchema } from './types'\nimport type { ShapeJob, ShapeReply } from './worker'\n\n/** Anything with `postMessage` / `onmessage` / `terminate`: a browser `Worker`, a `worker_threads` wrapper, an in-thread fake. */\nexport interface WorkerLike {\n onmessage: ((event: { data: unknown }) => void) | null\n onerror?: ((event: unknown) => void) | null\n postMessage(message: unknown, transfer?: ArrayBuffer[]): void\n terminate(): unknown\n}\n\nexport interface ShapePoolOptions {\n /** Workers (default 0: generate in the calling thread). */\n readonly size?: number\n /** Makes one worker that runs `installShapeWorker`. Without it the pool generates in the calling thread. */\n readonly spawn?: () => WorkerLike\n /** Results by `shapeKey`: a hit resolves at once and never reaches a worker. */\n readonly cache?: ShapeCache\n /** Generators of the `custom` nodes for the jobs made in the calling thread (the workers register their own). */\n readonly generators?: Readonly<Record<string, ShapeGenerator>>\n /** Look custom nodes up in `generators` only (for example `shapes.record()` of `createShapes`), never in the global registry; the jobs then run in the calling thread, since a worker cannot receive functions. */\n readonly isolatedGenerators?: boolean\n}\n\nexport interface ShapeRequest {\n readonly schema: ShapeSchema\n readonly options?: GenerateOptions\n}\n\nexport interface ShapePoolStats {\n readonly workers: number\n readonly jobs: number\n readonly cacheHits: number\n readonly shared: number\n readonly inThread: number\n readonly busy: number\n}\n\nexport interface ShapePool {\n /** `generate(schema, options)` off the main thread. Same key, same promise while in flight; the result is shared (read-only). */\n generate(schema: ShapeSchema, options?: GenerateOptions): Promise<ShapeBuffers>\n /** A list spread over the workers, resolved in input order. */\n generateMany(list: readonly (ShapeSchema | ShapeRequest)[]): Promise<ShapeBuffers[]>\n stats(): ShapePoolStats\n /** Stops the workers; pending jobs reject. */\n terminate(): void\n}\n\ninterface Slot {\n worker: WorkerLike\n pending: Map<number, { resolve: (b: ShapeBuffers) => void; reject: (e: Error) => void }>\n}\n\nconst isRequest = (value: ShapeSchema | ShapeRequest): value is ShapeRequest => (value as ShapeRequest).schema !== undefined && (value as ShapeSchema).root === undefined\n\n/**\n * A pool of shape workers. The schema is cheap (plain data) and is built on the main thread; the buffers are generated in a worker and\n * transferred back. With `size: 0` or no `spawn` it generates in the calling thread, with the same cache and in-flight sharing.\n */\nexport function createShapePool(options: ShapePoolOptions = {}): ShapePool {\n const size = options.spawn ? Math.max(0, options.size ?? 0) : 0\n const cache = options.cache\n const slots: Slot[] = []\n const inFlight = new Map<string, Promise<ShapeBuffers>>()\n let nextId = 1\n let jobs = 0\n let cacheHits = 0\n let shared = 0\n let inThread = 0\n let terminated = false\n\n const failAll = (slot: Slot, error: Error): void => {\n for (const job of slot.pending.values()) job.reject(error)\n slot.pending.clear()\n }\n const spawnSlot = (): Slot => {\n const slot: Slot = { worker: (options.spawn as () => WorkerLike)(), pending: new Map() }\n slot.worker.onmessage = (event) => {\n const reply = event.data as ShapeReply\n const job = slot.pending.get(reply.id)\n if (!job) return\n slot.pending.delete(reply.id)\n if (reply.ok) job.resolve(reply.buffers)\n else job.reject(new Error(reply.error))\n }\n slot.worker.onerror = (event) => {\n // a worker that crashed takes its jobs with it; a fresh one takes its place\n failAll(slot, new Error(`game-shapes worker failed: ${(event as { message?: string })?.message ?? String(event)}`))\n slot.worker.terminate()\n const index = slots.indexOf(slot)\n if (index >= 0 && !terminated) slots[index] = spawnSlot()\n }\n return slot\n }\n for (let i = 0; i < size; i++) slots.push(spawnSlot())\n\n const run = (schema: ShapeSchema, generateOptions: GenerateOptions): Promise<ShapeBuffers> => {\n // custom generators passed per call are functions: they cannot reach a worker, so that job runs here\n if (slots.length === 0 || generateOptions.generators || options.isolatedGenerators) {\n inThread++\n try {\n const generators = { ...(options.generators ?? {}), ...(generateOptions.generators ?? {}) }\n return Promise.resolve(generate(schema, { ...generateOptions, ...(Object.keys(generators).length ? { generators } : {}), ...(options.isolatedGenerators ? { isolatedGenerators: true } : {}) }))\n } catch (error) {\n return Promise.reject(error)\n }\n }\n let slot = slots[0] as Slot\n for (const s of slots) if (s.pending.size < slot.pending.size) slot = s\n const id = nextId++\n const job: ShapeJob = { id, schema, options: generateOptions }\n return new Promise<ShapeBuffers>((resolve, reject) => {\n slot.pending.set(id, { resolve, reject })\n slot.worker.postMessage(job)\n })\n }\n\n const pool: ShapePool = {\n generate(schema, generateOptions = {}) {\n if (terminated) return Promise.reject(new Error('createShapePool: the pool was terminated'))\n jobs++\n const key = shapeKey(schema, generateOptions)\n const hit = cache?.get(key)\n if (hit) {\n cacheHits++\n return Promise.resolve(hit)\n }\n const flying = inFlight.get(key)\n if (flying) {\n shared++\n return flying\n }\n const promise = run(schema, generateOptions).then(\n (buffers) => {\n inFlight.delete(key)\n cache?.set(key, buffers)\n return buffers\n },\n (error: unknown) => {\n inFlight.delete(key)\n throw error\n },\n )\n inFlight.set(key, promise)\n return promise\n },\n generateMany(list) {\n return Promise.all(list.map((item) => (isRequest(item) ? pool.generate(item.schema, item.options) : pool.generate(item))))\n },\n stats: () => ({ workers: slots.length, jobs, cacheHits, shared, inThread, busy: slots.reduce((n, s) => n + s.pending.size, 0) }),\n terminate() {\n terminated = true\n for (const slot of slots) {\n failAll(slot, new Error('createShapePool: the pool was terminated'))\n slot.worker.terminate()\n }\n slots.length = 0\n },\n }\n return pool\n}\n"],"mappings":"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","names":[]}