minerender 2.1.0-alpha.62 → 2.1.0-alpha.64

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.
@@ -3545,6 +3545,9 @@ var init_InstanceReference = __esm({
3545
3545
  setMatrix(matrix) {
3546
3546
  this.activeInstanceable.setMatrixAt(this.index, matrix);
3547
3547
  }
3548
+ setVisible(visible) {
3549
+ this.activeInstanceable.setInstanceVisibleAt(this.index, visible);
3550
+ }
3548
3551
  setPositionRotationScale(position, rotation, scale) {
3549
3552
  this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
3550
3553
  }
@@ -3599,6 +3602,7 @@ var init_SceneObject = __esm({
3599
3602
  this._instanceCounter = 0;
3600
3603
  this.instanceReferences = /* @__PURE__ */ new Map();
3601
3604
  this.freeInstanceIndices = [];
3605
+ this.hiddenInstanceMatrices = /* @__PURE__ */ new Map();
3602
3606
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
3603
3607
  console.log("SceneObject options", this.options);
3604
3608
  }
@@ -3801,6 +3805,7 @@ var init_SceneObject = __esm({
3801
3805
  removeInstanceAt(index) {
3802
3806
  if (!this.instanceReferences.has(index)) return;
3803
3807
  const mesh = this.instanceMesh;
3808
+ this.hiddenInstanceMatrices.delete(index);
3804
3809
  this.setMatrixAt(index, new Matrix44().makeScale(0, 0, 0));
3805
3810
  this.instanceReferences.delete(index);
3806
3811
  this.freeInstanceIndices.push(index);
@@ -3833,18 +3838,46 @@ var init_SceneObject = __esm({
3833
3838
  //<editor-fold desc="TRANSFORMATION">
3834
3839
  getMatrixAt(index, matrix = new Matrix44()) {
3835
3840
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3841
+ const hidden = this.hiddenInstanceMatrices.get(index);
3842
+ if (hidden) {
3843
+ return matrix.copy(hidden);
3844
+ }
3836
3845
  this.instanceMesh.getMatrixAt(index, matrix);
3837
3846
  return matrix;
3838
3847
  }
3839
3848
  setMatrixAt(index, matrix) {
3840
3849
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3841
3850
  const mesh = this.instanceMesh;
3842
- mesh.setMatrixAt(index, matrix);
3851
+ const hidden = this.hiddenInstanceMatrices.get(index);
3852
+ if (hidden) {
3853
+ hidden.copy(matrix);
3854
+ }
3855
+ mesh.setMatrixAt(index, hidden ? new Matrix44().makeScale(0, 0, 0) : matrix);
3843
3856
  mesh.instanceMatrix.needsUpdate = true;
3844
3857
  mesh.boundingBox = null;
3845
3858
  mesh.boundingSphere = null;
3846
3859
  this.notifyDirty();
3847
3860
  }
3861
+ setInstanceVisibleAt(index, visible) {
3862
+ if (!this.instanceReferences.has(index)) {
3863
+ throw new MineRenderError("Instance is not active");
3864
+ }
3865
+ const hidden = this.hiddenInstanceMatrices.get(index);
3866
+ if (visible) {
3867
+ if (!hidden) {
3868
+ return;
3869
+ }
3870
+ this.hiddenInstanceMatrices.delete(index);
3871
+ this.setMatrixAt(index, hidden);
3872
+ } else {
3873
+ if (hidden) {
3874
+ return;
3875
+ }
3876
+ const matrix = this.getMatrixAt(index);
3877
+ this.hiddenInstanceMatrices.set(index, matrix);
3878
+ this.setMatrixAt(index, matrix);
3879
+ }
3880
+ }
3848
3881
  setPositionRotationScaleAt(index, position, rotation, scale) {
3849
3882
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3850
3883
  const oldPosition = new Vector36();
@@ -3984,6 +4017,7 @@ var init_SceneObject = __esm({
3984
4017
  if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
3985
4018
  this.instanceReferences.clear();
3986
4019
  this.freeInstanceIndices.length = 0;
4020
+ this.hiddenInstanceMatrices.clear();
3987
4021
  this._instanceCounter = 0;
3988
4022
  this.instanceMesh.count = 0;
3989
4023
  this.instanceMesh.dispose();
@@ -9193,6 +9227,21 @@ var BlockObject = class _BlockObject extends SceneObject {
9193
9227
  get blockEntities() {
9194
9228
  return this._entities;
9195
9229
  }
9230
+ /** Sets visibility for this block's model instances and block entities. */
9231
+ setVisible(visible) {
9232
+ this.visible = visible;
9233
+ for (const model of this._models) {
9234
+ if (isInstanceReference(model)) {
9235
+ model.setVisible(visible);
9236
+ } else {
9237
+ model.visible = visible;
9238
+ }
9239
+ }
9240
+ for (const entity of this._entities) {
9241
+ entity.visible = visible;
9242
+ }
9243
+ this.notifyDirty();
9244
+ }
9196
9245
  /**
9197
9246
  * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
9198
9247
  * when the block is not listed or one of its models cannot be loaded.
@@ -9226,6 +9275,7 @@ var BlockObject = class _BlockObject extends SceneObject {
9226
9275
  BlockEntities.matrix(resolved, this._entityPlacement);
9227
9276
  this._entities = created;
9228
9277
  this.placeEntities();
9278
+ this.setVisible(this.visible);
9229
9279
  return true;
9230
9280
  }
9231
9281
  placeEntities() {
@@ -9235,6 +9285,9 @@ var BlockObject = class _BlockObject extends SceneObject {
9235
9285
  }
9236
9286
  }
9237
9287
  get isOccluding() {
9288
+ if (!this.visible) {
9289
+ return false;
9290
+ }
9238
9291
  return this._models.some((model) => {
9239
9292
  const object = isInstanceReference(model) ? model.instanceable : model;
9240
9293
  return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;
@@ -9290,6 +9343,9 @@ var BlockObject = class _BlockObject extends SceneObject {
9290
9343
  this._models = replacements;
9291
9344
  this._cullMask = worldMask;
9292
9345
  this.removeModels(previous.filter((model) => !replacements.includes(model)));
9346
+ if (!this.visible) {
9347
+ this.setVisible(false);
9348
+ }
9293
9349
  this.notifyDirty();
9294
9350
  }
9295
9351
  get state() {
@@ -9325,6 +9381,9 @@ var BlockObject = class _BlockObject extends SceneObject {
9325
9381
  this._isInstanced ||= isInstanceReference(replacement);
9326
9382
  this._instanceCounter = this._isInstanced ? 1 : 0;
9327
9383
  if (previous) this.removeModels([previous]);
9384
+ if (!this.visible) {
9385
+ this.setVisible(false);
9386
+ }
9328
9387
  this.notifyDirty();
9329
9388
  }
9330
9389
  nextInstance() {
@@ -9353,6 +9412,7 @@ var BlockObject = class _BlockObject extends SceneObject {
9353
9412
  this._models.push(await this.createVariant(blockStateVariant));
9354
9413
  }
9355
9414
  await this.updateFluid(this._fluidSampler);
9415
+ this.setVisible(this.visible);
9356
9416
  }
9357
9417
  async hasGeometry(variant) {
9358
9418
  const modelKey = AssetKey.parse("models", variant.model);
@@ -11186,7 +11246,11 @@ var legacyBlocks_default = {
11186
11246
 
11187
11247
  // src/model/multiblock/SchematicParser.ts
11188
11248
  var SchematicParser = class {
11189
- static async parse(nbt) {
11249
+ /**
11250
+ * Parses a legacy schematic using custom mappings before the bundled defaults.
11251
+ * Keys are `id:metadata`; values are block states such as `minecraft:oak_log[axis=x]`.
11252
+ */
11253
+ static async parse(nbt, customMappings = {}) {
11190
11254
  const tags = nbt.value;
11191
11255
  if (tags.Materials?.type !== "string" || tags.Materials.value !== "Alpha") {
11192
11256
  throw new MineRenderError("Schematic Materials must be Alpha");
@@ -11228,15 +11292,16 @@ var SchematicParser = class {
11228
11292
  const high = packed >> (index & 1) * 4 & 15;
11229
11293
  const id = high << 8 | ids.value[index] & 255;
11230
11294
  const metadata = data.value[index] & 255;
11231
- const mapped = mapping[`${id}:${metadata}`];
11295
+ const key = `${id}:${metadata}`;
11296
+ const mapped = customMappings[key] ?? mapping[key];
11232
11297
  if (!mapped) throw new MineRenderError(`Unsupported legacy block ${id}:${metadata} at schematic index ${index}`);
11233
11298
  const [type, state] = mapped.split("[");
11234
11299
  if (type === "minecraft:air") continue;
11235
11300
  const properties = {};
11236
11301
  if (state) {
11237
11302
  for (const property of state.slice(0, -1).split(",")) {
11238
- const [key, value] = property.split("=");
11239
- properties[key] = value;
11303
+ const [key2, value] = property.split("=");
11304
+ properties[key2] = value;
11240
11305
  }
11241
11306
  }
11242
11307
  blocks.push({
@@ -14142,6 +14207,16 @@ var MineRenderWorld = class {
14142
14207
  const chunk = Chunk.isAir(value) ? this.getChunkAt(pos) : this.getOrCreateChunkAt(pos);
14143
14208
  return chunk?.setBlockInChunkAt(chunk.worldPosToChunkPos(pos), value, pos, onBlocksChanged);
14144
14209
  }
14210
+ async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
14211
+ if (typeof posOrX === "number") {
14212
+ return this.setBlockVisibleAt(new Vector316(posOrX, yOrVisible, z), visible);
14213
+ }
14214
+ if (isTripleArray(posOrX)) {
14215
+ return this.setBlockVisibleAt(new Vector316(...posOrX), yOrVisible);
14216
+ }
14217
+ this.validatePosBounds(posOrX);
14218
+ await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
14219
+ }
14145
14220
  async placeMultiBlock(multiblock, useBatches = true, executor) {
14146
14221
  const changes = /* @__PURE__ */ new Map();
14147
14222
  try {
@@ -14257,12 +14332,14 @@ var MineRenderWorld = class {
14257
14332
  if (!chunk) continue;
14258
14333
  changed.add(chunk);
14259
14334
  const block = chunk.getBlockAt(pos);
14260
- if (!block) continue;
14335
+ if (!block || !chunk.isBlockVisibleAt(pos)) {
14336
+ continue;
14337
+ }
14261
14338
  if (block.object?.fluidKind) {
14262
14339
  await block.object.updateFluid((x, y, z) => {
14263
14340
  const neighbor = pos.clone().add(new Vector316(x, y, z));
14264
14341
  const section = this.getChunkAt(neighbor);
14265
- const object = section?.getBlockAt(neighbor)?.object;
14342
+ const object = section?.isBlockVisibleAt(neighbor) ? section.getBlockAt(neighbor)?.object : void 0;
14266
14343
  return {
14267
14344
  fluid: object?.fluidKind,
14268
14345
  level: object?.fluidLevel,
@@ -14449,6 +14526,7 @@ var Chunk = class _Chunk {
14449
14526
  this.data = new ChunkData();
14450
14527
  this.renderedBlocks = /* @__PURE__ */ new Map();
14451
14528
  this.sectionBlocks = /* @__PURE__ */ new Map();
14529
+ this.hiddenBlocks = /* @__PURE__ */ new Set();
14452
14530
  this.meshDirty = false;
14453
14531
  this.scene = scene;
14454
14532
  this.x = x;
@@ -14486,6 +14564,7 @@ var Chunk = class _Chunk {
14486
14564
  worldPos = this.chunkPosToWorldPos(pos);
14487
14565
  }
14488
14566
  const index = _Chunk.chunkPosToBlockIndex(pos);
14567
+ this.hiddenBlocks.delete(index);
14489
14568
  this.data.set(index, block);
14490
14569
  const readBlock = this.data.snapshot(index);
14491
14570
  this.renderedBlocks.get(index)?.object?.removeFromScene();
@@ -14527,9 +14606,31 @@ var Chunk = class _Chunk {
14527
14606
  await onBlocksChanged?.([worldPos]);
14528
14607
  }
14529
14608
  }
14609
+ async setBlockVisibleAt(pos, visible) {
14610
+ const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14611
+ const block = this.renderedBlocks.get(index);
14612
+ if (!block || visible === !this.hiddenBlocks.has(index)) {
14613
+ return;
14614
+ }
14615
+ if (visible) {
14616
+ this.hiddenBlocks.delete(index);
14617
+ } else {
14618
+ this.hiddenBlocks.add(index);
14619
+ }
14620
+ block.object?.setVisible(visible);
14621
+ if (this.sectionBlocks.has(index)) {
14622
+ this.meshDirty = true;
14623
+ }
14624
+ this.scene.dirty = true;
14625
+ await this.onBlocksChanged?.([pos]);
14626
+ }
14627
+ isBlockVisibleAt(pos) {
14628
+ const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14629
+ return this.renderedBlocks.has(index) && !this.hiddenBlocks.has(index);
14630
+ }
14530
14631
  isOccludingAt(pos) {
14531
14632
  const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14532
- return this.sectionBlocks.has(index) || (this.renderedBlocks.get(index)?.object?.isOccluding ?? false);
14633
+ return !this.hiddenBlocks.has(index) && (this.sectionBlocks.has(index) || (this.renderedBlocks.get(index)?.object?.isOccluding ?? false));
14533
14634
  }
14534
14635
  async setCullMaskAt(pos, mask) {
14535
14636
  const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
@@ -14545,7 +14646,10 @@ var Chunk = class _Chunk {
14545
14646
  }
14546
14647
  rebuildSectionMesh() {
14547
14648
  if (!this.meshDirty) return;
14548
- const next = this.sectionBlocks.size ? SectionMesh.build([...this.sectionBlocks.values()], this.sectionModels.maxAtlasSize) : void 0;
14649
+ const next = this.sectionBlocks.size ? SectionMesh.build(
14650
+ [...this.sectionBlocks.values()].filter((entry) => !this.hiddenBlocks.has(entry.index)),
14651
+ this.sectionModels.maxAtlasSize
14652
+ ) : void 0;
14549
14653
  this.sectionMesh?.dispose();
14550
14654
  this.sectionMesh = next;
14551
14655
  if (next) {
@@ -14565,6 +14669,7 @@ var Chunk = class _Chunk {
14565
14669
  this.sectionMesh = void 0;
14566
14670
  this.meshDirty = false;
14567
14671
  this.renderedBlocks.clear();
14672
+ this.hiddenBlocks.clear();
14568
14673
  this.data.clear();
14569
14674
  await onBlocksChanged?.(positions);
14570
14675
  }