minecraft-renderer 0.1.41 → 0.1.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minecraft-renderer",
3
- "version": "0.1.41",
3
+ "version": "0.1.42",
4
4
  "description": "The most Modular Minecraft world renderer with Three.js WebGL backend",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -27,6 +27,24 @@ export function generateGeometryFromDump118(section_x: number, section_y: number
27
27
  */
28
28
  export function generateGeometryFromMapChunkV18Plus(raw_packet: Uint8Array, num_sections: number, max_bits_per_block: number, max_bits_per_biome: number, protocol: number, section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number, section_data_start_y: number, invisible_blocks: Uint16Array, transparent_blocks: Uint16Array, no_ao_blocks: Uint16Array, cull_identical_blocks: Uint16Array, occluding_blocks: Uint16Array, enable_lighting: boolean, smooth_lighting: boolean, sky_light_value: number): any;
29
29
 
30
+ /**
31
+ * Fused multi-column parse+mesh for 1.18+ raw map_chunk.
32
+ *
33
+ * Parses multiple raw packets inside Rust and meshes them in a single
34
+ * `mesher.generate_multi` call with correct per-neighbor AO/lighting.
35
+ * No typed arrays are materialised on the JS heap.
36
+ *
37
+ * `raw_packets` — `Array<Uint8Array>`, one raw packet per column.
38
+ * Reuses the existing JS-side per-column buffers (zero concat, zero alloc).
39
+ *
40
+ * `num_sections_list` — per-column section count (terrain height varies).
41
+ *
42
+ * Invariant: `chunk_xs[0]` / `chunk_zs[0]` is the **target** column whose
43
+ * geometry is emitted. Neighbour columns provide border data to the mesher
44
+ * but do not contribute directly to the output.
45
+ */
46
+ export function generateGeometryFromMapChunkV18PlusMulti(raw_packets: Array<any>, num_sections_list: Uint32Array, max_bits_per_block: number, max_bits_per_biome: number, protocol: number, chunk_xs: Int32Array, chunk_zs: Int32Array, section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number, section_data_start_y: number, invisible_blocks: Uint16Array, transparent_blocks: Uint16Array, no_ao_blocks: Uint16Array, cull_identical_blocks: Uint16Array, occluding_blocks: Uint16Array, enable_lighting: boolean, smooth_lighting: boolean, sky_light_value: number): any;
47
+
30
48
  /**
31
49
  * Fused parse+mesh for 1.16 / 1.17 chunk sections.
32
50
  *
@@ -41,6 +59,27 @@ export function generateGeometryFromMapChunkV18Plus(raw_packet: Uint8Array, num_
41
59
  */
42
60
  export function generateGeometryFromParsedV16V17(chunk_data: Uint8Array, bit_map_lo_hi: Uint32Array, num_sections: number, max_bits_per_block: number, biomes_cells: Int32Array, default_biome: number, sky_light: Uint8Array, block_light: Uint8Array, section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number, section_data_start_y: number, invisible_blocks: Uint16Array, transparent_blocks: Uint16Array, no_ao_blocks: Uint16Array, cull_identical_blocks: Uint16Array, occluding_blocks: Uint16Array, enable_lighting: boolean, smooth_lighting: boolean, sky_light_value: number): any;
43
61
 
62
+ /**
63
+ * Fused multi-column parse+mesh for 1.16 / 1.17 chunk sections.
64
+ *
65
+ * Parses multiple columns inside Rust and meshes them in one
66
+ * `mesher.generate_multi` call. Block states and biomes never leave WASM
67
+ * memory; light arrays are passed by reference from the JS-side
68
+ * update-light caches.
69
+ *
70
+ * `chunk_data_list` — `Array<Uint8Array>`, one chunk_data buffer per column.
71
+ * `bit_map_lo_hi` — flat `&[u32]` of length `chunkCount * 2`; each pair
72
+ * (lo, hi) is the section mask for one column.
73
+ * `num_sections_list` — per-column section count.
74
+ * `biomes_cells_list` — `Array<Int32Array>`, may contain empty arrays for
75
+ * columns without captured biomes.
76
+ * `sky_light_list` / `block_light_list` — `Array<Uint8Array>`, may contain
77
+ * empty arrays for columns where update_light has not arrived yet.
78
+ *
79
+ * Invariant: `chunk_xs[0]` / `chunk_zs[0]` is the target column.
80
+ */
81
+ export function generateGeometryFromParsedV16V17Multi(chunk_data_list: Array<any>, bit_map_lo_hi: Uint32Array, num_sections_list: Uint32Array, max_bits_per_block: number, biomes_cells_list: Array<any>, default_biome: number, sky_light_list: Array<any>, block_light_list: Array<any>, chunk_xs: Int32Array, chunk_zs: Int32Array, section_x: number, section_y: number, section_z: number, section_height: number, world_min_y: number, world_max_y: number, section_data_start_y: number, invisible_blocks: Uint16Array, transparent_blocks: Uint16Array, no_ao_blocks: Uint16Array, cull_identical_blocks: Uint16Array, occluding_blocks: Uint16Array, enable_lighting: boolean, smooth_lighting: boolean, sky_light_value: number): any;
82
+
44
83
  /**
45
84
  * Main entry point for generating geometry
46
85
  *
@@ -177,6 +216,8 @@ export interface InitOutput {
177
216
  readonly parseMapChunkV18Plus: (a: number, b: number, c: number, d: number, e: number, f: number) => any;
178
217
  readonly parseChunkSectionsV16V17: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => any;
179
218
  readonly generateGeometryFromParsedV16V17: (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) => any;
219
+ readonly generateGeometryFromMapChunkV18PlusMulti: (a: any, 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) => any;
220
+ 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;
180
221
  readonly parseUpdateLightV17: (a: number, b: number, c: number) => any;
181
222
  readonly __wbindgen_malloc: (a: number, b: number) => number;
182
223
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -71,6 +71,11 @@ function debugString(val) {
71
71
  return className;
72
72
  }
73
73
 
74
+ function getArrayI32FromWasm0(ptr, len) {
75
+ ptr = ptr >>> 0;
76
+ return getInt32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
77
+ }
78
+
74
79
  function getArrayU16FromWasm0(ptr, len) {
75
80
  ptr = ptr >>> 0;
76
81
  return getUint16ArrayMemory0().subarray(ptr / 2, ptr / 2 + len);
@@ -89,6 +94,14 @@ function getDataViewMemory0() {
89
94
  return cachedDataViewMemory0;
90
95
  }
91
96
 
97
+ let cachedInt32ArrayMemory0 = null;
98
+ function getInt32ArrayMemory0() {
99
+ if (cachedInt32ArrayMemory0 === null || cachedInt32ArrayMemory0.byteLength === 0) {
100
+ cachedInt32ArrayMemory0 = new Int32Array(wasm.memory.buffer);
101
+ }
102
+ return cachedInt32ArrayMemory0;
103
+ }
104
+
92
105
  function getStringFromWasm0(ptr, len) {
93
106
  ptr = ptr >>> 0;
94
107
  return decodeText(ptr, len);
@@ -328,6 +341,66 @@ export function generateGeometryFromMapChunkV18Plus(raw_packet, num_sections, ma
328
341
  return ret;
329
342
  }
330
343
 
344
+ /**
345
+ * Fused multi-column parse+mesh for 1.18+ raw map_chunk.
346
+ *
347
+ * Parses multiple raw packets inside Rust and meshes them in a single
348
+ * `mesher.generate_multi` call with correct per-neighbor AO/lighting.
349
+ * No typed arrays are materialised on the JS heap.
350
+ *
351
+ * `raw_packets` — `Array<Uint8Array>`, one raw packet per column.
352
+ * Reuses the existing JS-side per-column buffers (zero concat, zero alloc).
353
+ *
354
+ * `num_sections_list` — per-column section count (terrain height varies).
355
+ *
356
+ * Invariant: `chunk_xs[0]` / `chunk_zs[0]` is the **target** column whose
357
+ * geometry is emitted. Neighbour columns provide border data to the mesher
358
+ * but do not contribute directly to the output.
359
+ * @param {Array<any>} raw_packets
360
+ * @param {Uint32Array} num_sections_list
361
+ * @param {number} max_bits_per_block
362
+ * @param {number} max_bits_per_biome
363
+ * @param {number} protocol
364
+ * @param {Int32Array} chunk_xs
365
+ * @param {Int32Array} chunk_zs
366
+ * @param {number} section_x
367
+ * @param {number} section_y
368
+ * @param {number} section_z
369
+ * @param {number} section_height
370
+ * @param {number} world_min_y
371
+ * @param {number} world_max_y
372
+ * @param {number} section_data_start_y
373
+ * @param {Uint16Array} invisible_blocks
374
+ * @param {Uint16Array} transparent_blocks
375
+ * @param {Uint16Array} no_ao_blocks
376
+ * @param {Uint16Array} cull_identical_blocks
377
+ * @param {Uint16Array} occluding_blocks
378
+ * @param {boolean} enable_lighting
379
+ * @param {boolean} smooth_lighting
380
+ * @param {number} sky_light_value
381
+ * @returns {any}
382
+ */
383
+ export function generateGeometryFromMapChunkV18PlusMulti(raw_packets, num_sections_list, max_bits_per_block, max_bits_per_biome, protocol, chunk_xs, chunk_zs, section_x, section_y, section_z, section_height, world_min_y, world_max_y, section_data_start_y, invisible_blocks, transparent_blocks, no_ao_blocks, cull_identical_blocks, occluding_blocks, enable_lighting, smooth_lighting, sky_light_value) {
384
+ const ptr0 = passArray32ToWasm0(num_sections_list, wasm.__wbindgen_malloc);
385
+ const len0 = WASM_VECTOR_LEN;
386
+ const ptr1 = passArray32ToWasm0(chunk_xs, wasm.__wbindgen_malloc);
387
+ const len1 = WASM_VECTOR_LEN;
388
+ const ptr2 = passArray32ToWasm0(chunk_zs, wasm.__wbindgen_malloc);
389
+ const len2 = WASM_VECTOR_LEN;
390
+ const ptr3 = passArray16ToWasm0(invisible_blocks, wasm.__wbindgen_malloc);
391
+ const len3 = WASM_VECTOR_LEN;
392
+ const ptr4 = passArray16ToWasm0(transparent_blocks, wasm.__wbindgen_malloc);
393
+ const len4 = WASM_VECTOR_LEN;
394
+ const ptr5 = passArray16ToWasm0(no_ao_blocks, wasm.__wbindgen_malloc);
395
+ const len5 = WASM_VECTOR_LEN;
396
+ const ptr6 = passArray16ToWasm0(cull_identical_blocks, wasm.__wbindgen_malloc);
397
+ const len6 = WASM_VECTOR_LEN;
398
+ const ptr7 = passArray16ToWasm0(occluding_blocks, wasm.__wbindgen_malloc);
399
+ const len7 = WASM_VECTOR_LEN;
400
+ const ret = wasm.generateGeometryFromMapChunkV18PlusMulti(raw_packets, ptr0, len0, max_bits_per_block, max_bits_per_biome, protocol, ptr1, len1, ptr2, len2, section_x, section_y, section_z, section_height, world_min_y, world_max_y, section_data_start_y, ptr3, len3, ptr4, len4, ptr5, len5, ptr6, len6, ptr7, len7, enable_lighting, smooth_lighting, sky_light_value);
401
+ return ret;
402
+ }
403
+
331
404
  /**
332
405
  * Fused parse+mesh for 1.16 / 1.17 chunk sections.
333
406
  *
@@ -389,6 +462,74 @@ export function generateGeometryFromParsedV16V17(chunk_data, bit_map_lo_hi, num_
389
462
  return ret;
390
463
  }
391
464
 
465
+ /**
466
+ * Fused multi-column parse+mesh for 1.16 / 1.17 chunk sections.
467
+ *
468
+ * Parses multiple columns inside Rust and meshes them in one
469
+ * `mesher.generate_multi` call. Block states and biomes never leave WASM
470
+ * memory; light arrays are passed by reference from the JS-side
471
+ * update-light caches.
472
+ *
473
+ * `chunk_data_list` — `Array<Uint8Array>`, one chunk_data buffer per column.
474
+ * `bit_map_lo_hi` — flat `&[u32]` of length `chunkCount * 2`; each pair
475
+ * (lo, hi) is the section mask for one column.
476
+ * `num_sections_list` — per-column section count.
477
+ * `biomes_cells_list` — `Array<Int32Array>`, may contain empty arrays for
478
+ * columns without captured biomes.
479
+ * `sky_light_list` / `block_light_list` — `Array<Uint8Array>`, may contain
480
+ * empty arrays for columns where update_light has not arrived yet.
481
+ *
482
+ * Invariant: `chunk_xs[0]` / `chunk_zs[0]` is the target column.
483
+ * @param {Array<any>} chunk_data_list
484
+ * @param {Uint32Array} bit_map_lo_hi
485
+ * @param {Uint32Array} num_sections_list
486
+ * @param {number} max_bits_per_block
487
+ * @param {Array<any>} biomes_cells_list
488
+ * @param {number} default_biome
489
+ * @param {Array<any>} sky_light_list
490
+ * @param {Array<any>} block_light_list
491
+ * @param {Int32Array} chunk_xs
492
+ * @param {Int32Array} chunk_zs
493
+ * @param {number} section_x
494
+ * @param {number} section_y
495
+ * @param {number} section_z
496
+ * @param {number} section_height
497
+ * @param {number} world_min_y
498
+ * @param {number} world_max_y
499
+ * @param {number} section_data_start_y
500
+ * @param {Uint16Array} invisible_blocks
501
+ * @param {Uint16Array} transparent_blocks
502
+ * @param {Uint16Array} no_ao_blocks
503
+ * @param {Uint16Array} cull_identical_blocks
504
+ * @param {Uint16Array} occluding_blocks
505
+ * @param {boolean} enable_lighting
506
+ * @param {boolean} smooth_lighting
507
+ * @param {number} sky_light_value
508
+ * @returns {any}
509
+ */
510
+ export function generateGeometryFromParsedV16V17Multi(chunk_data_list, bit_map_lo_hi, num_sections_list, max_bits_per_block, biomes_cells_list, default_biome, sky_light_list, block_light_list, chunk_xs, chunk_zs, section_x, section_y, section_z, section_height, world_min_y, world_max_y, section_data_start_y, invisible_blocks, transparent_blocks, no_ao_blocks, cull_identical_blocks, occluding_blocks, enable_lighting, smooth_lighting, sky_light_value) {
511
+ const ptr0 = passArray32ToWasm0(bit_map_lo_hi, wasm.__wbindgen_malloc);
512
+ const len0 = WASM_VECTOR_LEN;
513
+ const ptr1 = passArray32ToWasm0(num_sections_list, wasm.__wbindgen_malloc);
514
+ const len1 = WASM_VECTOR_LEN;
515
+ const ptr2 = passArray32ToWasm0(chunk_xs, wasm.__wbindgen_malloc);
516
+ const len2 = WASM_VECTOR_LEN;
517
+ const ptr3 = passArray32ToWasm0(chunk_zs, wasm.__wbindgen_malloc);
518
+ const len3 = WASM_VECTOR_LEN;
519
+ const ptr4 = passArray16ToWasm0(invisible_blocks, wasm.__wbindgen_malloc);
520
+ const len4 = WASM_VECTOR_LEN;
521
+ const ptr5 = passArray16ToWasm0(transparent_blocks, wasm.__wbindgen_malloc);
522
+ const len5 = WASM_VECTOR_LEN;
523
+ const ptr6 = passArray16ToWasm0(no_ao_blocks, wasm.__wbindgen_malloc);
524
+ const len6 = WASM_VECTOR_LEN;
525
+ const ptr7 = passArray16ToWasm0(cull_identical_blocks, wasm.__wbindgen_malloc);
526
+ const len7 = WASM_VECTOR_LEN;
527
+ const ptr8 = passArray16ToWasm0(occluding_blocks, wasm.__wbindgen_malloc);
528
+ const len8 = WASM_VECTOR_LEN;
529
+ const ret = wasm.generateGeometryFromParsedV16V17Multi(chunk_data_list, ptr0, len0, ptr1, len1, max_bits_per_block, biomes_cells_list, default_biome, sky_light_list, block_light_list, ptr2, len2, ptr3, len3, section_x, section_y, section_z, section_height, world_min_y, world_max_y, section_data_start_y, ptr4, len4, ptr5, len5, ptr6, len6, ptr7, len7, ptr8, len8, enable_lighting, smooth_lighting, sky_light_value);
530
+ return ret;
531
+ }
532
+
392
533
  /**
393
534
  * Main entry point for generating geometry
394
535
  *
@@ -750,6 +891,30 @@ function __wbg_get_imports() {
750
891
  imports.wbg.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
751
892
  throw new Error(getStringFromWasm0(arg0, arg1));
752
893
  };
894
+ imports.wbg.__wbg_get_6b7bd52aca3f9671 = function(arg0, arg1) {
895
+ const ret = arg0[arg1 >>> 0];
896
+ return ret;
897
+ };
898
+ imports.wbg.__wbg_instanceof_Int32Array_b6281022039fba32 = function(arg0) {
899
+ let result;
900
+ try {
901
+ result = arg0 instanceof Int32Array;
902
+ } catch (_) {
903
+ result = false;
904
+ }
905
+ const ret = result;
906
+ return ret;
907
+ };
908
+ imports.wbg.__wbg_instanceof_Uint8Array_da54ccc9d3e09434 = function(arg0) {
909
+ let result;
910
+ try {
911
+ result = arg0 instanceof Uint8Array;
912
+ } catch (_) {
913
+ result = false;
914
+ }
915
+ const ret = result;
916
+ return ret;
917
+ };
753
918
  imports.wbg.__wbg_length_22ac23eaec9d8053 = function(arg0) {
754
919
  const ret = arg0.length;
755
920
  return ret;
@@ -758,6 +923,10 @@ function __wbg_get_imports() {
758
923
  const ret = arg0.length;
759
924
  return ret;
760
925
  };
926
+ imports.wbg.__wbg_length_ab53989976907f11 = function(arg0) {
927
+ const ret = arg0.length;
928
+ return ret;
929
+ };
761
930
  imports.wbg.__wbg_new_1ba21ce319a06297 = function() {
762
931
  const ret = new Object();
763
932
  return ret;
@@ -766,6 +935,10 @@ function __wbg_get_imports() {
766
935
  const ret = new Array();
767
936
  return ret;
768
937
  };
938
+ imports.wbg.__wbg_new_with_length_1e8603a5c71d4e06 = function(arg0) {
939
+ const ret = new Int32Array(arg0 >>> 0);
940
+ return ret;
941
+ };
769
942
  imports.wbg.__wbg_new_with_length_aa5eaf41d35235e5 = function(arg0) {
770
943
  const ret = new Uint8Array(arg0 >>> 0);
771
944
  return ret;
@@ -774,6 +947,12 @@ function __wbg_get_imports() {
774
947
  const ret = new Uint16Array(arg0 >>> 0);
775
948
  return ret;
776
949
  };
950
+ imports.wbg.__wbg_prototypesetcall_dd07c344a74d4bfd = function(arg0, arg1, arg2) {
951
+ Int32Array.prototype.set.call(getArrayI32FromWasm0(arg0, arg1), arg2);
952
+ };
953
+ imports.wbg.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) {
954
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
955
+ };
777
956
  imports.wbg.__wbg_set_169e13b608078b7b = function(arg0, arg1, arg2) {
778
957
  arg0.set(getArrayU8FromWasm0(arg1, arg2));
779
958
  };
@@ -822,6 +1001,7 @@ function __wbg_finalize_init(instance, module) {
822
1001
  wasm = instance.exports;
823
1002
  __wbg_init.__wbindgen_wasm_module = module;
824
1003
  cachedDataViewMemory0 = null;
1004
+ cachedInt32ArrayMemory0 = null;
825
1005
  cachedUint16ArrayMemory0 = null;
826
1006
  cachedUint32ArrayMemory0 = null;
827
1007
  cachedUint8ArrayMemory0 = null;
@@ -14,6 +14,8 @@ export const generateGeometryFromMapChunkV18Plus: (a: number, b: number, c: numb
14
14
  export const parseMapChunkV18Plus: (a: number, b: number, c: number, d: number, e: number, f: number) => any;
15
15
  export const parseChunkSectionsV16V17: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => any;
16
16
  export const generateGeometryFromParsedV16V17: (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) => any;
17
+ export const generateGeometryFromMapChunkV18PlusMulti: (a: any, 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) => any;
18
+ 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;
17
19
  export const parseUpdateLightV17: (a: number, b: number, c: number) => any;
18
20
  export const __wbindgen_malloc: (a: number, b: number) => number;
19
21
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
@@ -519,6 +519,167 @@ const meshColumnFromParsedV16V17 = (
519
519
  }
520
520
  }
521
521
 
522
+ // ---------------------------------------------------------------------------
523
+ // Fused multi-column helpers.
524
+ // Zero-alloc: reuse existing TypedArray buffers from caches, no concat.
525
+ // ---------------------------------------------------------------------------
526
+
527
+ const meshMultiColumnsFromRawV18Plus = (
528
+ chunksToUse: Array<{ x: number, z: number, chunk: any }>,
529
+ x: number,
530
+ z: number,
531
+ worldMinY: number,
532
+ worldMaxY: number,
533
+ meta: ReturnType<typeof getBlockMeta>
534
+ ): any | null => {
535
+ if (!wasm || !(wasm as any).generateGeometryFromMapChunkV18PlusMulti) return null
536
+ const chunkCount = chunksToUse.length
537
+ if (chunkCount === 0) return null
538
+
539
+ const rawPackets: Uint8Array[] = []
540
+ const numSectionsList = new Uint32Array(chunkCount)
541
+ const chunkXs = new Int32Array(chunkCount)
542
+ const chunkZs = new Int32Array(chunkCount)
543
+ let protocol = 0
544
+
545
+ for (let i = 0; i < chunkCount; i++) {
546
+ const raw = rawMapChunkCache.get(rawCacheKey(chunksToUse[i].x, chunksToUse[i].z))
547
+ if (!raw || raw.protocol < 757) return null
548
+ rawPackets.push(raw.rawPacket)
549
+ numSectionsList[i] = raw.numSections
550
+ chunkXs[i] = chunksToUse[i].x
551
+ chunkZs[i] = chunksToUse[i].z
552
+ if (i === 0) protocol = raw.protocol
553
+ }
554
+
555
+ const columnHeight = worldMaxY - worldMinY
556
+ try {
557
+ return (wasm as any).generateGeometryFromMapChunkV18PlusMulti(
558
+ rawPackets,
559
+ numSectionsList,
560
+ MAX_BITS_PER_BLOCK,
561
+ MAX_BITS_PER_BIOME,
562
+ protocol,
563
+ chunkXs,
564
+ chunkZs,
565
+ x, worldMinY, z, columnHeight,
566
+ worldMinY, worldMaxY,
567
+ worldMinY,
568
+ meta.invisibleBlocks,
569
+ meta.transparentBlocks,
570
+ meta.noAoBlocks,
571
+ meta.cullIdenticalBlocks,
572
+ meta.occludingBlocks,
573
+ config?.enableLighting !== false,
574
+ config?.smoothLighting !== false,
575
+ config?.skyLight || 15
576
+ )
577
+ } catch (err) {
578
+ console.warn('[WASM Mesher] generateGeometryFromMapChunkV18PlusMulti failed:', err)
579
+ return null
580
+ }
581
+ }
582
+
583
+ const meshMultiColumnsFromParsedV16V17 = (
584
+ chunksToUse: Array<{ x: number, z: number, chunk: any }>,
585
+ x: number,
586
+ z: number,
587
+ worldMinY: number,
588
+ worldMaxY: number,
589
+ meta: ReturnType<typeof getBlockMeta>
590
+ ): any | null => {
591
+ if (!wasm || !(wasm as any).generateGeometryFromParsedV16V17Multi) return null
592
+ const chunkCount = chunksToUse.length
593
+ if (chunkCount === 0) return null
594
+
595
+ // Determine which cache family owns all columns. Homogeneity is
596
+ // guaranteed by the server protocol version: v16 and v17 caches are
597
+ // never populated simultaneously within a session.
598
+ let family: 'v17' | 'v16' | null = null
599
+ for (let i = 0; i < chunkCount; i++) {
600
+ const key = rawCacheKey(chunksToUse[i].x, chunksToUse[i].z)
601
+ if (parsedV17Cache.has(key)) {
602
+ if (family === 'v16') return null
603
+ family = 'v17'
604
+ } else if (parsedV16Cache.has(key)) {
605
+ if (family === 'v17') return null
606
+ family = 'v16'
607
+ } else {
608
+ return null
609
+ }
610
+ }
611
+ if (!family) return null
612
+
613
+ const chunkDataList: Uint8Array[] = []
614
+ const biomesList: Int32Array[] = []
615
+ const skyLightList: Uint8Array[] = []
616
+ const blockLightList: Uint8Array[] = []
617
+ const numSectionsList = new Uint32Array(chunkCount)
618
+ const chunkXs = new Int32Array(chunkCount)
619
+ const chunkZs = new Int32Array(chunkCount)
620
+ const bitMapLoHi = new Uint32Array(chunkCount * 2)
621
+ let maxBitsPerBlock = 15
622
+
623
+ for (let i = 0; i < chunkCount; i++) {
624
+ const key = rawCacheKey(chunksToUse[i].x, chunksToUse[i].z)
625
+ if (family === 'v17') {
626
+ const entry = parsedV17Cache.get(key)!
627
+ chunkDataList.push(entry.chunkData)
628
+ biomesList.push(entry.biomes ?? new Int32Array(0))
629
+ numSectionsList[i] = entry.numSections
630
+ bitMapLoHi[i * 2] = entry.bitMapLoHi[0]
631
+ bitMapLoHi[i * 2 + 1] = entry.bitMapLoHi[1]
632
+ if (i === 0) maxBitsPerBlock = entry.maxBitsPerBlock
633
+ const light = updateLightV17Cache.get(key)
634
+ skyLightList.push(light?.skyLight ?? new Uint8Array(0))
635
+ blockLightList.push(light?.blockLight ?? new Uint8Array(0))
636
+ } else {
637
+ const entry = parsedV16Cache.get(key)!
638
+ chunkDataList.push(entry.chunkData)
639
+ biomesList.push(entry.biomes ?? new Int32Array(0))
640
+ numSectionsList[i] = 16
641
+ const bm = entry.bitMap >>> 0
642
+ bitMapLoHi[i * 2] = bm
643
+ bitMapLoHi[i * 2 + 1] = 0
644
+ const light = updateLightV16Cache.get(key)
645
+ skyLightList.push(light?.skyLight ?? new Uint8Array(0))
646
+ blockLightList.push(light?.blockLight ?? new Uint8Array(0))
647
+ }
648
+ chunkXs[i] = chunksToUse[i].x
649
+ chunkZs[i] = chunksToUse[i].z
650
+ }
651
+
652
+ const columnHeight = worldMaxY - worldMinY
653
+ try {
654
+ return (wasm as any).generateGeometryFromParsedV16V17Multi(
655
+ chunkDataList,
656
+ bitMapLoHi,
657
+ numSectionsList,
658
+ maxBitsPerBlock,
659
+ biomesList,
660
+ 1,
661
+ skyLightList,
662
+ blockLightList,
663
+ chunkXs,
664
+ chunkZs,
665
+ x, worldMinY, z, columnHeight,
666
+ worldMinY, worldMaxY,
667
+ worldMinY,
668
+ meta.invisibleBlocks,
669
+ meta.transparentBlocks,
670
+ meta.noAoBlocks,
671
+ meta.cullIdenticalBlocks,
672
+ meta.occludingBlocks,
673
+ config?.enableLighting !== false,
674
+ config?.smoothLighting !== false,
675
+ config?.skyLight || 15
676
+ )
677
+ } catch (err) {
678
+ console.warn('[WASM Mesher] generateGeometryFromParsedV16V17Multi failed:', err)
679
+ return null
680
+ }
681
+ }
682
+
522
683
  const handleMessage = async (data: any) => {
523
684
  const globalVar: any = globalThis
524
685
 
@@ -885,6 +1046,8 @@ function processColumnTick() {
885
1046
  let t1 = 0
886
1047
  let usedFusedPath = false
887
1048
 
1049
+ const meta = getBlockMeta(version)
1050
+
888
1051
  // ------------------------------------------------------------------
889
1052
  // Fused fast-path: for single-column meshing (no neighbours), parse
890
1053
  // and mesh in ONE WASM call so no typed arrays leave Rust memory.
@@ -894,7 +1057,6 @@ function processColumnTick() {
894
1057
  const rawEntry = rawMapChunkCache.get(rawCacheKey(x, z))
895
1058
  const v17Entry = parsedV17Cache.get(rawCacheKey(x, z))
896
1059
  const v16Entry = parsedV16Cache.get(rawCacheKey(x, z))
897
- const meta = getBlockMeta(version)
898
1060
 
899
1061
  if (rawEntry) {
900
1062
  wasmResult = meshColumnFromRawV18Plus(rawEntry, x, z, worldMinY, worldMaxY, meta)
@@ -922,7 +1084,23 @@ function processColumnTick() {
922
1084
  t1 = performance.now()
923
1085
  wasmPhase = t1 - t0
924
1086
  preTargetConvert = wasmPhase
925
- // prePhase stays 0 — no JS conversion loop ran.
1087
+ }
1088
+ }
1089
+
1090
+ // ------------------------------------------------------------------
1091
+ // Fused multi-column fast-path: parse+mesh all columns in one WASM
1092
+ // call with zero JS typed-array allocation.
1093
+ // Falls back to the old two-step path when the cache is incomplete
1094
+ // or any helper returns null.
1095
+ // ------------------------------------------------------------------
1096
+ if (!wasmResult && chunkCount > 1) {
1097
+ wasmResult = meshMultiColumnsFromRawV18Plus(chunksToUse, x, z, worldMinY, worldMaxY, meta)
1098
+ ?? meshMultiColumnsFromParsedV16V17(chunksToUse, x, z, worldMinY, worldMaxY, meta)
1099
+ if (wasmResult) {
1100
+ usedFusedPath = true
1101
+ t1 = performance.now()
1102
+ wasmPhase = t1 - t0
1103
+ preTargetConvert = wasmPhase
926
1104
  }
927
1105
  }
928
1106