minerender 2.1.0-alpha.33 → 2.1.0-alpha.35

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/bundle.js CHANGED
@@ -81217,32 +81217,42 @@ ${key}` : key;
81217
81217
  nextInstance() {
81218
81218
  return this.instanceable.nextInstance();
81219
81219
  }
81220
+ get activeInstanceable() {
81221
+ if (!this.instanceable.isInstanceActive(this.index, this)) throw new MineRenderError("Instance has been removed");
81222
+ return this.instanceable;
81223
+ }
81224
+ removeFromScene() {
81225
+ if (this.instanceable.isInstanceActive(this.index, this)) this.instanceable.removeInstanceAt(this.index);
81226
+ }
81227
+ dispose() {
81228
+ this.removeFromScene();
81229
+ }
81220
81230
  getMatrix(matrix) {
81221
- return this.instanceable.getMatrixAt(this.index, matrix);
81231
+ return this.activeInstanceable.getMatrixAt(this.index, matrix);
81222
81232
  }
81223
81233
  setMatrix(matrix) {
81224
- this.instanceable.setMatrixAt(this.index, matrix);
81234
+ this.activeInstanceable.setMatrixAt(this.index, matrix);
81225
81235
  }
81226
81236
  setPositionRotationScale(position, rotation, scale) {
81227
- this.instanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
81237
+ this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
81228
81238
  }
81229
81239
  setPosition(position) {
81230
- this.instanceable.setPositionAt(this.index, position);
81240
+ this.activeInstanceable.setPositionAt(this.index, position);
81231
81241
  }
81232
81242
  getPosition() {
81233
- return this.instanceable.getPositionAt(this.index);
81243
+ return this.activeInstanceable.getPositionAt(this.index);
81234
81244
  }
81235
81245
  setRotation(rotation) {
81236
- this.instanceable.setRotationAt(this.index, rotation);
81246
+ this.activeInstanceable.setRotationAt(this.index, rotation);
81237
81247
  }
81238
81248
  getRotation() {
81239
- return this.instanceable.getRotationAt(this.index);
81249
+ return this.activeInstanceable.getRotationAt(this.index);
81240
81250
  }
81241
81251
  setScale(scale) {
81242
- this.instanceable.setScaleAt(this.index, scale);
81252
+ this.activeInstanceable.setScaleAt(this.index, scale);
81243
81253
  }
81244
81254
  getScale() {
81245
- return this.instanceable.getScaleAt(this.index);
81255
+ return this.activeInstanceable.getScaleAt(this.index);
81246
81256
  }
81247
81257
  //TODO: support for custom methods e.g. setting block variants
81248
81258
  };
@@ -81260,6 +81270,8 @@ ${key}` : key;
81260
81270
  this.materialCallbacks = {};
81261
81271
  this._isInstanced = false;
81262
81272
  this._instanceCounter = 0;
81273
+ this.instanceReferences = /* @__PURE__ */ new Map();
81274
+ this.freeInstanceIndices = [];
81263
81275
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
81264
81276
  console.log("SceneObject options", this.options);
81265
81277
  }
@@ -81355,6 +81367,8 @@ ${key}` : key;
81355
81367
  createInstancedMesh(name2, geometry, material, count) {
81356
81368
  const mesh = new InstancedMesh(geometry, material, count);
81357
81369
  mesh.count = 0;
81370
+ this.instanceMesh = mesh;
81371
+ this._isInstanced = true;
81358
81372
  if (name2) {
81359
81373
  mesh.name = `mesh:${name2}`;
81360
81374
  }
@@ -81422,40 +81436,70 @@ ${key}` : key;
81422
81436
  return new InstanceReference(this, i4);
81423
81437
  }
81424
81438
  nextInstance() {
81425
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
81426
- const i4 = this._instanceCounter++;
81427
- this.setMatrixAt(i4, new Matrix4());
81428
- const mesh = this.children[0];
81429
- if (mesh && isInstancedMesh(mesh)) {
81430
- mesh.count = Math.min(this._instanceCounter, mesh.instanceMatrix.count);
81431
- }
81432
- console.debug(p9, "nextInstance " + i4);
81433
- if (i4 === this.options.maxInstanceCount) {
81434
- console.warn(p9, "Max instance count reached for " + this);
81435
- }
81436
- if (this.scene) {
81437
- this.scene.stats.instanceCount++;
81439
+ const mesh = this.instanceMesh;
81440
+ if (!mesh) throw new MineRenderError("Object is not instanced");
81441
+ const index = this.freeInstanceIndices.pop() ?? mesh.count;
81442
+ if (index >= mesh.instanceMatrix.count) this.growInstances(index + 1);
81443
+ const reference = this.constructInstanceReference(index);
81444
+ this.instanceReferences.set(index, reference);
81445
+ this._instanceCounter = this.instanceReferences.size;
81446
+ mesh.count = Math.max(mesh.count, index + 1);
81447
+ if (mesh.instanceColor) {
81448
+ mesh.setColorAt(index, new Color(16777215));
81449
+ mesh.instanceColor.needsUpdate = true;
81450
+ }
81451
+ if (this._scene) this._scene.stats.instanceCount++;
81452
+ this.setMatrixAt(index, new Matrix4());
81453
+ return reference;
81454
+ }
81455
+ isInstanceActive(index, reference) {
81456
+ return this.instanceReferences.get(index) === reference;
81457
+ }
81458
+ removeInstanceAt(index) {
81459
+ if (!this.instanceReferences.has(index)) return;
81460
+ const mesh = this.instanceMesh;
81461
+ this.setMatrixAt(index, new Matrix4().makeScale(0, 0, 0));
81462
+ this.instanceReferences.delete(index);
81463
+ this.freeInstanceIndices.push(index);
81464
+ this._instanceCounter = this.instanceReferences.size;
81465
+ while (mesh.count > 0 && !this.instanceReferences.has(mesh.count - 1)) mesh.count--;
81466
+ if (this._scene) this._scene.stats.instanceCount--;
81467
+ }
81468
+ growInstances(required) {
81469
+ const mesh = this.instanceMesh;
81470
+ const capacity = Math.max(required, mesh.instanceMatrix.count * 2);
81471
+ const grow = (attribute, fill) => {
81472
+ const array = new Float32Array(capacity * attribute.itemSize).fill(fill);
81473
+ array.set(attribute.array);
81474
+ return new InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
81475
+ };
81476
+ const matrix = grow(mesh.instanceMatrix, 0);
81477
+ const color2 = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;
81478
+ mesh.dispose();
81479
+ mesh.instanceMatrix = matrix;
81480
+ mesh.instanceColor = color2;
81481
+ }
81482
+ *activeInstanceIndices() {
81483
+ if (this.instanceMesh) {
81484
+ yield* this.instanceReferences.keys();
81485
+ } else {
81486
+ for (let i4 = 0; i4 < this.instanceCounter; i4++) yield i4;
81438
81487
  }
81439
- this.notifyDirty();
81440
- return this.constructInstanceReference(i4);
81441
81488
  }
81442
81489
  //</editor-fold>
81443
81490
  //<editor-fold desc="TRANSFORMATION">
81444
81491
  getMatrixAt(index, matrix = new Matrix4()) {
81445
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
81446
- const child = this.children[0];
81447
- if (child && isInstancedMesh(child)) {
81448
- child.getMatrixAt(index, matrix);
81449
- }
81492
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
81493
+ this.instanceMesh.getMatrixAt(index, matrix);
81450
81494
  return matrix;
81451
81495
  }
81452
81496
  setMatrixAt(index, matrix) {
81453
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
81454
- const child = this.children[0];
81455
- if (child && isInstancedMesh(child)) {
81456
- child.setMatrixAt(index, matrix);
81457
- child.instanceMatrix.needsUpdate = true;
81458
- }
81497
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
81498
+ const mesh = this.instanceMesh;
81499
+ mesh.setMatrixAt(index, matrix);
81500
+ mesh.instanceMatrix.needsUpdate = true;
81501
+ mesh.boundingBox = null;
81502
+ mesh.boundingSphere = null;
81459
81503
  this.notifyDirty();
81460
81504
  }
81461
81505
  setPositionRotationScaleAt(index, position, rotation, scale) {
@@ -81506,7 +81550,7 @@ ${key}` : key;
81506
81550
  }
81507
81551
  setPositionRotationScale(position, rotation, scale) {
81508
81552
  if (this.isInstanced) {
81509
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81553
+ for (const i4 of this.activeInstanceIndices()) {
81510
81554
  this.setPositionRotationScaleAt(i4, position, rotation, scale);
81511
81555
  }
81512
81556
  } else {
@@ -81524,7 +81568,7 @@ ${key}` : key;
81524
81568
  }
81525
81569
  setPosition(position) {
81526
81570
  if (this.isInstanced) {
81527
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81571
+ for (const i4 of this.activeInstanceIndices()) {
81528
81572
  this.setPositionRotationScaleAt(i4, position);
81529
81573
  }
81530
81574
  } else {
@@ -81534,14 +81578,14 @@ ${key}` : key;
81534
81578
  }
81535
81579
  getPosition() {
81536
81580
  if (this.isInstanced) {
81537
- return this.getPositionAt(0);
81581
+ return this.getPositionAt(this.instanceReferences.keys().next().value ?? 0);
81538
81582
  } else {
81539
81583
  return this.position;
81540
81584
  }
81541
81585
  }
81542
81586
  setRotation(rotation) {
81543
81587
  if (this.isInstanced) {
81544
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81588
+ for (const i4 of this.activeInstanceIndices()) {
81545
81589
  this.setPositionRotationScaleAt(i4, void 0, rotation);
81546
81590
  }
81547
81591
  } else {
@@ -81551,14 +81595,14 @@ ${key}` : key;
81551
81595
  }
81552
81596
  getRotation() {
81553
81597
  if (this.isInstanced) {
81554
- return this.getRotationAt(0);
81598
+ return this.getRotationAt(this.instanceReferences.keys().next().value ?? 0);
81555
81599
  } else {
81556
81600
  return this.rotation;
81557
81601
  }
81558
81602
  }
81559
81603
  setScale(scale) {
81560
81604
  if (this.isInstanced) {
81561
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81605
+ for (const i4 of this.activeInstanceIndices()) {
81562
81606
  this.setPositionRotationScaleAt(i4, void 0, void 0, scale);
81563
81607
  }
81564
81608
  } else {
@@ -81568,7 +81612,7 @@ ${key}` : key;
81568
81612
  }
81569
81613
  getScale() {
81570
81614
  if (this.isInstanced) {
81571
- return this.getScaleAt(0);
81615
+ return this.getScaleAt(this.instanceReferences.keys().next().value ?? 0);
81572
81616
  } else {
81573
81617
  return this.scale;
81574
81618
  }
@@ -81592,6 +81636,17 @@ ${key}` : key;
81592
81636
  this.notifyDirty();
81593
81637
  }
81594
81638
  disposeAndRemoveAllChildren() {
81639
+ if (this.instanceMesh) {
81640
+ if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
81641
+ this.instanceReferences.clear();
81642
+ this.freeInstanceIndices.length = 0;
81643
+ this._instanceCounter = 0;
81644
+ this.instanceMesh.count = 0;
81645
+ this.instanceMesh.dispose();
81646
+ this.instanceMesh.removeFromParent();
81647
+ this.instanceMesh = void 0;
81648
+ this._isInstanced = false;
81649
+ }
81595
81650
  while (this.children.length > 0) {
81596
81651
  let c4 = this.children[0];
81597
81652
  if (isDisposable(c4)) {
@@ -82905,10 +82960,6 @@ ${key}` : key;
82905
82960
  this.createMeshes();
82906
82961
  this.applyTextures();
82907
82962
  }
82908
- dispose() {
82909
- super.dispose();
82910
- this.atlas?.dispose();
82911
- }
82912
82963
  get textureAtlas() {
82913
82964
  return this.atlas;
82914
82965
  }
@@ -83073,18 +83124,21 @@ ${key}` : key;
83073
83124
  }
83074
83125
  }
83075
83126
  dispose() {
83127
+ this.clearModels();
83076
83128
  super.dispose();
83077
83129
  }
83078
83130
  removeFromScene() {
83079
- for (let model of this._models) {
83080
- if (isModelObject(model)) {
83081
- model.removeFromScene();
83082
- } else if (isInstanceReference(model)) {
83083
- model.setScale(new Vector3(0, 0, 0));
83084
- }
83085
- }
83131
+ this.clearModels();
83086
83132
  super.removeFromScene();
83087
83133
  }
83134
+ clearModels() {
83135
+ for (const model of this._models.splice(0)) {
83136
+ model.removeFromScene();
83137
+ if (!isInstanceReference(model)) model.dispose();
83138
+ }
83139
+ this._isInstanced = false;
83140
+ this._instanceCounter = 0;
83141
+ }
83088
83142
  get state() {
83089
83143
  return this._state;
83090
83144
  }
@@ -83133,22 +83187,7 @@ ${key}` : key;
83133
83187
  return out;
83134
83188
  }
83135
83189
  async recreateModels() {
83136
- const instanceInfo = [];
83137
- if (this.isInstanced) {
83138
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
83139
- instanceInfo[i4] = this.getMatrixAt(i4);
83140
- }
83141
- }
83142
- for (let model of this._models) {
83143
- if (isInstanceReference(model)) {
83144
- model.setScale(new Vector3(0, 0, 0));
83145
- } else {
83146
- model.dispose();
83147
- }
83148
- }
83149
- while (this._models.length > 0) {
83150
- this._models.shift();
83151
- }
83190
+ this.clearModels();
83152
83191
  const variantsToCreate = await this.mapStateToVariant(this.state);
83153
83192
  this._variants = variantsToCreate;
83154
83193
  for (let blockStateVariant of variantsToCreate) {
@@ -83199,6 +83238,7 @@ ${key}` : key;
83199
83238
  this._instanceCounter = 1;
83200
83239
  }
83201
83240
  obj.setRotation(rotation);
83241
+ obj.setPosition(this.position);
83202
83242
  return obj;
83203
83243
  }
83204
83244
  async resetState() {
@@ -87513,9 +87553,6 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87513
87553
  init_process2();
87514
87554
  var MineRenderWorld = class {
87515
87555
  constructor(scene) {
87516
- this._size = 4;
87517
- //TODO: expandable
87518
- this._blockSize = this._size * 16;
87519
87556
  this._chunks = /* @__PURE__ */ new Map();
87520
87557
  this.scene = scene;
87521
87558
  }
@@ -87526,12 +87563,8 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87526
87563
  if (isTripleArray(posOrX)) {
87527
87564
  return this.getBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]));
87528
87565
  }
87529
- const chunk = this.getChunkAt(posOrX);
87530
- if (typeof chunk === "undefined") {
87531
- return void 0;
87532
- }
87533
87566
  this.validatePosBounds(posOrX);
87534
- return chunk.getBlockAt(posOrX);
87567
+ return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
87535
87568
  }
87536
87569
  async setBlockAt(posOrX, yOrBlock, z4, block) {
87537
87570
  if (typeof posOrX == "number") {
@@ -87541,8 +87574,9 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87541
87574
  return this.setBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
87542
87575
  }
87543
87576
  this.validatePosBounds(posOrX);
87544
- const chunk = this.getOrCreateChunkAt(posOrX);
87545
- return chunk.setBlockAt(posOrX, yOrBlock);
87577
+ const value = yOrBlock;
87578
+ const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
87579
+ return chunk?.setBlockAt(posOrX, value);
87546
87580
  }
87547
87581
  async placeMultiBlock(multiblock, useBatches = true, executor = new BatchedExecutor()) {
87548
87582
  const keys = new Set(multiblock.blocks.map((block) => AssetKey.parse("blockstates", block.type)));
@@ -87563,10 +87597,8 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87563
87597
  }
87564
87598
  }
87565
87599
  async clear() {
87566
- console.log("CHUNKS", this._chunks);
87567
- for (let chunk of this._chunks.values()) {
87568
- console.log("dispose chunk", chunk);
87569
- await chunk?.dispose();
87600
+ for (const chunk of this._chunks.values()) {
87601
+ await chunk.dispose();
87570
87602
  }
87571
87603
  this._chunks.clear();
87572
87604
  }
@@ -87580,8 +87612,7 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87580
87612
  return chunk;
87581
87613
  }
87582
87614
  getChunkAt(pos) {
87583
- const index = this.worldPosToChunkIndex(pos);
87584
- return this._chunks[index];
87615
+ return this._chunks.get(this.worldPosToChunkKey(pos));
87585
87616
  }
87586
87617
  static worldToScenePosition(pos) {
87587
87618
  return new Vector3(
@@ -87597,12 +87628,6 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87597
87628
  pos.z / 16
87598
87629
  );
87599
87630
  }
87600
- worldPosToChunkIndex(pos) {
87601
- const chunkX = Math.floor(pos.x / 16);
87602
- const chunkY = Math.floor(pos.y / 16);
87603
- const chunkZ = Math.floor(pos.z / 16);
87604
- return chunkZ * this._size * this._size + chunkY * this._size + chunkX;
87605
- }
87606
87631
  worldPosToChunkKey(pos) {
87607
87632
  const chunkX = Math.floor(pos.x / 16);
87608
87633
  const chunkY = Math.floor(pos.y / 16);
@@ -87610,12 +87635,9 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87610
87635
  return `${chunkX}_${chunkY}_${chunkZ}`;
87611
87636
  }
87612
87637
  validatePosBounds(pos) {
87613
- if (pos.x < 0) throw new Error("x<0");
87614
- if (pos.y < 0) throw new Error("y<0");
87615
- if (pos.z < 0) throw new Error("z<0");
87616
- if (pos.x > this._blockSize) throw new Error("x>" + this._blockSize);
87617
- if (pos.y > this._blockSize) throw new Error("y>" + this._blockSize);
87618
- if (pos.z > this._blockSize) throw new Error("z>" + this._blockSize);
87638
+ if (![pos.x, pos.y, pos.z].every(Number.isInteger)) {
87639
+ throw new RangeError("Block coordinates must be integers");
87640
+ }
87619
87641
  }
87620
87642
  };
87621
87643
 
@@ -87628,16 +87650,6 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87628
87650
  this.x = x4;
87629
87651
  this.y = y5;
87630
87652
  this.z = z4;
87631
- let anchor = new Object3D();
87632
- this._anchor = anchor;
87633
- scene.add(anchor);
87634
- anchor.position.set(this.x * 256 + 128 - 8, this.y * 256 + 128 - 8, this.z * 256 + 128 - 8);
87635
- addBox3WireframeToObject(
87636
- new Box3(new Vector3(0, 0, 0), new Vector3(256, 256, 256)),
87637
- anchor,
87638
- 16776960,
87639
- 4
87640
- );
87641
87653
  }
87642
87654
  getBlockAt(posOrX, y5, z4) {
87643
87655
  if (typeof posOrX == "number") {
@@ -87663,7 +87675,7 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87663
87675
  return this.setBlockInChunkAt(pos, block, worldPos);
87664
87676
  }
87665
87677
  /**
87666
- * Set block at a _chunk_ position (0-16)
87678
+ * Set a block at integer chunk-local coordinates from 0 to 15.
87667
87679
  */
87668
87680
  async setBlockInChunkAt(pos, block, worldPos) {
87669
87681
  if (typeof worldPos === "undefined") {
@@ -87676,15 +87688,13 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87676
87688
  current.object.removeFromScene();
87677
87689
  delete this._blocks[index];
87678
87690
  }
87679
- if (typeof block === "undefined" || typeof block.type === "undefined" || block.type === "air") return void 0;
87691
+ if (!block || _Chunk.isAir(block)) return void 0;
87680
87692
  const blockState = await BlockStates.get(AssetKey.parse("blockstates", block.type));
87681
87693
  if (blockState) {
87682
87694
  const blockObject = await this.scene.addBlock(blockState, {
87683
87695
  mergeMeshes: true,
87684
87696
  instanceMeshes: true,
87685
- wireframe: true,
87686
87697
  maxInstanceCount: 2e3
87687
- //TODO: setting this to high kills FPS; increase on demand somehow?
87688
87698
  });
87689
87699
  if (block.properties) {
87690
87700
  await blockObject.setState(block.properties);
@@ -87700,23 +87710,21 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87700
87710
  return void 0;
87701
87711
  }
87702
87712
  async clear() {
87703
- let promises = [];
87704
- let pos = new Vector3();
87705
- for (let x4 = 0; x4 < 16; x4++) {
87706
- for (let z4 = 0; z4 < 16; z4++) {
87707
- for (let y5 = 0; y5 < 16; y5++) {
87708
- promises.push(this.setBlockInChunkAt(pos.set(x4, y5, z4), void 0));
87709
- }
87710
- }
87711
- }
87712
- return Promise.all(promises).then((ignored) => {
87713
- });
87713
+ this._blocks.forEach((block) => block.object.removeFromScene());
87714
+ this._blocks.length = 0;
87714
87715
  }
87715
87716
  async dispose() {
87716
87717
  await this.clear();
87717
- this.scene.remove(this._anchor);
87718
+ }
87719
+ static isAir(block) {
87720
+ if (typeof block === "undefined" || typeof block.type === "undefined") return true;
87721
+ const key = AssetKey.parse("blockstates", block.type);
87722
+ return key.namespace === "minecraft" && !key.type && ["air", "cave_air", "void_air"].includes(key.path);
87718
87723
  }
87719
87724
  static chunkPosToBlockIndex(pos) {
87725
+ if ([pos.x, pos.y, pos.z].some((value) => !Number.isInteger(value) || value < 0 || value >= 16)) {
87726
+ throw new RangeError("Block coordinates must be integers from 0 to 15 within a chunk");
87727
+ }
87720
87728
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
87721
87729
  }
87722
87730
  worldPosToChunkPos(pos) {