minecraft-renderer 0.1.107 → 0.1.109

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.
Files changed (95) hide show
  1. package/dist/lightOwnerWorker.js +9 -0
  2. package/dist/lightOwnerWorker.js.map +7 -0
  3. package/dist/mesher.js +1 -1
  4. package/dist/mesher.js.map +2 -2
  5. package/dist/mesherWasm.js +222 -222
  6. package/dist/minecraft-renderer.js +84 -84
  7. package/dist/minecraft-renderer.js.meta.json +1 -1
  8. package/dist/threeWorker.js +517 -517
  9. package/package.json +1 -1
  10. package/src/bundler/bundlePrepare.test.ts +25 -0
  11. package/src/bundler/bundlePrepare.ts +1 -1
  12. package/src/graphicsBackend/appViewer.ts +15 -0
  13. package/src/graphicsBackend/config.ts +5 -0
  14. package/src/graphicsBackend/rendererDefaultOptions.test.ts +51 -0
  15. package/src/graphicsBackend/rendererDefaultOptions.ts +13 -1
  16. package/src/graphicsBackend/rendererOptionsSync.ts +3 -3
  17. package/src/lib/blockEntityLightRegistry.ts +4 -0
  18. package/src/lib/worldrendererCommon.lightOwner.test.ts +916 -0
  19. package/src/lib/worldrendererCommon.removeColumn.test.ts +16 -0
  20. package/src/lib/worldrendererCommon.ts +329 -67
  21. package/src/lighting/cache/rendererLightCache.test.ts +158 -0
  22. package/src/lighting/cache/rendererLightCache.ts +248 -0
  23. package/src/lighting/coordinator/clientLightCoordinator.test.ts +102 -0
  24. package/src/lighting/coordinator/clientLightCoordinator.ts +574 -0
  25. package/src/lighting/debug/clientLightProbe.test.ts +24 -0
  26. package/src/lighting/debug/clientLightProbe.ts +20 -0
  27. package/src/lighting/debug/clientLightTrace.test.ts +271 -0
  28. package/src/lighting/debug/clientLightTrace.ts +335 -0
  29. package/src/lighting/entity/entityLightController.test.ts +216 -0
  30. package/src/lighting/entity/entityLightController.ts +322 -0
  31. package/src/lighting/owner/clientLightOwner.test.ts +467 -0
  32. package/src/lighting/owner/clientLightOwner.ts +523 -0
  33. package/src/lighting/owner/lightOwnerHost.test.ts +78 -0
  34. package/src/lighting/owner/lightOwnerHost.ts +202 -0
  35. package/src/lighting/owner/lightOwnerWorker.ts +154 -0
  36. package/src/lighting/owner/updateLight1171OwnerPath.test.ts +68 -0
  37. package/src/lighting/owner/updateLightToOwnerEvents.ts +49 -0
  38. package/src/lighting/tables/lightTables1171.generated.json +10 -0
  39. package/src/lighting/tables/lightTables1171.test.ts +168 -0
  40. package/src/lighting/tables/lightTables1171.ts +59 -0
  41. package/src/lighting/versioning/clientLightVersions.test.ts +241 -0
  42. package/src/lighting/versioning/clientLightVersions.ts +203 -0
  43. package/src/lighting/versioning/pendingSectionFlush.test.ts +214 -0
  44. package/src/lighting/versioning/pendingSectionFlush.ts +123 -0
  45. package/src/mesher-shared/lightNibblePack.ts +26 -0
  46. package/src/mesher-shared/mcDataWorkerShim.cjs +9 -7
  47. package/src/mesher-shared/modelsGeometryCommon.test.ts +6 -1
  48. package/src/mesher-shared/shared.ts +48 -1
  49. package/src/three/chunkMeshManager.ts +26 -0
  50. package/src/three/cloudCover.ts +22 -0
  51. package/src/three/cloudGeometry.ts +71 -0
  52. package/src/three/entities.ts +77 -11
  53. package/src/three/entity/EntityMesh.ts +1 -0
  54. package/src/three/entity/legWalkAnimation.test.ts +11 -2
  55. package/src/three/entity/legWalkAnimation.ts +1 -9
  56. package/src/three/globalBlockBuffer.ts +94 -2
  57. package/src/three/globalLegacyBuffer.ts +94 -2
  58. package/src/three/graphicsBackendBase.ts +2 -9
  59. package/src/three/modules/clouds.ts +98 -75
  60. package/src/three/tests/cloudGeometry.test.ts +87 -0
  61. package/src/three/tests/clouds.test.ts +65 -14
  62. package/src/three/tests/globalBlockBuffer.test.ts +98 -0
  63. package/src/three/tests/globalLegacyBuffer.test.ts +108 -0
  64. package/src/three/worldRendererThree.ts +75 -34
  65. package/src/wasm-mesher/bridge/render-from-wasm.ts +46 -1
  66. package/src/wasm-mesher/runtime-build/wasm_mesher.d.ts +31 -5
  67. package/src/wasm-mesher/runtime-build/wasm_mesher.js +180 -5
  68. package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
  69. package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm.d.ts +11 -0
  70. package/src/wasm-mesher/tests/mesherLightDependencies.test.ts +83 -0
  71. package/src/wasm-mesher/tests/mesherWasmColumnTickSelect.test.ts +39 -0
  72. package/src/wasm-mesher/tests/mesherWasmConversionCache.test.ts +30 -1
  73. package/src/wasm-mesher/tests/mesherWasmTickParseCache.test.ts +73 -0
  74. package/src/wasm-mesher/tests/mesherWasmTickSchedule.test.ts +51 -0
  75. package/src/wasm-mesher/tests/mesherWasmTopologyPostCache.test.ts +78 -0
  76. package/src/wasm-mesher/worker/clientLightDarkPublication.probe.test.ts +32 -0
  77. package/src/wasm-mesher/worker/mesherLightDependencies.ts +43 -0
  78. package/src/wasm-mesher/worker/mesherWasm.ownerLightSync.test.ts +198 -0
  79. package/src/wasm-mesher/worker/mesherWasm.ts +506 -96
  80. package/src/wasm-mesher/worker/mesherWasmChunkBuffer.ts +1 -0
  81. package/src/wasm-mesher/worker/mesherWasmColumnTickSelect.ts +47 -0
  82. package/src/wasm-mesher/worker/mesherWasmConversionCache.ts +16 -5
  83. package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +17 -1
  84. package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +10 -0
  85. package/src/wasm-mesher/worker/mesherWasmLightMerge.test.ts +208 -0
  86. package/src/wasm-mesher/worker/mesherWasmLightMerge.ts +228 -0
  87. package/src/wasm-mesher/worker/mesherWasmOwnerLight.test.ts +161 -0
  88. package/src/wasm-mesher/worker/mesherWasmOwnerLight.ts +112 -0
  89. package/src/wasm-mesher/worker/mesherWasmTickParseCache.ts +45 -0
  90. package/src/wasm-mesher/worker/mesherWasmTickSchedule.ts +44 -0
  91. package/src/wasm-mesher/worker/mesherWasmTopologyPostCache.ts +63 -0
  92. package/src/worldView/types.ts +1 -0
  93. package/src/worldView/worldView.geometryReload.test.ts +68 -0
  94. package/src/worldView/worldView.spiral.test.ts +1 -1
  95. package/src/worldView/worldView.ts +46 -1
@@ -2,6 +2,21 @@
2
2
  /* tslint:disable */
3
3
  /* eslint-disable */
4
4
 
5
+ export class JsLightEngine {
6
+ free(): void;
7
+ [Symbol.dispose](): void;
8
+ pushEvent(event: any): void;
9
+ getSkyLight(x: number, y: number, z: number): number;
10
+ getBlockLight(x: number, y: number, z: number): number;
11
+ setLightTables(emission: Uint8Array, opacity: Uint8Array): void;
12
+ setOcclusionTable(occupancy: Uint8Array): void;
13
+ setSkyLightEnabled(enabled: boolean): void;
14
+ pollCompletedPublication(): any;
15
+ step(budget_ms: number): boolean;
16
+ constructor(world_min_y: number, world_height: number);
17
+ readonly fallbackRelights: number;
18
+ }
19
+
5
20
  /**
6
21
  * Compute wireframe edge positions from a triangle mesh.
7
22
  *
@@ -210,11 +225,11 @@ export function parseMapChunkV18Plus(raw_packet: Uint8Array, num_sections: numbe
210
225
  * `raw_packet` includes the leading packet-id varint (we skip it).
211
226
  * `num_sections` should match the column the light is for (16 in 1.17).
212
227
  *
213
- * Returns `{ x, z, skyLight: Uint8Array(num_sections * 4096),
214
- * blockLight: Uint8Array(num_sections * 4096), bytesRead }`.
215
- * Layout matches the existing 1.18+ light arrays
216
- * (`x + z*16 + y_abs*256`); the JS-side worker reorders into per-section
217
- * stack via the same path used for 1.18+ raw map_chunk parsing.
228
+ * Returns `{ x, z, trustEdges, skyLight, blockLight, skyLightMask,
229
+ * emptySkyLightMask, blockLightMask, emptyBlockLightMask,
230
+ * skyBelow?, skyAbove?, blockBelow?, blockAbove?, bytesRead }`.
231
+ * World arrays are `num_sections * 4096` (`x + z*16 + y_abs*256`).
232
+ * Omitted sections are left 0 and are not authoritative — use the masks.
218
233
  */
219
234
  export function parseUpdateLightV17(raw_packet: Uint8Array, num_sections: number): any;
220
235
 
@@ -227,6 +242,7 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
227
242
 
228
243
  export interface InitOutput {
229
244
  readonly memory: WebAssembly.Memory;
245
+ readonly __wbg_jslightengine_free: (a: number, b: number) => void;
230
246
  readonly computeWireframeEdges: (a: number, b: number, c: number, d: number) => [number, number];
231
247
  readonly computeWireframeEdgesU16: (a: number, b: number, c: number, d: number) => [number, number];
232
248
  readonly generateGeometryFromDump118: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number, h1: number, i1: number, j1: number, k1: number) => any;
@@ -236,6 +252,16 @@ export interface InitOutput {
236
252
  readonly generateGeometryFromParsedV16V17Multi: (a: any, b: number, c: number, d: number, e: number, f: number, g: any, h: number, i: any, j: any, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number, h1: number) => any;
237
253
  readonly generate_geometry: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number) => any;
238
254
  readonly generate_geometry_multi: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number) => any;
255
+ readonly jslightengine_fallbackRelights: (a: number) => number;
256
+ readonly jslightengine_getBlockLight: (a: number, b: number, c: number, d: number) => number;
257
+ readonly jslightengine_getSkyLight: (a: number, b: number, c: number, d: number) => number;
258
+ readonly jslightengine_js_new: (a: number, b: number) => number;
259
+ readonly jslightengine_pollCompletedPublication: (a: number) => any;
260
+ readonly jslightengine_pushEvent: (a: number, b: any) => void;
261
+ readonly jslightengine_setLightTables: (a: number, b: number, c: number, d: number, e: number) => void;
262
+ readonly jslightengine_setOcclusionTable: (a: number, b: number, c: number) => void;
263
+ readonly jslightengine_setSkyLightEnabled: (a: number, b: number) => void;
264
+ readonly jslightengine_step: (a: number, b: number) => number;
239
265
  readonly parseChunkDump118: (a: number, b: number, c: number, d: number, e: number) => any;
240
266
  readonly parseChunkDump118FullColumn: (a: number, b: number, c: number, d: number, e: number) => any;
241
267
  readonly parseChunkDump118FullColumnAll: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number) => any;
@@ -86,6 +86,11 @@ function getArrayU16FromWasm0(ptr, len) {
86
86
  return getUint16ArrayMemory0().subarray(ptr / 2, ptr / 2 + len);
87
87
  }
88
88
 
89
+ function getArrayU32FromWasm0(ptr, len) {
90
+ ptr = ptr >>> 0;
91
+ return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
92
+ }
93
+
89
94
  function getArrayU8FromWasm0(ptr, len) {
90
95
  ptr = ptr >>> 0;
91
96
  return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
@@ -153,6 +158,10 @@ function handleError(f, args) {
153
158
  }
154
159
  }
155
160
 
161
+ function isLikeNone(x) {
162
+ return x === undefined || x === null;
163
+ }
164
+
156
165
  function passArray16ToWasm0(arg, malloc) {
157
166
  const ptr = malloc(arg.length * 2, 2) >>> 0;
158
167
  getUint16ArrayMemory0().set(arg, ptr / 2);
@@ -247,6 +256,107 @@ if (!('encodeInto' in cachedTextEncoder)) {
247
256
 
248
257
  let WASM_VECTOR_LEN = 0;
249
258
 
259
+ const JsLightEngineFinalization = (typeof FinalizationRegistry === 'undefined')
260
+ ? { register: () => {}, unregister: () => {} }
261
+ : new FinalizationRegistry(ptr => wasm.__wbg_jslightengine_free(ptr >>> 0, 1));
262
+
263
+ export class JsLightEngine {
264
+ __destroy_into_raw() {
265
+ const ptr = this.__wbg_ptr;
266
+ this.__wbg_ptr = 0;
267
+ JsLightEngineFinalization.unregister(this);
268
+ return ptr;
269
+ }
270
+ free() {
271
+ const ptr = this.__destroy_into_raw();
272
+ wasm.__wbg_jslightengine_free(ptr, 0);
273
+ }
274
+ /**
275
+ * @param {any} event
276
+ */
277
+ pushEvent(event) {
278
+ wasm.jslightengine_pushEvent(this.__wbg_ptr, event);
279
+ }
280
+ /**
281
+ * @param {number} x
282
+ * @param {number} y
283
+ * @param {number} z
284
+ * @returns {number}
285
+ */
286
+ getSkyLight(x, y, z) {
287
+ const ret = wasm.jslightengine_getSkyLight(this.__wbg_ptr, x, y, z);
288
+ return ret;
289
+ }
290
+ /**
291
+ * @param {number} x
292
+ * @param {number} y
293
+ * @param {number} z
294
+ * @returns {number}
295
+ */
296
+ getBlockLight(x, y, z) {
297
+ const ret = wasm.jslightengine_getBlockLight(this.__wbg_ptr, x, y, z);
298
+ return ret;
299
+ }
300
+ /**
301
+ * @param {Uint8Array} emission
302
+ * @param {Uint8Array} opacity
303
+ */
304
+ setLightTables(emission, opacity) {
305
+ const ptr0 = passArray8ToWasm0(emission, wasm.__wbindgen_malloc);
306
+ const len0 = WASM_VECTOR_LEN;
307
+ const ptr1 = passArray8ToWasm0(opacity, wasm.__wbindgen_malloc);
308
+ const len1 = WASM_VECTOR_LEN;
309
+ wasm.jslightengine_setLightTables(this.__wbg_ptr, ptr0, len0, ptr1, len1);
310
+ }
311
+ /**
312
+ * @returns {number}
313
+ */
314
+ get fallbackRelights() {
315
+ const ret = wasm.jslightengine_fallbackRelights(this.__wbg_ptr);
316
+ return ret >>> 0;
317
+ }
318
+ /**
319
+ * @param {Uint8Array} occupancy
320
+ */
321
+ setOcclusionTable(occupancy) {
322
+ const ptr0 = passArray8ToWasm0(occupancy, wasm.__wbindgen_malloc);
323
+ const len0 = WASM_VECTOR_LEN;
324
+ wasm.jslightengine_setOcclusionTable(this.__wbg_ptr, ptr0, len0);
325
+ }
326
+ /**
327
+ * @param {boolean} enabled
328
+ */
329
+ setSkyLightEnabled(enabled) {
330
+ wasm.jslightengine_setSkyLightEnabled(this.__wbg_ptr, enabled);
331
+ }
332
+ /**
333
+ * @returns {any}
334
+ */
335
+ pollCompletedPublication() {
336
+ const ret = wasm.jslightengine_pollCompletedPublication(this.__wbg_ptr);
337
+ return ret;
338
+ }
339
+ /**
340
+ * @param {number} budget_ms
341
+ * @returns {boolean}
342
+ */
343
+ step(budget_ms) {
344
+ const ret = wasm.jslightengine_step(this.__wbg_ptr, budget_ms);
345
+ return ret !== 0;
346
+ }
347
+ /**
348
+ * @param {number} world_min_y
349
+ * @param {number} world_height
350
+ */
351
+ constructor(world_min_y, world_height) {
352
+ const ret = wasm.jslightengine_js_new(world_min_y, world_height);
353
+ this.__wbg_ptr = ret >>> 0;
354
+ JsLightEngineFinalization.register(this, this.__wbg_ptr, this);
355
+ return this;
356
+ }
357
+ }
358
+ if (Symbol.dispose) JsLightEngine.prototype[Symbol.dispose] = JsLightEngine.prototype.free;
359
+
250
360
  /**
251
361
  * Compute wireframe edge positions from a triangle mesh.
252
362
  *
@@ -879,11 +989,11 @@ export function parseMapChunkV18Plus(raw_packet, num_sections, max_bits_per_bloc
879
989
  * `raw_packet` includes the leading packet-id varint (we skip it).
880
990
  * `num_sections` should match the column the light is for (16 in 1.17).
881
991
  *
882
- * Returns `{ x, z, skyLight: Uint8Array(num_sections * 4096),
883
- * blockLight: Uint8Array(num_sections * 4096), bytesRead }`.
884
- * Layout matches the existing 1.18+ light arrays
885
- * (`x + z*16 + y_abs*256`); the JS-side worker reorders into per-section
886
- * stack via the same path used for 1.18+ raw map_chunk parsing.
992
+ * Returns `{ x, z, trustEdges, skyLight, blockLight, skyLightMask,
993
+ * emptySkyLightMask, blockLightMask, emptyBlockLightMask,
994
+ * skyBelow?, skyAbove?, blockBelow?, blockAbove?, bytesRead }`.
995
+ * World arrays are `num_sections * 4096` (`x + z*16 + y_abs*256`).
996
+ * Omitted sections are left 0 and are not authoritative — use the masks.
887
997
  * @param {Uint8Array} raw_packet
888
998
  * @param {number} num_sections
889
999
  * @returns {any}
@@ -948,6 +1058,11 @@ function __wbg_get_imports() {
948
1058
  const ret = Error(getStringFromWasm0(arg0, arg1));
949
1059
  return ret;
950
1060
  };
1061
+ imports.wbg.__wbg___wbindgen_boolean_get_dea25b33882b895b = function(arg0) {
1062
+ const v = arg0;
1063
+ const ret = typeof(v) === 'boolean' ? v : undefined;
1064
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
1065
+ };
951
1066
  imports.wbg.__wbg___wbindgen_debug_string_adfb662ae34724b6 = function(arg0, arg1) {
952
1067
  const ret = debugString(arg1);
953
1068
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -955,6 +1070,28 @@ function __wbg_get_imports() {
955
1070
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
956
1071
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
957
1072
  };
1073
+ imports.wbg.__wbg___wbindgen_is_null_dfda7d66506c95b5 = function(arg0) {
1074
+ const ret = arg0 === null;
1075
+ return ret;
1076
+ };
1077
+ imports.wbg.__wbg___wbindgen_is_undefined_f6b95eab589e0269 = function(arg0) {
1078
+ const ret = arg0 === undefined;
1079
+ return ret;
1080
+ };
1081
+ imports.wbg.__wbg___wbindgen_number_get_9619185a74197f95 = function(arg0, arg1) {
1082
+ const obj = arg1;
1083
+ const ret = typeof(obj) === 'number' ? obj : undefined;
1084
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
1085
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
1086
+ };
1087
+ imports.wbg.__wbg___wbindgen_string_get_a2a31e16edf96e42 = function(arg0, arg1) {
1088
+ const obj = arg1;
1089
+ const ret = typeof(obj) === 'string' ? obj : undefined;
1090
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1091
+ var len1 = WASM_VECTOR_LEN;
1092
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
1093
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
1094
+ };
958
1095
  imports.wbg.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
959
1096
  throw new Error(getStringFromWasm0(arg0, arg1));
960
1097
  };
@@ -962,6 +1099,10 @@ function __wbg_get_imports() {
962
1099
  const ret = arg0[arg1 >>> 0];
963
1100
  return ret;
964
1101
  };
1102
+ imports.wbg.__wbg_get_af9dab7e9603ea93 = function() { return handleError(function (arg0, arg1) {
1103
+ const ret = Reflect.get(arg0, arg1);
1104
+ return ret;
1105
+ }, arguments) };
965
1106
  imports.wbg.__wbg_instanceof_Int32Array_b6281022039fba32 = function(arg0) {
966
1107
  let result;
967
1108
  try {
@@ -990,6 +1131,10 @@ function __wbg_get_imports() {
990
1131
  const ret = arg0.length;
991
1132
  return ret;
992
1133
  };
1134
+ imports.wbg.__wbg_length_89c3414ed7f0594d = function(arg0) {
1135
+ const ret = arg0.length;
1136
+ return ret;
1137
+ };
993
1138
  imports.wbg.__wbg_length_ab53989976907f11 = function(arg0) {
994
1139
  const ret = arg0.length;
995
1140
  return ret;
@@ -1002,10 +1147,26 @@ function __wbg_get_imports() {
1002
1147
  const ret = new Array();
1003
1148
  return ret;
1004
1149
  };
1150
+ imports.wbg.__wbg_new_6421f6084cc5bc5a = function(arg0) {
1151
+ const ret = new Uint8Array(arg0);
1152
+ return ret;
1153
+ };
1154
+ imports.wbg.__wbg_new_9f7fd5c3a6ba7298 = function(arg0) {
1155
+ const ret = new Uint16Array(arg0);
1156
+ return ret;
1157
+ };
1158
+ imports.wbg.__wbg_new_from_slice_e6bd3cfb5a35313d = function(arg0, arg1) {
1159
+ const ret = new Int32Array(getArrayI32FromWasm0(arg0, arg1));
1160
+ return ret;
1161
+ };
1005
1162
  imports.wbg.__wbg_new_with_length_1e8603a5c71d4e06 = function(arg0) {
1006
1163
  const ret = new Int32Array(arg0 >>> 0);
1007
1164
  return ret;
1008
1165
  };
1166
+ imports.wbg.__wbg_new_with_length_202b3db94ba5fc86 = function(arg0) {
1167
+ const ret = new Uint32Array(arg0 >>> 0);
1168
+ return ret;
1169
+ };
1009
1170
  imports.wbg.__wbg_new_with_length_aa5eaf41d35235e5 = function(arg0) {
1010
1171
  const ret = new Uint8Array(arg0 >>> 0);
1011
1172
  return ret;
@@ -1014,12 +1175,23 @@ function __wbg_get_imports() {
1014
1175
  const ret = new Uint16Array(arg0 >>> 0);
1015
1176
  return ret;
1016
1177
  };
1178
+ imports.wbg.__wbg_now_69d776cd24f5215b = function() {
1179
+ const ret = Date.now();
1180
+ return ret;
1181
+ };
1182
+ imports.wbg.__wbg_prototypesetcall_b0bea5f39077cfd3 = function(arg0, arg1, arg2) {
1183
+ Uint16Array.prototype.set.call(getArrayU16FromWasm0(arg0, arg1), arg2);
1184
+ };
1017
1185
  imports.wbg.__wbg_prototypesetcall_dd07c344a74d4bfd = function(arg0, arg1, arg2) {
1018
1186
  Int32Array.prototype.set.call(getArrayI32FromWasm0(arg0, arg1), arg2);
1019
1187
  };
1020
1188
  imports.wbg.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) {
1021
1189
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
1022
1190
  };
1191
+ imports.wbg.__wbg_push_7d9be8f38fc13975 = function(arg0, arg1) {
1192
+ const ret = arg0.push(arg1);
1193
+ return ret;
1194
+ };
1023
1195
  imports.wbg.__wbg_set_169e13b608078b7b = function(arg0, arg1, arg2) {
1024
1196
  arg0.set(getArrayU8FromWasm0(arg1, arg2));
1025
1197
  };
@@ -1036,6 +1208,9 @@ function __wbg_get_imports() {
1036
1208
  imports.wbg.__wbg_set_bb0c6a7fe60d81b5 = function(arg0, arg1, arg2) {
1037
1209
  arg0.set(getArrayU16FromWasm0(arg1, arg2));
1038
1210
  };
1211
+ imports.wbg.__wbg_set_e7cd108182596b7f = function(arg0, arg1, arg2) {
1212
+ arg0.set(getArrayU32FromWasm0(arg1, arg2));
1213
+ };
1039
1214
  imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
1040
1215
  // Cast intrinsic for `Ref(String) -> Externref`.
1041
1216
  const ret = getStringFromWasm0(arg0, arg1);
@@ -2,6 +2,7 @@
2
2
  /* tslint:disable */
3
3
  /* eslint-disable */
4
4
  export const memory: WebAssembly.Memory;
5
+ export const __wbg_jslightengine_free: (a: number, b: number) => void;
5
6
  export const computeWireframeEdges: (a: number, b: number, c: number, d: number) => [number, number];
6
7
  export const computeWireframeEdgesU16: (a: number, b: number, c: number, d: number) => [number, number];
7
8
  export const generateGeometryFromDump118: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number, h1: number, i1: number, j1: number, k1: number) => any;
@@ -11,6 +12,16 @@ export const generateGeometryFromParsedV16V17: (a: number, b: number, c: number,
11
12
  export const generateGeometryFromParsedV16V17Multi: (a: any, b: number, c: number, d: number, e: number, f: number, g: any, h: number, i: any, j: any, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number, h1: number) => any;
12
13
  export const generate_geometry: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number) => any;
13
14
  export const generate_geometry_multi: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number) => any;
15
+ export const jslightengine_fallbackRelights: (a: number) => number;
16
+ export const jslightengine_getBlockLight: (a: number, b: number, c: number, d: number) => number;
17
+ export const jslightengine_getSkyLight: (a: number, b: number, c: number, d: number) => number;
18
+ export const jslightengine_js_new: (a: number, b: number) => number;
19
+ export const jslightengine_pollCompletedPublication: (a: number) => any;
20
+ export const jslightengine_pushEvent: (a: number, b: any) => void;
21
+ export const jslightengine_setLightTables: (a: number, b: number, c: number, d: number, e: number) => void;
22
+ export const jslightengine_setOcclusionTable: (a: number, b: number, c: number) => void;
23
+ export const jslightengine_setSkyLightEnabled: (a: number, b: number) => void;
24
+ export const jslightengine_step: (a: number, b: number) => number;
14
25
  export const parseChunkDump118: (a: number, b: number, c: number, d: number, e: number) => any;
15
26
  export const parseChunkDump118FullColumn: (a: number, b: number, c: number, d: number, e: number) => any;
16
27
  export const parseChunkDump118FullColumnAll: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number) => any;
@@ -0,0 +1,83 @@
1
+ //@ts-nocheck
2
+ import { describe, expect, test } from 'vitest'
3
+ import { provenMeshLightVersion } from '../worker/mesherLightDependencies'
4
+
5
+ function prove(sx: number, sz: number, used: string[], applied: Array<[string, number]>) {
6
+ return provenMeshLightVersion({
7
+ sx,
8
+ sz,
9
+ usedColumns: new Set(used),
10
+ appliedVersionByColumn: new Map(applied)
11
+ })
12
+ }
13
+
14
+ describe('provenMeshLightVersion', () => {
15
+ test('a bootstrap neighbor wall takes the published column version when that column was meshed', () => {
16
+ expect(prove(16, 0, ['0,0', '16,0'], [['0,0', 10]])).toBe(10)
17
+ expect(prove(0, 16, ['0,0', '0,16'], [['0,0', 8]])).toBe(8)
18
+ })
19
+
20
+ test('negative chunk coordinates use the same column keys', () => {
21
+ expect(prove(-16, -32, ['-32,-32', '-16,-32'], [['-32,-32', 7]])).toBe(7)
22
+ })
23
+
24
+ test('an unused published column is not proof, even if a dirty job requested that version', () => {
25
+ expect(prove(16, 0, ['16,0'], [['0,0', 10]])).toBe(0)
26
+ })
27
+
28
+ test('an older own-column version does not hide a newer neighbor publication that was meshed', () => {
29
+ expect(
30
+ prove(
31
+ 16,
32
+ 0,
33
+ ['0,0', '16,0'],
34
+ [
35
+ ['16,0', 4],
36
+ ['0,0', 10]
37
+ ]
38
+ )
39
+ ).toBe(10)
40
+ })
41
+
42
+ test('a later own publication does not cover an earlier neighbor that was left out of the mesh', () => {
43
+ expect(
44
+ prove(
45
+ 16,
46
+ 0,
47
+ ['16,0'],
48
+ [
49
+ ['0,0', 10],
50
+ ['16,0', 12]
51
+ ]
52
+ )
53
+ ).toBe(0)
54
+ })
55
+
56
+ test('a used column older than the missing neighbor still counts', () => {
57
+ expect(
58
+ prove(
59
+ 16,
60
+ 0,
61
+ ['16,0'],
62
+ [
63
+ ['0,0', 10],
64
+ ['16,0', 4]
65
+ ]
66
+ )
67
+ ).toBe(4)
68
+ })
69
+
70
+ test('a far column publication does not raise the stamp', () => {
71
+ expect(prove(0, 0, ['0,0', '100,100'], [['100,100', 100]])).toBe(0)
72
+ })
73
+
74
+ test('forgetting a column drops it from later proofs', () => {
75
+ const applied = new Map<string, number>([
76
+ ['0,0', 10],
77
+ ['16,0', 10]
78
+ ])
79
+ applied.delete('0,0')
80
+ expect(prove(16, 0, ['16,0'], [...applied.entries()])).toBe(10)
81
+ expect(prove(0, 0, ['0,0'], [...applied.entries()])).toBe(0)
82
+ })
83
+ })
@@ -0,0 +1,39 @@
1
+ //@ts-nocheck
2
+ import { describe, expect, test } from 'vitest'
3
+ import { BULK_COLUMNS_PER_TICK, selectColumnGroupsForTick } from '../worker/mesherWasmColumnTickSelect'
4
+
5
+ function dirtyOf(keys: string[]): Map<string, number> {
6
+ const dirty = new Map<string, number>()
7
+ for (const key of keys) dirty.set(key, 1)
8
+ return dirty
9
+ }
10
+
11
+ describe('selectColumnGroupsForTick', () => {
12
+ test('urgent columns are selected before bulk columns', () => {
13
+ const dirty = dirtyOf(['160,64,0', '0,64,0', '32,64,0'])
14
+ const urgent = new Set(['0,64,0'])
15
+ const { selected, remaining } = selectColumnGroupsForTick(dirty, urgent, 4)
16
+ expect(selected.map(group => `${group.x},${group.z}`)).toEqual(['0,0', '160,0', '32,0'])
17
+ expect(remaining.size).toBe(0)
18
+ })
19
+
20
+ test('a tick leaves leftover bulk columns for the next tick', () => {
21
+ const keys = ['0,64,0', '16,64,0', '32,64,0', '48,64,0', '64,64,0', '80,64,0']
22
+ const dirty = dirtyOf(keys)
23
+ const first = selectColumnGroupsForTick(dirty, new Set(), BULK_COLUMNS_PER_TICK)
24
+ expect(first.selected).toHaveLength(4)
25
+ expect([...first.remaining.keys()]).toEqual(['64,64,0', '80,64,0'])
26
+ const second = selectColumnGroupsForTick(first.remaining, new Set(), BULK_COLUMNS_PER_TICK)
27
+ expect(second.selected.map(group => `${group.x},${group.z}`)).toEqual(['64,0', '80,0'])
28
+ expect(second.remaining.size).toBe(0)
29
+ })
30
+
31
+ test('urgent still wins when the same key also has bulk dirties', () => {
32
+ const dirty = dirtyOf(['16,64,0', '0,64,0', '32,64,0', '48,64,0', '64,64,0', '80,64,0', '96,64,0'])
33
+ dirty.set('0,64,0', 2)
34
+ const { selected, remaining } = selectColumnGroupsForTick(dirty, new Set(['0,64,0']), 4)
35
+ expect(selected[0]).toMatchObject({ x: 0, z: 0 })
36
+ expect(selected).toHaveLength(5)
37
+ expect([...remaining.keys()]).toEqual(['80,64,0', '96,64,0'])
38
+ })
39
+ })
@@ -5,7 +5,8 @@ import {
5
5
  _peekConversionCache,
6
6
  clearConversionCache,
7
7
  getOrConvertColumn,
8
- invalidateConversion
8
+ invalidateConversion,
9
+ patchConversionBlock
9
10
  } from '../worker/mesherWasmConversionCache'
10
11
  import type { ChunkConversionResult } from '../bridge/convertChunk'
11
12
 
@@ -27,6 +28,34 @@ describe('mesherWasmConversionCache', () => {
27
28
  clearConversionCache()
28
29
  })
29
30
 
31
+ test('patches state and count in place and rejects identity drift', () => {
32
+ const ref = {}
33
+ const result = { ...makeResult(0), blockStates: new Uint16Array(4096) }
34
+ getOrConvertColumn(-16, 0, ref, 'v', -64, -48, () => result, ref)
35
+ expect(patchConversionBlock(-16, 0, ref, -1, -49, 15, 2)).toBe(true)
36
+ expect(result.blockStates[4095]).toBe(2)
37
+ expect(result.blockCount).toBe(1)
38
+ patchConversionBlock(-16, 0, ref, -1, -49, 15, 3)
39
+ expect(result.blockCount).toBe(1)
40
+ expect(patchConversionBlock(-16, 0, {}, -1, -49, 15, 0)).toBe(false)
41
+ patchConversionBlock(-16, 0, ref, -1, -49, 15, 0)
42
+ expect(result.blockCount).toBe(0)
43
+ expect(
44
+ getOrConvertColumn(
45
+ -16,
46
+ 0,
47
+ ref,
48
+ 'v',
49
+ -64,
50
+ -48,
51
+ () => {
52
+ throw new Error('unexpected conversion')
53
+ },
54
+ ref
55
+ ).result
56
+ ).toBe(result)
57
+ })
58
+
30
59
  test('miss then hit on same chunk ref returns cached result', () => {
31
60
  const ref = { id: 'chunk-a' }
32
61
  let calls = 0
@@ -0,0 +1,73 @@
1
+ //@ts-nocheck
2
+ import { afterEach, describe, expect, test } from 'vitest'
3
+ import { beginTickWasmParseCache, endTickWasmParseCache, getOrConvertTickWasmParse, getTickWasmParseStats } from '../worker/mesherWasmTickParseCache'
4
+
5
+ afterEach(() => {
6
+ endTickWasmParseCache()
7
+ })
8
+
9
+ describe('mesherWasmTickParseCache', () => {
10
+ test('second convert of the same column in one tick is a hit without copying', () => {
11
+ beginTickWasmParseCache()
12
+ let calls = 0
13
+ const convert = () => {
14
+ calls++
15
+ return { tag: calls }
16
+ }
17
+ const a = getOrConvertTickWasmParse('0,0', convert)
18
+ const b = getOrConvertTickWasmParse('0,0', convert)
19
+ expect(a.hit).toBe(false)
20
+ expect(b.hit).toBe(true)
21
+ expect(calls).toBe(1)
22
+ expect(b.result).toBe(a.result)
23
+ expect(getTickWasmParseStats()).toEqual({ hits: 1, misses: 1 })
24
+ })
25
+
26
+ test('distinct columns miss independently and unique-column count matches the cache', () => {
27
+ beginTickWasmParseCache()
28
+ let calls = 0
29
+ const convert = () => {
30
+ calls++
31
+ return { tag: calls }
32
+ }
33
+ for (let i = 0; i < 9; i++) getOrConvertTickWasmParse(`${i * 16},0`, convert)
34
+ for (let i = 0; i < 9; i++) getOrConvertTickWasmParse(`${i * 16},0`, convert)
35
+ expect(calls).toBe(9)
36
+ expect(getTickWasmParseStats()).toEqual({ hits: 9, misses: 9 })
37
+ })
38
+
39
+ test('null results are not cached so a later convert can recover', () => {
40
+ beginTickWasmParseCache()
41
+ let calls = 0
42
+ const a = getOrConvertTickWasmParse('16,16', () => {
43
+ calls++
44
+ return null
45
+ })
46
+ const b = getOrConvertTickWasmParse('16,16', () => {
47
+ calls++
48
+ return { tag: 1 }
49
+ })
50
+ expect(a.result).toBeNull()
51
+ expect(a.hit).toBe(false)
52
+ expect(b.hit).toBe(false)
53
+ expect(b.result).toEqual({ tag: 1 })
54
+ expect(calls).toBe(2)
55
+ })
56
+
57
+ test('end of tick drops entries so the next tick misses', () => {
58
+ beginTickWasmParseCache()
59
+ let calls = 0
60
+ getOrConvertTickWasmParse('0,0', () => {
61
+ calls++
62
+ return { tag: 1 }
63
+ })
64
+ endTickWasmParseCache()
65
+ beginTickWasmParseCache()
66
+ getOrConvertTickWasmParse('0,0', () => {
67
+ calls++
68
+ return { tag: 2 }
69
+ })
70
+ expect(calls).toBe(2)
71
+ expect(getTickWasmParseStats()).toEqual({ hits: 0, misses: 1 })
72
+ })
73
+ })
@@ -0,0 +1,51 @@
1
+ //@ts-nocheck
2
+ import { describe, expect, test, vi } from 'vitest'
3
+ import { BULK_MESH_INTERVAL_MS, createMeshTickScheduler } from '../worker/mesherWasmTickSchedule'
4
+
5
+ describe('createMeshTickScheduler', () => {
6
+ test('an urgent kick runs on the next turn, before the bulk poll interval', async () => {
7
+ vi.useFakeTimers()
8
+ try {
9
+ let runs = 0
10
+ const scheduler = createMeshTickScheduler(() => {
11
+ runs++
12
+ })
13
+ scheduler.kick()
14
+ expect(runs).toBe(0)
15
+ await vi.advanceTimersByTimeAsync(0)
16
+ expect(runs).toBe(1)
17
+ expect(BULK_MESH_INTERVAL_MS).toBeGreaterThan(0)
18
+ } finally {
19
+ vi.clearAllTimers()
20
+ vi.useRealTimers()
21
+ }
22
+ })
23
+
24
+ test('a kick during a running tick runs again after that tick finishes', async () => {
25
+ vi.useFakeTimers()
26
+ try {
27
+ let release: () => void = () => {}
28
+ const gate = new Promise<void>(resolve => {
29
+ release = resolve
30
+ })
31
+ let runs = 0
32
+ const scheduler = createMeshTickScheduler(() => {
33
+ runs++
34
+ if (runs === 1) {
35
+ scheduler.kick()
36
+ return gate
37
+ }
38
+ })
39
+ scheduler.kick()
40
+ await vi.advanceTimersByTimeAsync(0)
41
+ expect(runs).toBe(1)
42
+ release()
43
+ await gate
44
+ await Promise.resolve()
45
+ expect(runs).toBe(2)
46
+ } finally {
47
+ vi.clearAllTimers()
48
+ vi.useRealTimers()
49
+ }
50
+ })
51
+ })