minerender 2.1.0-alpha.53 → 2.1.0-alpha.55

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.
@@ -257,7 +257,9 @@ var init_Caching = __esm({
257
257
  this.defaultBlockStatesCache,
258
258
  this.blockTintCache,
259
259
  this.entityModelCache,
260
- this.entityTextureCache
260
+ this.entityTextureCache,
261
+ this.entityAnimationCache,
262
+ this.blockEntityIndexCache
261
263
  ];
262
264
  }
263
265
  static clear() {
@@ -302,6 +304,8 @@ var init_Caching = __esm({
302
304
  _Caching.blockTintCache = _Caching.createAssetCache();
303
305
  _Caching.entityModelCache = _Caching.createAssetCache();
304
306
  _Caching.entityTextureCache = _Caching.createAssetCache();
307
+ _Caching.entityAnimationCache = _Caching.createAssetCache();
308
+ _Caching.blockEntityIndexCache = _Caching.createAssetCache();
305
309
  Caching = _Caching;
306
310
  }
307
311
  });
@@ -839,6 +843,71 @@ var init_Materials = __esm({
839
843
  alphaTest: 0.5
840
844
  });
841
845
  }
846
+ /** Whether vanilla's render type for the mode culls back faces. */
847
+ static entityModeCulls(mode = "cutout") {
848
+ return mode === "cutout_cull" || mode === "solid" || mode === "eyes" || mode === "water_mask";
849
+ }
850
+ /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */
851
+ static entityModeScroll(mode = "cutout") {
852
+ if (mode === "energy_swirl") return [0.01, 0.01];
853
+ if (mode === "breeze_wind") return [0.02, 0];
854
+ return void 0;
855
+ }
856
+ /**
857
+ * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes
858
+ * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides
859
+ * whether the geometry gets inward faces.
860
+ */
861
+ static createEntityCanvasMaterial(canvas, mode = "cutout", tint) {
862
+ const material = _Materials.createBasicCanvasMaterial(canvas);
863
+ switch (mode) {
864
+ case "cutout":
865
+ case "cutout_cull":
866
+ break;
867
+ case "cutout_z_offset":
868
+ material.polygonOffset = true;
869
+ material.polygonOffsetFactor = -1;
870
+ material.polygonOffsetUnits = -10;
871
+ break;
872
+ case "solid":
873
+ material.alphaTest = 0;
874
+ break;
875
+ case "translucent":
876
+ case "breeze_wind":
877
+ material.transparent = true;
878
+ material.alphaTest = 0.1;
879
+ break;
880
+ case "translucent_emissive":
881
+ material.transparent = true;
882
+ material.alphaTest = 0.1;
883
+ material.depthWrite = false;
884
+ break;
885
+ case "eyes":
886
+ material.transparent = true;
887
+ material.alphaTest = 0;
888
+ material.depthWrite = false;
889
+ break;
890
+ case "energy_swirl":
891
+ material.transparent = true;
892
+ material.alphaTest = 0.1;
893
+ material.blending = import_three5.CustomBlending;
894
+ material.blendSrc = import_three5.OneFactor;
895
+ material.blendDst = import_three5.OneFactor;
896
+ material.blendSrcAlpha = import_three5.ZeroFactor;
897
+ material.blendDstAlpha = import_three5.OneFactor;
898
+ material.color.set(8421504);
899
+ break;
900
+ case "water_mask":
901
+ material.alphaTest = 0;
902
+ material.colorWrite = false;
903
+ break;
904
+ }
905
+ if (_Materials.entityModeScroll(mode)) {
906
+ material.map.wrapS = material.map.wrapT = import_three5.RepeatWrapping;
907
+ }
908
+ if (tint !== void 0) material.color.multiply(new import_three5.Color(tint));
909
+ return material;
910
+ }
842
911
  static createGuiCanvasMaterial(canvas) {
843
912
  const material = new import_three5.MeshBasicMaterial({
844
913
  map: Textures.createCanvasTexture(canvas),
@@ -3019,10 +3088,10 @@ var init_InstanceReference = __esm({
3019
3088
  function isSceneObject(obj) {
3020
3089
  return obj.isSceneObject;
3021
3090
  }
3022
- var import_three10, import_ts_deepmerge3, p6, _SceneObject, SceneObject;
3091
+ var import_three11, import_ts_deepmerge3, p6, _SceneObject, SceneObject;
3023
3092
  var init_SceneObject = __esm({
3024
3093
  "src/renderer/SceneObject.ts"() {
3025
- import_three10 = require("three");
3094
+ import_three11 = require("three");
3026
3095
  init_Geometries();
3027
3096
  init_UVMapper();
3028
3097
  init_Axis();
@@ -3034,7 +3103,7 @@ var init_SceneObject = __esm({
3034
3103
  import_ts_deepmerge3 = __toESM(require_dist());
3035
3104
  init_log();
3036
3105
  p6 = prefix("SceneObject");
3037
- _SceneObject = class _SceneObject extends import_three10.Object3D {
3106
+ _SceneObject = class _SceneObject extends import_three11.Object3D {
3038
3107
  constructor(options) {
3039
3108
  super();
3040
3109
  this.isSceneObject = true;
@@ -3078,7 +3147,7 @@ var init_SceneObject = __esm({
3078
3147
  return group;
3079
3148
  }
3080
3149
  createGroup(name, x = 0, y = 0, z = 0, offsetAxis, offset = 0) {
3081
- const obj = new import_three10.Object3D();
3150
+ const obj = new import_three11.Object3D();
3082
3151
  if (name) {
3083
3152
  obj.name = `group:${name}`;
3084
3153
  }
@@ -3128,7 +3197,7 @@ var init_SceneObject = __esm({
3128
3197
  return mesh;
3129
3198
  }
3130
3199
  createMesh(name, geometry, material, offsetAxis, offset = 0) {
3131
- const mesh = new import_three10.Mesh(geometry, material);
3200
+ const mesh = new import_three11.Mesh(geometry, material);
3132
3201
  if (name) {
3133
3202
  mesh.name = `mesh:${name}`;
3134
3203
  }
@@ -3140,7 +3209,7 @@ var init_SceneObject = __esm({
3140
3209
  return mesh;
3141
3210
  }
3142
3211
  createInstancedMesh(name, geometry, material, count) {
3143
- const mesh = new import_three10.InstancedMesh(geometry, material, count);
3212
+ const mesh = new import_three11.InstancedMesh(geometry, material, count);
3144
3213
  mesh.count = 0;
3145
3214
  this.instanceMesh = mesh;
3146
3215
  this._isInstanced = true;
@@ -3220,11 +3289,11 @@ var init_SceneObject = __esm({
3220
3289
  this._instanceCounter = this.instanceReferences.size;
3221
3290
  mesh.count = Math.max(mesh.count, index + 1);
3222
3291
  if (mesh.instanceColor) {
3223
- mesh.setColorAt(index, new import_three10.Color(16777215));
3292
+ mesh.setColorAt(index, new import_three11.Color(16777215));
3224
3293
  mesh.instanceColor.needsUpdate = true;
3225
3294
  }
3226
3295
  if (this._scene) this._scene.stats.instanceCount++;
3227
- this.setMatrixAt(index, new import_three10.Matrix4());
3296
+ this.setMatrixAt(index, new import_three11.Matrix4());
3228
3297
  return reference;
3229
3298
  }
3230
3299
  /** Returns the live reference for a raycast hit on this object's instance mesh. */
@@ -3237,7 +3306,7 @@ var init_SceneObject = __esm({
3237
3306
  removeInstanceAt(index) {
3238
3307
  if (!this.instanceReferences.has(index)) return;
3239
3308
  const mesh = this.instanceMesh;
3240
- this.setMatrixAt(index, new import_three10.Matrix4().makeScale(0, 0, 0));
3309
+ this.setMatrixAt(index, new import_three11.Matrix4().makeScale(0, 0, 0));
3241
3310
  this.instanceReferences.delete(index);
3242
3311
  this.freeInstanceIndices.push(index);
3243
3312
  this._instanceCounter = this.instanceReferences.size;
@@ -3250,7 +3319,7 @@ var init_SceneObject = __esm({
3250
3319
  const grow = (attribute, fill) => {
3251
3320
  const array = new Float32Array(capacity * attribute.itemSize).fill(fill);
3252
3321
  array.set(attribute.array);
3253
- return new import_three10.InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
3322
+ return new import_three11.InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
3254
3323
  };
3255
3324
  const matrix = grow(mesh.instanceMatrix, 0);
3256
3325
  const color = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;
@@ -3267,7 +3336,7 @@ var init_SceneObject = __esm({
3267
3336
  }
3268
3337
  //</editor-fold>
3269
3338
  //<editor-fold desc="TRANSFORMATION">
3270
- getMatrixAt(index, matrix = new import_three10.Matrix4()) {
3339
+ getMatrixAt(index, matrix = new import_three11.Matrix4()) {
3271
3340
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3272
3341
  this.instanceMesh.getMatrixAt(index, matrix);
3273
3342
  return matrix;
@@ -3283,16 +3352,16 @@ var init_SceneObject = __esm({
3283
3352
  }
3284
3353
  setPositionRotationScaleAt(index, position, rotation, scale) {
3285
3354
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3286
- const oldPosition = new import_three10.Vector3();
3287
- const oldRotation = new import_three10.Quaternion();
3288
- const oldScale = new import_three10.Vector3();
3289
- const matrix = new import_three10.Matrix4();
3355
+ const oldPosition = new import_three11.Vector3();
3356
+ const oldRotation = new import_three11.Quaternion();
3357
+ const oldScale = new import_three11.Vector3();
3358
+ const matrix = new import_three11.Matrix4();
3290
3359
  if (!scale || !rotation || !position) {
3291
3360
  this.getMatrixAt(index, matrix).decompose(oldPosition, oldRotation, oldScale);
3292
3361
  }
3293
3362
  matrix.compose(
3294
3363
  position ? position : oldPosition,
3295
- rotation ? new import_three10.Quaternion().setFromEuler(rotation) : oldRotation,
3364
+ rotation ? new import_three11.Quaternion().setFromEuler(rotation) : oldRotation,
3296
3365
  scale ? scale : oldScale
3297
3366
  );
3298
3367
  this.setMatrixAt(index, matrix);
@@ -3301,7 +3370,7 @@ var init_SceneObject = __esm({
3301
3370
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3302
3371
  this.setPositionRotationScaleAt(index, position);
3303
3372
  }
3304
- getPositionAt(index, vector = new import_three10.Vector3()) {
3373
+ getPositionAt(index, vector = new import_three11.Vector3()) {
3305
3374
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3306
3375
  const matrix = this.getMatrixAt(index);
3307
3376
  vector.setFromMatrixPosition(matrix);
@@ -3311,17 +3380,17 @@ var init_SceneObject = __esm({
3311
3380
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3312
3381
  this.setPositionRotationScaleAt(index, void 0, rotation, void 0);
3313
3382
  }
3314
- getRotationAt(index, euler = new import_three10.Euler()) {
3383
+ getRotationAt(index, euler = new import_three11.Euler()) {
3315
3384
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3316
- const rotation = new import_three10.Quaternion();
3317
- this.getMatrixAt(index).decompose(new import_three10.Vector3(), rotation, new import_three10.Vector3());
3385
+ const rotation = new import_three11.Quaternion();
3386
+ this.getMatrixAt(index).decompose(new import_three11.Vector3(), rotation, new import_three11.Vector3());
3318
3387
  return euler.setFromQuaternion(rotation);
3319
3388
  }
3320
3389
  setScaleAt(index, scale) {
3321
3390
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3322
3391
  this.setPositionRotationScaleAt(index, void 0, void 0, scale);
3323
3392
  }
3324
- getScaleAt(index, vector = new import_three10.Vector3()) {
3393
+ getScaleAt(index, vector = new import_three11.Vector3()) {
3325
3394
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3326
3395
  const matrix = this.getMatrixAt(index);
3327
3396
  vector.setFromMatrixScale(matrix);
@@ -3464,7 +3533,7 @@ function mergeBufferGeometries(geometries, useGroups = false) {
3464
3533
  const attributes = {};
3465
3534
  const morphAttributes = {};
3466
3535
  const morphTargetsRelative = geometries[0].morphTargetsRelative;
3467
- const mergedGeometry = new import_three19.BufferGeometry();
3536
+ const mergedGeometry = new import_three20.BufferGeometry();
3468
3537
  let offset = 0;
3469
3538
  for (let i = 0; i < geometries.length; ++i) {
3470
3539
  const geometry = geometries[i];
@@ -3588,7 +3657,7 @@ function mergeBufferAttributes(attributes) {
3588
3657
  array.set(attributes[i].array, offset);
3589
3658
  offset += attributes[i].array.length;
3590
3659
  }
3591
- return new import_three19.BufferAttribute(array, itemSize, normalized);
3660
+ return new import_three20.BufferAttribute(array, itemSize, normalized);
3592
3661
  }
3593
3662
  function interleaveAttributes(attributes) {
3594
3663
  let TypedArray;
@@ -3604,7 +3673,7 @@ function interleaveAttributes(attributes) {
3604
3673
  arrayLength += attribute.array.length;
3605
3674
  stride += attribute.itemSize;
3606
3675
  }
3607
- const interleavedBuffer = new import_three19.InterleavedBuffer(new TypedArray(arrayLength), stride);
3676
+ const interleavedBuffer = new import_three20.InterleavedBuffer(new TypedArray(arrayLength), stride);
3608
3677
  let offset = 0;
3609
3678
  const res = [];
3610
3679
  const getters = ["getX", "getY", "getZ", "getW"];
@@ -3613,7 +3682,7 @@ function interleaveAttributes(attributes) {
3613
3682
  const attribute = attributes[j];
3614
3683
  const itemSize = attribute.itemSize;
3615
3684
  const count = attribute.count;
3616
- const iba = new import_three19.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
3685
+ const iba = new import_three20.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
3617
3686
  res.push(iba);
3618
3687
  offset += itemSize;
3619
3688
  for (let c = 0; c < count; c++) {
@@ -3697,13 +3766,13 @@ function mergeVertices(geometry, tolerance = 1e-4) {
3697
3766
  const name = attributeNames[i];
3698
3767
  const oldAttribute = geometry.getAttribute(name);
3699
3768
  const buffer = new oldAttribute.array.constructor(attrArrays[name]);
3700
- const attribute = new import_three19.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
3769
+ const attribute = new import_three20.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
3701
3770
  result.setAttribute(name, attribute);
3702
3771
  if (name in morphAttrsArrays) {
3703
3772
  for (let j = 0; j < morphAttrsArrays[name].length; j++) {
3704
3773
  const oldMorphAttribute = geometry.morphAttributes[name][j];
3705
3774
  const buffer2 = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
3706
- const morphAttribute = new import_three19.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
3775
+ const morphAttribute = new import_three20.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
3707
3776
  result.morphAttributes[name][j] = morphAttribute;
3708
3777
  }
3709
3778
  }
@@ -3712,11 +3781,11 @@ function mergeVertices(geometry, tolerance = 1e-4) {
3712
3781
  return result;
3713
3782
  }
3714
3783
  function toTrianglesDrawMode(geometry, drawMode) {
3715
- if (drawMode === import_three19.TrianglesDrawMode) {
3784
+ if (drawMode === import_three20.TrianglesDrawMode) {
3716
3785
  console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.");
3717
3786
  return geometry;
3718
3787
  }
3719
- if (drawMode === import_three19.TriangleFanDrawMode || drawMode === import_three19.TriangleStripDrawMode) {
3788
+ if (drawMode === import_three20.TriangleFanDrawMode || drawMode === import_three20.TriangleStripDrawMode) {
3720
3789
  let index = geometry.getIndex();
3721
3790
  if (index === null) {
3722
3791
  const indices = [];
@@ -3734,7 +3803,7 @@ function toTrianglesDrawMode(geometry, drawMode) {
3734
3803
  }
3735
3804
  const numberOfTriangles = index.count - 2;
3736
3805
  const newIndices = [];
3737
- if (drawMode === import_three19.TriangleFanDrawMode) {
3806
+ if (drawMode === import_three20.TriangleFanDrawMode) {
3738
3807
  for (let i = 1; i <= numberOfTriangles; i++) {
3739
3808
  newIndices.push(index.getX(0));
3740
3809
  newIndices.push(index.getX(i));
@@ -3770,15 +3839,15 @@ function computeMorphedAttributes(object) {
3770
3839
  console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
3771
3840
  return null;
3772
3841
  }
3773
- const _vA = new import_three19.Vector3();
3774
- const _vB = new import_three19.Vector3();
3775
- const _vC = new import_three19.Vector3();
3776
- const _tempA = new import_three19.Vector3();
3777
- const _tempB = new import_three19.Vector3();
3778
- const _tempC = new import_three19.Vector3();
3779
- const _morphA = new import_three19.Vector3();
3780
- const _morphB = new import_three19.Vector3();
3781
- const _morphC = new import_three19.Vector3();
3842
+ const _vA = new import_three20.Vector3();
3843
+ const _vB = new import_three20.Vector3();
3844
+ const _vC = new import_three20.Vector3();
3845
+ const _tempA = new import_three20.Vector3();
3846
+ const _tempB = new import_three20.Vector3();
3847
+ const _tempC = new import_three20.Vector3();
3848
+ const _morphA = new import_three20.Vector3();
3849
+ const _morphB = new import_three20.Vector3();
3850
+ const _morphC = new import_three20.Vector3();
3782
3851
  function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
3783
3852
  _vA.fromBufferAttribute(attribute, a2);
3784
3853
  _vB.fromBufferAttribute(attribute, b2);
@@ -3973,8 +4042,8 @@ function computeMorphedAttributes(object) {
3973
4042
  }
3974
4043
  }
3975
4044
  }
3976
- const morphedPositionAttribute = new import_three19.Float32BufferAttribute(modifiedPosition, 3);
3977
- const morphedNormalAttribute = new import_three19.Float32BufferAttribute(modifiedNormal, 3);
4045
+ const morphedPositionAttribute = new import_three20.Float32BufferAttribute(modifiedPosition, 3);
4046
+ const morphedNormalAttribute = new import_three20.Float32BufferAttribute(modifiedNormal, 3);
3978
4047
  return {
3979
4048
  positionAttribute,
3980
4049
  normalAttribute,
@@ -3982,24 +4051,24 @@ function computeMorphedAttributes(object) {
3982
4051
  morphedNormalAttribute
3983
4052
  };
3984
4053
  }
3985
- var import_three19;
4054
+ var import_three20;
3986
4055
  var init_BufferGeometryUtils = __esm({
3987
4056
  "src/three/BufferGeometryUtils.js"() {
3988
- import_three19 = require("three");
4057
+ import_three20 = require("three");
3989
4058
  }
3990
4059
  });
3991
4060
 
3992
4061
  // src/model/ModelCulling.ts
3993
- var import_three20, ModelCulling;
4062
+ var import_three21, ModelCulling;
3994
4063
  var init_ModelCulling = __esm({
3995
4064
  "src/model/ModelCulling.ts"() {
3996
- import_three20 = require("three");
4065
+ import_three21 = require("three");
3997
4066
  init_CubeFace();
3998
4067
  ModelCulling = class {
3999
4068
  static toLocalMask(worldMask, rotation) {
4000
4069
  let localMask = 0;
4001
4070
  for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
4002
- const normal = new import_three20.Vector3(...offset).applyEuler(rotation);
4071
+ const normal = new import_three21.Vector3(...offset).applyEuler(rotation);
4003
4072
  const worldFace = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
4004
4073
  if (worldFace < 0) return 0;
4005
4074
  if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
@@ -4035,13 +4104,13 @@ var init_ModelCulling = __esm({
4035
4104
  function isModelObject(obj) {
4036
4105
  return obj.isModelObject;
4037
4106
  }
4038
- var import_three21, import_ts_deepmerge5, p7, _ModelObject, ModelObject;
4107
+ var import_three22, import_ts_deepmerge5, p7, _ModelObject, ModelObject;
4039
4108
  var init_ModelObject = __esm({
4040
4109
  "src/model/scene/ModelObject.ts"() {
4041
4110
  init_SceneObject();
4042
4111
  init_Materials();
4043
4112
  init_UVMapper();
4044
- import_three21 = require("three");
4113
+ import_three22 = require("three");
4045
4114
  init_BufferGeometryUtils();
4046
4115
  init_model();
4047
4116
  import_ts_deepmerge5 = __toESM(require_dist());
@@ -4095,7 +4164,7 @@ var init_ModelObject = __esm({
4095
4164
  elGeo.clearGroups();
4096
4165
  }
4097
4166
  if (this.options.uvLockRotation) {
4098
- UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three21.Euler(...this.options.uvLockRotation));
4167
+ UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three22.Euler(...this.options.uvLockRotation));
4099
4168
  }
4100
4169
  if (this.options.tints) {
4101
4170
  const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
@@ -4104,19 +4173,19 @@ var init_ModelObject = __esm({
4104
4173
  if (tintIndex === void 0 || tintIndex < 0) continue;
4105
4174
  const tint = this.options.tints[tintIndex];
4106
4175
  if (tint === void 0) continue;
4107
- const color = new import_three21.Color(tint);
4176
+ const color = new import_three22.Color(tint);
4108
4177
  for (let vertex = 0; vertex < 4; vertex++) {
4109
4178
  color.toArray(colors, (faceIndex * 4 + vertex) * 3);
4110
4179
  }
4111
4180
  }
4112
- elGeo.setAttribute("color", new import_three21.BufferAttribute(colors, 3));
4181
+ elGeo.setAttribute("color", new import_three22.BufferAttribute(colors, 3));
4113
4182
  }
4114
- elGeo.applyMatrix4(new import_three21.Matrix4().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4115
- elGeo.applyMatrix4(new import_three21.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4183
+ elGeo.applyMatrix4(new import_three22.Matrix4().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4184
+ elGeo.applyMatrix4(new import_three22.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4116
4185
  if (el.rotation) {
4117
4186
  applyElementRotation(el.rotation, elGeo);
4118
4187
  }
4119
- elGeo.applyMatrix4(new import_three21.Matrix4().makeTranslation(-8, -8, -8));
4188
+ elGeo.applyMatrix4(new import_three22.Matrix4().makeTranslation(-8, -8, -8));
4120
4189
  if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
4121
4190
  if (this.options.mergeMeshes) {
4122
4191
  allGeos.push(elGeo);
@@ -4138,7 +4207,7 @@ var init_ModelObject = __esm({
4138
4207
  if (allGeos.length > 0) {
4139
4208
  combinedGeo = mergeBufferGeometries(allGeos);
4140
4209
  } else {
4141
- combinedGeo = new import_three21.BoxGeometry(16, 16, 16);
4210
+ combinedGeo = new import_three22.BoxGeometry(16, 16, 16);
4142
4211
  if (displayTransform) DisplayTransforms.apply(combinedGeo, displayTransform);
4143
4212
  }
4144
4213
  combinedGeo.computeBoundingBox();
@@ -4248,7 +4317,7 @@ function ownHeight(sample) {
4248
4317
  return (level === 0 || level >= 8 ? 8 : 8 - level) / 9;
4249
4318
  }
4250
4319
  function createFluidGeometry(kind, sample) {
4251
- const geometry = new import_three26.BufferGeometry();
4320
+ const geometry = new import_three27.BufferGeometry();
4252
4321
  const positions = [], normals = [], uvs = [], indices = [];
4253
4322
  const self = sample(0, 0, 0);
4254
4323
  const height = (x, z) => {
@@ -4347,16 +4416,16 @@ function createFluidGeometry(kind, sample) {
4347
4416
  1
4348
4417
  );
4349
4418
  }
4350
- geometry.setAttribute("position", new import_three26.Float32BufferAttribute(positions, 3));
4351
- geometry.setAttribute("normal", new import_three26.Float32BufferAttribute(normals, 3));
4352
- geometry.setAttribute("uv", new import_three26.Float32BufferAttribute(uvs, 2));
4419
+ geometry.setAttribute("position", new import_three27.Float32BufferAttribute(positions, 3));
4420
+ geometry.setAttribute("normal", new import_three27.Float32BufferAttribute(normals, 3));
4421
+ geometry.setAttribute("uv", new import_three27.Float32BufferAttribute(uvs, 2));
4353
4422
  geometry.setIndex(indices);
4354
4423
  return geometry;
4355
4424
  }
4356
- var import_three26, fluidRules, HORIZONTAL, EPSILON;
4425
+ var import_three27, fluidRules, HORIZONTAL, EPSILON;
4357
4426
  var init_FluidGeometry = __esm({
4358
4427
  "src/model/fluid/FluidGeometry.ts"() {
4359
- import_three26 = require("three");
4428
+ import_three27 = require("three");
4360
4429
  init_fluidBlocks();
4361
4430
  fluidRules = fluidBlocks_default;
4362
4431
  HORIZONTAL = [[0, -1], [0, 1], [-1, 0], [1, 0]];
@@ -4385,10 +4454,10 @@ function sampleFluid(kind, sample) {
4385
4454
  }
4386
4455
  return { key: key.join(""), sample: (x, y, z) => cells[(y + 1) * 9 + (z + 1) * 3 + x + 1] };
4387
4456
  }
4388
- var import_three27, FluidModelObject;
4457
+ var import_three28, FluidModelObject;
4389
4458
  var init_FluidModelObject = __esm({
4390
4459
  "src/model/fluid/FluidModelObject.ts"() {
4391
- import_three27 = require("three");
4460
+ import_three28 = require("three");
4392
4461
  init_AssetKey();
4393
4462
  init_Materials();
4394
4463
  init_ModelObject();
@@ -4421,10 +4490,10 @@ var init_FluidModelObject = __esm({
4421
4490
  }
4422
4491
  }
4423
4492
  geometry.clearGroups();
4424
- const color = new import_three27.Color(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4493
+ const color = new import_three28.Color(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4425
4494
  const colors = new Float32Array(geometry.getAttribute("position").count * 3);
4426
4495
  for (let i = 0; i < colors.length; i += 3) color.toArray(colors, i);
4427
- geometry.setAttribute("color", new import_three27.BufferAttribute(colors, 3));
4496
+ geometry.setAttribute("color", new import_three28.BufferAttribute(colors, 3));
4428
4497
  geometry.computeBoundingBox();
4429
4498
  geometry.computeBoundingSphere();
4430
4499
  if (this.options.instanceMeshes) {
@@ -4438,7 +4507,7 @@ var init_FluidModelObject = __esm({
4438
4507
  super.applyTextures();
4439
4508
  this.iterateAllMeshes((mesh) => {
4440
4509
  const material = mesh.material;
4441
- material.side = import_three27.DoubleSide;
4510
+ material.side = import_three28.DoubleSide;
4442
4511
  material.forceSinglePass = true;
4443
4512
  material.depthWrite = !material.transparent;
4444
4513
  });
@@ -4469,6 +4538,7 @@ __export(index_browser_exports, {
4469
4538
  BUILTIN_GENERATED: () => BUILTIN_GENERATED,
4470
4539
  BasicAssetKey: () => BasicAssetKey,
4471
4540
  BatchedExecutor: () => BatchedExecutor,
4541
+ BlockEntities: () => BlockEntities,
4472
4542
  BlockObject: () => BlockObject,
4473
4543
  BlockStateResolver: () => BlockStateResolver,
4474
4544
  BlockStates: () => BlockStates,
@@ -4492,7 +4562,9 @@ __export(index_browser_exports, {
4492
4562
  DefaultBlockStates: () => DefaultBlockStates,
4493
4563
  DisplayPosition: () => DisplayPosition,
4494
4564
  DisplayTransforms: () => DisplayTransforms,
4565
+ ENTITY_ANIMATION_CHANNELS: () => ENTITY_ANIMATION_CHANNELS,
4495
4566
  Entities: () => Entities,
4567
+ EntityAnimationPlayer: () => EntityAnimationPlayer,
4496
4568
  EntityObject: () => EntityObject,
4497
4569
  Env: () => Env,
4498
4570
  FluidModelObject: () => FluidModelObject,
@@ -4566,6 +4638,7 @@ __export(index_browser_exports, {
4566
4638
  createCanvas: () => createCanvas,
4567
4639
  createFluidGeometry: () => createFluidGeometry,
4568
4640
  createImage: () => createImage,
4641
+ entityAnimationTime: () => entityAnimationTime,
4569
4642
  estimateBytesUsed: () => estimateBytesUsed,
4570
4643
  getBlockFluidState: () => getBlockFluidState,
4571
4644
  getFluidKind: () => getFluidKind,
@@ -4599,6 +4672,8 @@ __export(index_browser_exports, {
4599
4672
  prefix: () => prefix,
4600
4673
  probeImageSize: () => probeImageSize,
4601
4674
  registerBrowserEnv: () => registerBrowserEnv,
4675
+ sampleEntityAnimation: () => sampleEntityAnimation,
4676
+ sampleEntityKeyframes: () => sampleEntityKeyframes,
4602
4677
  sampleFluid: () => sampleFluid,
4603
4678
  serializeBoxGeometryKey: () => serializeBoxGeometryKey,
4604
4679
  serializeImageKey: () => serializeImageKey,
@@ -4894,6 +4969,59 @@ function shutdown() {
4894
4969
  init_AssetKey();
4895
4970
  init_AssetLoader();
4896
4971
  init_Assets();
4972
+
4973
+ // src/assets/BlockEntities.ts
4974
+ var import_three10 = require("three");
4975
+ init_AssetKey();
4976
+ init_AssetLoader();
4977
+ init_source();
4978
+ init_Caching();
4979
+ var BlockEntities = class {
4980
+ /**
4981
+ * Loads the block index of a version. Versions and sources without one yield an empty index, and so does
4982
+ * a failed load: the index is optional, and blocks must not retry or fail with it one by one. The empty
4983
+ * result is cached like any other; `Caching.clear()` or `AssetLoader.setVersion()` forces a new attempt.
4984
+ */
4985
+ static async getIndex(root) {
4986
+ const key = new AssetKey("entity-models", "blocks", void 0, void 0, void 0, ".json", root);
4987
+ key.rootType = void 0;
4988
+ const index = await Caching.blockEntityIndexCache.get(key.serialize(), async () => {
4989
+ try {
4990
+ return await AssetLoader.get(key, "json" /* JSON */) ?? {};
4991
+ } catch (error) {
4992
+ console.warn("Could not load the block entity index; block entities are drawn as plain block models", error);
4993
+ return {};
4994
+ }
4995
+ });
4996
+ return index ?? {};
4997
+ }
4998
+ /** The index entry of a block ID such as `minecraft:chest`. */
4999
+ static entry(index, block) {
5000
+ const entry = Object.prototype.hasOwnProperty.call(index, block) ? index[block] : void 0;
5001
+ return Array.isArray(entry?.parts) ? entry : void 0;
5002
+ }
5003
+ /** Selects the parts and placement for a block ID such as `minecraft:chest`; undefined when nothing is drawn. */
5004
+ static resolve(index, block, state = {}) {
5005
+ const entry = this.entry(index, block);
5006
+ if (!entry) return void 0;
5007
+ const value = (property) => String(state[property]).toLowerCase();
5008
+ const parts = entry.parts.filter((part) => Object.entries(part.when ?? {}).every(([property, values]) => String(values).split("|").includes(value(property))));
5009
+ if (!parts.length) return void 0;
5010
+ let rotation = 0;
5011
+ if (entry.rotation) {
5012
+ const selected = value(entry.rotation.property);
5013
+ rotation = "degrees" in entry.rotation ? entry.rotation.degrees[selected] : Number(selected) * entry.rotation.step;
5014
+ if (!Number.isFinite(rotation)) rotation = 0;
5015
+ }
5016
+ return { parts, rotation, translation: entry.translation ?? [0, 0, 0] };
5017
+ }
5018
+ /** Placement in block space (0..16 per axis), applied on top of the model's own transform. */
5019
+ static matrix(resolved, matrix = new import_three10.Matrix4()) {
5020
+ return matrix.makeTranslation(8, 0, 8).multiply(new import_three10.Matrix4().makeRotationY(resolved.rotation * Math.PI / 180)).multiply(new import_three10.Matrix4().makeTranslation(resolved.translation[0] - 8, resolved.translation[1], resolved.translation[2] - 8));
5021
+ }
5022
+ };
5023
+
5024
+ // src/assets/index.ts
4897
5025
  init_BlockStates();
4898
5026
 
4899
5027
  // src/assets/Entities.ts
@@ -4925,32 +5053,53 @@ var Entities = class {
4925
5053
  static async getLayerList(modelKey) {
4926
5054
  return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
4927
5055
  }
5056
+ /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
5057
+ static async getPassList(modelKey) {
5058
+ return (await this.getModelFile(modelKey))?.passes ?? [];
5059
+ }
4928
5060
  static async getEntity(modelKey, textureKey, options) {
4929
5061
  const model = await this.getModelFile(modelKey);
4930
5062
  if (!model) return void 0;
4931
- const names = [...new Set(options?.layers ?? [options?.layer ?? "main"])];
4932
- if (names.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
4933
- const selected = names.map((name) => {
4934
- const layer = model.layers[name];
5063
+ const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
5064
+ const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
5065
+ if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
5066
+ draws.push(...passes);
5067
+ const names = [];
5068
+ const selected = draws.map((pass) => {
5069
+ const layer = model.layers[pass.layer];
4935
5070
  if (!layer) {
4936
- throw new MineRenderError(`Entity ${model.id} has no layer "${name}". Available layers: ${Object.keys(model.layers).join(", ")}`);
5071
+ throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
4937
5072
  }
4938
- return { name, layer };
5073
+ let name = pass.layer;
5074
+ for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
5075
+ names.push(name);
5076
+ return { name, layer, pass };
4939
5077
  });
4940
- const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer }, index) => {
5078
+ const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
4941
5079
  const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
5080
+ const textureLocation = pass.textureLocation ?? layer.textureLocation;
4942
5081
  let texture;
4943
5082
  if (override) {
4944
5083
  const path = isAssetKey(override) ? override.getFullPath() : override.path;
4945
5084
  texture = isAssetKey(override) && override.assetType === "textures" && path.startsWith("entity/") ? override : new AssetKey(override.namespace, path, "textures", "entity", "assets", ".png", isAssetKey(override) ? override.root : void 0);
4946
- } else if (layer.textureLocation !== void 0) {
4947
- texture = AssetKey.parse("textures", layer.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
5085
+ } else if (textureLocation !== void 0) {
5086
+ texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
4948
5087
  } else {
4949
5088
  texture = await this.resolveTexture(modelKey);
4950
5089
  }
4951
- return [name, { key: override ?? modelKey, texture, layer }];
5090
+ const render = pass.render ?? layer.render;
5091
+ return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
4952
5092
  })));
4953
- return { ...layers[names[0]], id: model.id, layers };
5093
+ return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
5094
+ }
5095
+ /**
5096
+ * Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
5097
+ */
5098
+ static async getAnimations(modelKey) {
5099
+ const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
5100
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
5101
+ const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
5102
+ return file?.animations;
4954
5103
  }
4955
5104
  static async resolveTexture(modelKey) {
4956
5105
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
@@ -5028,11 +5177,125 @@ function trimCanvas(source) {
5028
5177
  return canvas;
5029
5178
  }
5030
5179
 
5180
+ // src/entity/EntityAnimation.ts
5181
+ var ENTITY_ANIMATION_CHANNELS = ["position", "rotation", "scale"];
5182
+ function catmullRom(delta, p0, p1, p22, p32) {
5183
+ return 0.5 * (2 * p1 + (p22 - p0) * delta + (2 * p0 - 5 * p1 + 4 * p22 - p32) * delta * delta + (3 * p1 - p0 - 3 * p22 + p32) * delta * delta * delta);
5184
+ }
5185
+ function sampleEntityKeyframes(keyframes, time) {
5186
+ if (keyframes.length === 0) return [0, 0, 0];
5187
+ let low = 0, high = keyframes.length;
5188
+ while (low < high) {
5189
+ const middle = low + high >>> 1;
5190
+ if (time <= keyframes[middle].time) high = middle;
5191
+ else low = middle + 1;
5192
+ }
5193
+ const a = Math.max(0, low - 1);
5194
+ const b = Math.min(keyframes.length - 1, a + 1);
5195
+ const from = keyframes[a];
5196
+ const to = keyframes[b];
5197
+ const delta = a === b ? 0 : Math.min(1, Math.max(0, (time - from.time) / (to.time - from.time)));
5198
+ if (to.interpolation === "catmullrom") {
5199
+ const before = keyframes[Math.max(0, a - 1)].value;
5200
+ const after = keyframes[Math.min(keyframes.length - 1, b + 1)].value;
5201
+ return [0, 1, 2].map((i) => catmullRom(delta, before[i], from.value[i], to.value[i], after[i]));
5202
+ }
5203
+ const target = to.pre ?? to.value;
5204
+ return [0, 1, 2].map((i) => from.value[i] + (target[i] - from.value[i]) * delta);
5205
+ }
5206
+ function entityAnimationTime(animation, time, loop = animation.loop) {
5207
+ return loop && animation.length > 0 ? time % animation.length : time;
5208
+ }
5209
+ function sampleEntityAnimation(animation, time, loop = animation.loop) {
5210
+ const elapsed = entityAnimationTime(animation, time, loop);
5211
+ const pose = {};
5212
+ for (const [name, bone] of Object.entries(animation.bones)) {
5213
+ const sampled = pose[name] = {};
5214
+ for (const channel of ENTITY_ANIMATION_CHANNELS) {
5215
+ const keyframes = bone[channel];
5216
+ if (keyframes?.length) sampled[channel] = sampleEntityKeyframes(keyframes, elapsed);
5217
+ }
5218
+ }
5219
+ return pose;
5220
+ }
5221
+
5222
+ // src/entity/scene/EntityAnimationPlayer.ts
5223
+ var ZERO = [0, 0, 0];
5224
+ var EntityAnimationPlayer = class {
5225
+ constructor() {
5226
+ this.parts = [];
5227
+ this._time = 0;
5228
+ this.loop = false;
5229
+ this.speed = 1;
5230
+ }
5231
+ get animation() {
5232
+ return this._animation;
5233
+ }
5234
+ get time() {
5235
+ return this._time;
5236
+ }
5237
+ /**
5238
+ * Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
5239
+ * bones without a matching part are skipped.
5240
+ */
5241
+ play(layers, animation, options = {}) {
5242
+ this.stop();
5243
+ this._animation = animation;
5244
+ this._time = options.time ?? 0;
5245
+ this.loop = options.loop ?? animation.loop;
5246
+ this.speed = options.speed ?? 1;
5247
+ for (const layer of layers) {
5248
+ for (const bone of Object.keys(animation.bones)) {
5249
+ const object = layer.getObjectByName(`group:${bone}`);
5250
+ if (!object) continue;
5251
+ this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
5252
+ }
5253
+ }
5254
+ this.apply();
5255
+ }
5256
+ /** Restores the default poses. Returns whether an animation was active. */
5257
+ stop() {
5258
+ if (!this._animation) return false;
5259
+ for (const part of this.parts) {
5260
+ part.object.position.copy(part.position);
5261
+ part.object.rotation.copy(part.rotation);
5262
+ part.object.scale.copy(part.scale);
5263
+ }
5264
+ this.clear();
5265
+ return true;
5266
+ }
5267
+ /** Forgets the animation without touching the parts, for parts that no longer exist. */
5268
+ clear() {
5269
+ this.parts = [];
5270
+ this._animation = void 0;
5271
+ this._time = 0;
5272
+ }
5273
+ setTime(seconds) {
5274
+ if (!this._animation) return false;
5275
+ this._time = seconds;
5276
+ this.apply();
5277
+ return true;
5278
+ }
5279
+ advance(deltaSeconds) {
5280
+ return this.setTime(this._time + deltaSeconds * this.speed);
5281
+ }
5282
+ apply() {
5283
+ const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
5284
+ for (const part of this.parts) {
5285
+ const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
5286
+ part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
5287
+ part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
5288
+ part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
5289
+ }
5290
+ }
5291
+ };
5292
+
5031
5293
  // src/entity/scene/EntityObject.ts
5032
5294
  init_SceneObject();
5033
5295
  init_Caching();
5034
5296
  var import_ts_deepmerge4 = __toESM(require_dist());
5035
- var import_three12 = require("three");
5297
+ var import_three13 = require("three");
5298
+ init_Ticker();
5036
5299
  init_model();
5037
5300
  init_ModelTextures();
5038
5301
  init_AssetKey();
@@ -5044,6 +5307,11 @@ var _EntityObject = class _EntityObject extends SceneObject {
5044
5307
  this.entity = entity;
5045
5308
  this.isEntityObject = true;
5046
5309
  this.meshesCreated = false;
5310
+ /** Scrolling materials are owned: their texture offset follows this entity's age. */
5311
+ this.scrollMaterials = [];
5312
+ /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
5313
+ this.age = 0;
5314
+ this.animationPlayer = new EntityAnimationPlayer();
5047
5315
  this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
5048
5316
  }
5049
5317
  async init() {
@@ -5053,6 +5321,59 @@ var _EntityObject = class _EntityObject extends SceneObject {
5053
5321
  dispose() {
5054
5322
  super.dispose();
5055
5323
  }
5324
+ disposeAndRemoveAllChildren() {
5325
+ this.clearScrollMaterials();
5326
+ this.animationPlayer.clear();
5327
+ super.disposeAndRemoveAllChildren();
5328
+ }
5329
+ clearScrollMaterials() {
5330
+ Ticker.remove(this.scrollTicker);
5331
+ this.scrollTicker = void 0;
5332
+ for (const { material } of this.scrollMaterials.splice(0)) {
5333
+ material.map?.dispose();
5334
+ material.dispose();
5335
+ }
5336
+ }
5337
+ /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
5338
+ updateScroll() {
5339
+ for (const { offset, speed } of this.scrollMaterials) {
5340
+ offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
5341
+ }
5342
+ this.notifyDirty();
5343
+ }
5344
+ //<editor-fold desc="ANIMATION">
5345
+ /** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
5346
+ get animation() {
5347
+ return this.animationPlayer.animation;
5348
+ }
5349
+ /** Seconds since the animation started, before looping. */
5350
+ get animationTime() {
5351
+ return this.animationPlayer.time;
5352
+ }
5353
+ /**
5354
+ * Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
5355
+ * Parts of every layer are matched by name and their current pose is the default the offsets add to.
5356
+ * The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
5357
+ */
5358
+ playAnimation(animation, options) {
5359
+ this.createMeshes();
5360
+ const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
5361
+ this.animationPlayer.play(layers, animation, options);
5362
+ this.notifyDirty();
5363
+ }
5364
+ /** Stops the animation and restores the default pose. */
5365
+ stopAnimation() {
5366
+ if (this.animationPlayer.stop()) this.notifyDirty();
5367
+ }
5368
+ /** Poses the object at an explicit time in seconds. Has no effect without an animation. */
5369
+ setAnimationTime(seconds) {
5370
+ if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
5371
+ }
5372
+ /** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
5373
+ advanceAnimation(deltaSeconds) {
5374
+ if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
5375
+ }
5376
+ //</editor-fold>
5056
5377
  getLayerGroup(name) {
5057
5378
  return super.getGroupByName(`layer:${name}`);
5058
5379
  }
@@ -5082,17 +5403,30 @@ var _EntityObject = class _EntityObject extends SceneObject {
5082
5403
  }
5083
5404
  createMeshes(force = false) {
5084
5405
  if (this.meshesCreated && !force) return;
5085
- const modelRoot = new import_three12.Object3D();
5086
- if (this.options.flip) modelRoot.scale.set(-1, -1, 1);
5406
+ const modelRoot = new import_three13.Object3D();
5407
+ const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
5408
+ if (transform) {
5409
+ for (const op of transform) {
5410
+ const matrix = new import_three13.Matrix4();
5411
+ if ("scale" in op) matrix.makeScale(...op.scale);
5412
+ else if ("translate" in op) matrix.makeTranslation(...op.translate);
5413
+ else matrix.makeRotationFromEuler(new import_three13.Euler(...op.rotate, "ZYX"));
5414
+ modelRoot.matrix.multiply(matrix);
5415
+ }
5416
+ modelRoot.matrixAutoUpdate = false;
5417
+ } else if (this.options.flip ?? true) {
5418
+ modelRoot.scale.set(-1, -1, 1);
5419
+ }
5087
5420
  this.add(modelRoot);
5088
5421
  Object.entries(this.entityLayers).forEach(([name, layer], index) => {
5089
5422
  const group = this.createGroup(`layer:${name}`);
5090
5423
  modelRoot.add(group);
5091
- this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index);
5424
+ const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
5425
+ this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
5092
5426
  });
5093
5427
  this.meshesCreated = true;
5094
5428
  }
5095
- createPart(name, part, parent, textureSize, material, renderOrder) {
5429
+ createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
5096
5430
  const anchor = this.createGroup(name);
5097
5431
  anchor.position.fromArray(part.pose.offset);
5098
5432
  anchor.rotation.set(...part.pose.rotation, "ZYX");
@@ -5111,7 +5445,7 @@ var _EntityObject = class _EntityObject extends SceneObject {
5111
5445
  uv
5112
5446
  ).clone();
5113
5447
  geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
5114
- if (Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
5448
+ if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
5115
5449
  const index = Array.from(geometry.getIndex().array);
5116
5450
  geometry.setIndex(index.concat(index.slice().reverse()));
5117
5451
  }
@@ -5121,30 +5455,46 @@ var _EntityObject = class _EntityObject extends SceneObject {
5121
5455
  if (this.options.wireframe) addWireframeToMesh(geometry, mesh);
5122
5456
  }
5123
5457
  for (const [childName, child] of Object.entries(part.children)) {
5124
- this.createPart(childName, child, anchor, size, material, renderOrder);
5458
+ this.createPart(childName, child, anchor, size, material, renderOrder, inward);
5125
5459
  }
5126
5460
  }
5127
5461
  async applyTextures() {
5462
+ this.clearScrollMaterials();
5128
5463
  await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
5464
+ const mode = layer.render ?? layer.layer.render ?? "cutout";
5465
+ const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
5466
+ const scroll = Materials.entityModeScroll(mode);
5129
5467
  const assetKeyStr = this.getTextureKey(layer).serialize();
5130
- const keyStr = `entity:${assetKeyStr}`;
5131
- let mat = Caching.materialCache.getIfPresent(keyStr);
5468
+ const keyStr = `entity:${mode}:${tint === void 0 ? "" : new import_three13.Color(tint).getHexString()}:${assetKeyStr}`;
5469
+ let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
5132
5470
  if (!mat) {
5133
5471
  const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
5134
5472
  const imageData = await this.loadTextures(layer);
5135
5473
  if (!imageData) return;
5136
5474
  const canvas = imageData.data.canvas;
5137
- const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
5138
- mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5475
+ const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
5476
+ mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5477
+ if (scroll) {
5478
+ this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
5479
+ }
5139
5480
  }
5140
5481
  this.getLayerGroup(name)?.traverse((object) => {
5141
5482
  if (isMesh(object)) object.material = mat;
5142
5483
  });
5143
5484
  }));
5485
+ if (!this.children.length) {
5486
+ this.clearScrollMaterials();
5487
+ } else if (this.scrollMaterials.length) {
5488
+ this.updateScroll();
5489
+ this.scrollTicker = Ticker.add(() => {
5490
+ this.age++;
5491
+ this.updateScroll();
5492
+ });
5493
+ }
5144
5494
  this.notifyDirty();
5145
5495
  }
5146
5496
  };
5147
- _EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, { flip: true });
5497
+ _EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
5148
5498
  var EntityObject = _EntityObject;
5149
5499
  function isEntityObject(obj) {
5150
5500
  return obj.isEntityObject;
@@ -5154,27 +5504,27 @@ function isEntityObject(obj) {
5154
5504
  init_MineRenderError();
5155
5505
 
5156
5506
  // src/export/SceneExporter.ts
5157
- var import_three18 = require("three");
5507
+ var import_three19 = require("three");
5158
5508
 
5159
5509
  // ../../node_modules/three/examples/jsm/exporters/OBJExporter.js
5160
- var import_three14 = require("three");
5510
+ var import_three15 = require("three");
5161
5511
  var OBJExporter = class {
5162
5512
  parse(object) {
5163
5513
  let output = "";
5164
5514
  let indexVertex = 0;
5165
5515
  let indexVertexUvs = 0;
5166
5516
  let indexNormals = 0;
5167
- const vertex = new import_three14.Vector3();
5168
- const color = new import_three14.Color();
5169
- const normal = new import_three14.Vector3();
5170
- const uv = new import_three14.Vector2();
5517
+ const vertex = new import_three15.Vector3();
5518
+ const color = new import_three15.Color();
5519
+ const normal = new import_three15.Vector3();
5520
+ const uv = new import_three15.Vector2();
5171
5521
  const face = [];
5172
5522
  function parseMesh(mesh) {
5173
5523
  let nbVertex = 0;
5174
5524
  let nbNormals = 0;
5175
5525
  let nbVertexUvs = 0;
5176
5526
  const geometry = mesh.geometry;
5177
- const normalMatrixWorld = new import_three14.Matrix3();
5527
+ const normalMatrixWorld = new import_three15.Matrix3();
5178
5528
  const vertices = geometry.getAttribute("position");
5179
5529
  const normals = geometry.getAttribute("normal");
5180
5530
  const uvs = geometry.getAttribute("uv");
@@ -5293,7 +5643,7 @@ var OBJExporter = class {
5293
5643
  };
5294
5644
 
5295
5645
  // ../../node_modules/three/examples/jsm/exporters/PLYExporter.js
5296
- var import_three15 = require("three");
5646
+ var import_three16 = require("three");
5297
5647
  var PLYExporter = class {
5298
5648
  parse(object, onDone, options = {}) {
5299
5649
  function traverseMeshes(cb) {
@@ -5350,7 +5700,7 @@ var PLYExporter = class {
5350
5700
  includeIndices = false;
5351
5701
  }
5352
5702
  });
5353
- const tempColor = new import_three15.Color();
5703
+ const tempColor = new import_three16.Color();
5354
5704
  includeIndices = includeIndices && excludeAttributes.indexOf("index") === -1;
5355
5705
  includeNormals = includeNormals && excludeAttributes.indexOf("normal") === -1;
5356
5706
  includeColors = includeColors && excludeAttributes.indexOf("color") === -1;
@@ -5384,8 +5734,8 @@ property list uchar int vertex_index
5384
5734
  `;
5385
5735
  }
5386
5736
  header += "end_header\n";
5387
- const vertex = new import_three15.Vector3();
5388
- const normalMatrixWorld = new import_three15.Matrix3();
5737
+ const vertex = new import_three16.Vector3();
5738
+ const normalMatrixWorld = new import_three16.Matrix3();
5389
5739
  let result = null;
5390
5740
  if (options.binary === true) {
5391
5741
  const headerBin = new TextEncoder().encode(header);
@@ -5559,18 +5909,18 @@ property list uchar int vertex_index
5559
5909
  };
5560
5910
 
5561
5911
  // ../../node_modules/three/examples/jsm/exporters/GLTFExporter.js
5562
- var import_three17 = require("three");
5912
+ var import_three18 = require("three");
5563
5913
 
5564
5914
  // ../../node_modules/three/examples/jsm/utils/TextureUtils.js
5565
- var import_three16 = require("three");
5915
+ var import_three17 = require("three");
5566
5916
  var _renderer;
5567
5917
  var fullscreenQuadGeometry;
5568
5918
  var fullscreenQuadMaterial;
5569
5919
  var fullscreenQuad;
5570
5920
  function decompress(texture, maxTextureSize = Infinity, renderer = null) {
5571
- if (!fullscreenQuadGeometry) fullscreenQuadGeometry = new import_three16.PlaneGeometry(2, 2, 1, 1);
5572
- if (!fullscreenQuadMaterial) fullscreenQuadMaterial = new import_three16.ShaderMaterial({
5573
- uniforms: { blitTexture: new import_three16.Uniform(texture) },
5921
+ if (!fullscreenQuadGeometry) fullscreenQuadGeometry = new import_three17.PlaneGeometry(2, 2, 1, 1);
5922
+ if (!fullscreenQuadMaterial) fullscreenQuadMaterial = new import_three17.ShaderMaterial({
5923
+ uniforms: { blitTexture: new import_three17.Uniform(texture) },
5574
5924
  vertexShader: `
5575
5925
  varying vec2 vUv;
5576
5926
  void main(){
@@ -5592,22 +5942,22 @@ function decompress(texture, maxTextureSize = Infinity, renderer = null) {
5592
5942
  }`
5593
5943
  });
5594
5944
  fullscreenQuadMaterial.uniforms.blitTexture.value = texture;
5595
- fullscreenQuadMaterial.defines.IS_SRGB = texture.colorSpace == import_three16.SRGBColorSpace;
5945
+ fullscreenQuadMaterial.defines.IS_SRGB = texture.colorSpace == import_three17.SRGBColorSpace;
5596
5946
  fullscreenQuadMaterial.needsUpdate = true;
5597
5947
  if (!fullscreenQuad) {
5598
- fullscreenQuad = new import_three16.Mesh(fullscreenQuadGeometry, fullscreenQuadMaterial);
5948
+ fullscreenQuad = new import_three17.Mesh(fullscreenQuadGeometry, fullscreenQuadMaterial);
5599
5949
  fullscreenQuad.frustrumCulled = false;
5600
5950
  }
5601
- const _camera = new import_three16.PerspectiveCamera();
5602
- const _scene = new import_three16.Scene();
5951
+ const _camera = new import_three17.PerspectiveCamera();
5952
+ const _scene = new import_three17.Scene();
5603
5953
  _scene.add(fullscreenQuad);
5604
5954
  if (!renderer) {
5605
- renderer = _renderer = new import_three16.WebGLRenderer({ antialias: false });
5955
+ renderer = _renderer = new import_three17.WebGLRenderer({ antialias: false });
5606
5956
  }
5607
5957
  renderer.setSize(Math.min(texture.image.width, maxTextureSize), Math.min(texture.image.height, maxTextureSize));
5608
5958
  renderer.clear();
5609
5959
  renderer.render(_scene, _camera);
5610
- const readableTexture = new import_three16.Texture(renderer.domElement);
5960
+ const readableTexture = new import_three17.Texture(renderer.domElement);
5611
5961
  readableTexture.minFilter = texture.minFilter;
5612
5962
  readableTexture.magFilter = texture.magFilter;
5613
5963
  readableTexture.wrapS = texture.wrapS;
@@ -5753,22 +6103,22 @@ var WEBGL_CONSTANTS = {
5753
6103
  };
5754
6104
  var KHR_MESH_QUANTIZATION = "KHR_mesh_quantization";
5755
6105
  var THREE_TO_WEBGL = {};
5756
- THREE_TO_WEBGL[import_three17.NearestFilter] = WEBGL_CONSTANTS.NEAREST;
5757
- THREE_TO_WEBGL[import_three17.NearestMipmapNearestFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_NEAREST;
5758
- THREE_TO_WEBGL[import_three17.NearestMipmapLinearFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_LINEAR;
5759
- THREE_TO_WEBGL[import_three17.LinearFilter] = WEBGL_CONSTANTS.LINEAR;
5760
- THREE_TO_WEBGL[import_three17.LinearMipmapNearestFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST;
5761
- THREE_TO_WEBGL[import_three17.LinearMipmapLinearFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR;
5762
- THREE_TO_WEBGL[import_three17.ClampToEdgeWrapping] = WEBGL_CONSTANTS.CLAMP_TO_EDGE;
5763
- THREE_TO_WEBGL[import_three17.RepeatWrapping] = WEBGL_CONSTANTS.REPEAT;
5764
- THREE_TO_WEBGL[import_three17.MirroredRepeatWrapping] = WEBGL_CONSTANTS.MIRRORED_REPEAT;
6106
+ THREE_TO_WEBGL[import_three18.NearestFilter] = WEBGL_CONSTANTS.NEAREST;
6107
+ THREE_TO_WEBGL[import_three18.NearestMipmapNearestFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_NEAREST;
6108
+ THREE_TO_WEBGL[import_three18.NearestMipmapLinearFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_LINEAR;
6109
+ THREE_TO_WEBGL[import_three18.LinearFilter] = WEBGL_CONSTANTS.LINEAR;
6110
+ THREE_TO_WEBGL[import_three18.LinearMipmapNearestFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST;
6111
+ THREE_TO_WEBGL[import_three18.LinearMipmapLinearFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR;
6112
+ THREE_TO_WEBGL[import_three18.ClampToEdgeWrapping] = WEBGL_CONSTANTS.CLAMP_TO_EDGE;
6113
+ THREE_TO_WEBGL[import_three18.RepeatWrapping] = WEBGL_CONSTANTS.REPEAT;
6114
+ THREE_TO_WEBGL[import_three18.MirroredRepeatWrapping] = WEBGL_CONSTANTS.MIRRORED_REPEAT;
5765
6115
  var PATH_PROPERTIES = {
5766
6116
  scale: "scale",
5767
6117
  position: "translation",
5768
6118
  quaternion: "rotation",
5769
6119
  morphTargetInfluences: "weights"
5770
6120
  };
5771
- var DEFAULT_SPECULAR_COLOR = new import_three17.Color();
6121
+ var DEFAULT_SPECULAR_COLOR = new import_three18.Color();
5772
6122
  var GLB_HEADER_BYTES = 12;
5773
6123
  var GLB_HEADER_MAGIC = 1179937895;
5774
6124
  var GLB_VERSION = 2;
@@ -5802,7 +6152,7 @@ function getMinMax(attribute, start, count) {
5802
6152
  else if (a === 2) value = attribute.getZ(i);
5803
6153
  else if (a === 3) value = attribute.getW(i);
5804
6154
  if (attribute.normalized === true) {
5805
- value = import_three17.MathUtils.normalize(value, attribute.array);
6155
+ value = import_three18.MathUtils.normalize(value, attribute.array);
5806
6156
  }
5807
6157
  }
5808
6158
  output.min[a] = Math.min(output.min[a], value);
@@ -6008,7 +6358,7 @@ var GLTFWriter = class {
6008
6358
  isNormalizedNormalAttribute(normal) {
6009
6359
  const cache = this.cache;
6010
6360
  if (cache.attributesNormalized.has(normal)) return false;
6011
- const v = new import_three17.Vector3();
6361
+ const v = new import_three18.Vector3();
6012
6362
  for (let i = 0, il = normal.count; i < il; i++) {
6013
6363
  if (Math.abs(v.fromBufferAttribute(normal, i).length() - 1) > 5e-4) return false;
6014
6364
  }
@@ -6025,7 +6375,7 @@ var GLTFWriter = class {
6025
6375
  const cache = this.cache;
6026
6376
  if (cache.attributesNormalized.has(normal)) return cache.attributesNormalized.get(normal);
6027
6377
  const attribute = normal.clone();
6028
- const v = new import_three17.Vector3();
6378
+ const v = new import_three18.Vector3();
6029
6379
  for (let i = 0, il = attribute.count; i < il; i++) {
6030
6380
  v.fromBufferAttribute(attribute, i);
6031
6381
  if (v.x === 0 && v.y === 0 && v.z === 0) {
@@ -6069,7 +6419,7 @@ var GLTFWriter = class {
6069
6419
  buildMetalRoughTexture(metalnessMap, roughnessMap) {
6070
6420
  if (metalnessMap === roughnessMap) return metalnessMap;
6071
6421
  function getEncodingConversion(map) {
6072
- if (map.colorSpace === import_three17.SRGBColorSpace) {
6422
+ if (map.colorSpace === import_three18.SRGBColorSpace) {
6073
6423
  return function SRGBToLinear(c) {
6074
6424
  return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);
6075
6425
  };
@@ -6079,10 +6429,10 @@ var GLTFWriter = class {
6079
6429
  };
6080
6430
  }
6081
6431
  console.warn("THREE.GLTFExporter: Merged metalnessMap and roughnessMap textures.");
6082
- if (metalnessMap instanceof import_three17.CompressedTexture) {
6432
+ if (metalnessMap instanceof import_three18.CompressedTexture) {
6083
6433
  metalnessMap = decompress(metalnessMap);
6084
6434
  }
6085
- if (roughnessMap instanceof import_three17.CompressedTexture) {
6435
+ if (roughnessMap instanceof import_three18.CompressedTexture) {
6086
6436
  roughnessMap = decompress(roughnessMap);
6087
6437
  }
6088
6438
  const metalness = metalnessMap ? metalnessMap.image : null;
@@ -6115,8 +6465,8 @@ var GLTFWriter = class {
6115
6465
  context.putImageData(composite, 0, 0);
6116
6466
  const reference = metalnessMap || roughnessMap;
6117
6467
  const texture = reference.clone();
6118
- texture.source = new import_three17.Source(canvas);
6119
- texture.colorSpace = import_three17.NoColorSpace;
6468
+ texture.source = new import_three18.Source(canvas);
6469
+ texture.colorSpace = import_three18.NoColorSpace;
6120
6470
  texture.channel = (metalnessMap || roughnessMap).channel;
6121
6471
  if (metalnessMap && roughnessMap && metalnessMap.channel !== roughnessMap.channel) {
6122
6472
  console.warn("THREE.GLTFExporter: UV channels for metalnessMap and roughnessMap textures must match.");
@@ -6174,7 +6524,7 @@ var GLTFWriter = class {
6174
6524
  else if (a === 2) value = attribute.getZ(i);
6175
6525
  else if (a === 3) value = attribute.getW(i);
6176
6526
  if (attribute.normalized === true) {
6177
- value = import_three17.MathUtils.normalize(value, attribute.array);
6527
+ value = import_three18.MathUtils.normalize(value, attribute.array);
6178
6528
  }
6179
6529
  }
6180
6530
  if (componentType === WEBGL_CONSTANTS.FLOAT) {
@@ -6324,7 +6674,7 @@ var GLTFWriter = class {
6324
6674
  ctx.scale(1, -1);
6325
6675
  }
6326
6676
  if (image.data !== void 0) {
6327
- if (format !== import_three17.RGBAFormat) {
6677
+ if (format !== import_three18.RGBAFormat) {
6328
6678
  console.error("GLTFExporter: Only RGBAFormat is supported.", format);
6329
6679
  }
6330
6680
  if (image.width > options.maxTextureSize || image.height > options.maxTextureSize) {
@@ -6393,7 +6743,7 @@ var GLTFWriter = class {
6393
6743
  const json = this.json;
6394
6744
  if (cache.textures.has(map)) return cache.textures.get(map);
6395
6745
  if (!json.textures) json.textures = [];
6396
- if (map instanceof import_three17.CompressedTexture) {
6746
+ if (map instanceof import_three18.CompressedTexture) {
6397
6747
  map = decompress(map, options.maxTextureSize);
6398
6748
  }
6399
6749
  let mimeType = map.userData.mimeType;
@@ -6501,7 +6851,7 @@ var GLTFWriter = class {
6501
6851
  materialDef.alphaCutoff = material.alphaTest;
6502
6852
  }
6503
6853
  }
6504
- if (material.side === import_three17.DoubleSide) materialDef.doubleSided = true;
6854
+ if (material.side === import_three18.DoubleSide) materialDef.doubleSided = true;
6505
6855
  if (material.name !== "") materialDef.name = material.name;
6506
6856
  this.serializeUserData(material, materialDef);
6507
6857
  this._invokeAll(function(ext) {
@@ -6575,7 +6925,7 @@ var GLTFWriter = class {
6575
6925
  const array = attribute.array;
6576
6926
  if (attributeName === "JOINTS_0" && !(array instanceof Uint16Array) && !(array instanceof Uint8Array)) {
6577
6927
  console.warn('GLTFExporter: Attribute "skinIndex" converted to type UNSIGNED_SHORT.');
6578
- modifiedAttribute = new import_three17.BufferAttribute(new Uint16Array(array), attribute.itemSize, attribute.normalized);
6928
+ modifiedAttribute = new import_three18.BufferAttribute(new Uint16Array(array), attribute.itemSize, attribute.normalized);
6579
6929
  }
6580
6930
  const accessor = this.processAccessor(modifiedAttribute || attribute, geometry);
6581
6931
  if (accessor !== null) {
@@ -6735,7 +7085,7 @@ var GLTFWriter = class {
6735
7085
  } else {
6736
7086
  cameraDef.perspective = {
6737
7087
  aspectRatio: camera.aspect,
6738
- yfov: import_three17.MathUtils.degToRad(camera.fov),
7088
+ yfov: import_three18.MathUtils.degToRad(camera.fov),
6739
7089
  zfar: camera.far <= 0 ? 1e-3 : camera.far,
6740
7090
  znear: camera.near < 0 ? 0 : camera.near
6741
7091
  };
@@ -6763,8 +7113,8 @@ var GLTFWriter = class {
6763
7113
  const samplers = [];
6764
7114
  for (let i = 0; i < tracks.length; ++i) {
6765
7115
  const track = tracks[i];
6766
- const trackBinding = import_three17.PropertyBinding.parseTrackName(track.name);
6767
- let trackNode = import_three17.PropertyBinding.findNode(root, trackBinding.nodeName);
7116
+ const trackBinding = import_three18.PropertyBinding.parseTrackName(track.name);
7117
+ let trackNode = import_three18.PropertyBinding.findNode(root, trackBinding.nodeName);
6768
7118
  const trackProperty = PATH_PROPERTIES[trackBinding.propertyName];
6769
7119
  if (trackBinding.objectName === "bones") {
6770
7120
  if (trackNode.isSkinnedMesh === true) {
@@ -6786,14 +7136,14 @@ var GLTFWriter = class {
6786
7136
  if (track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true) {
6787
7137
  interpolation = "CUBICSPLINE";
6788
7138
  outputItemSize /= 3;
6789
- } else if (track.getInterpolation() === import_three17.InterpolateDiscrete) {
7139
+ } else if (track.getInterpolation() === import_three18.InterpolateDiscrete) {
6790
7140
  interpolation = "STEP";
6791
7141
  } else {
6792
7142
  interpolation = "LINEAR";
6793
7143
  }
6794
7144
  samplers.push({
6795
- input: this.processAccessor(new import_three17.BufferAttribute(track.times, inputItemSize)),
6796
- output: this.processAccessor(new import_three17.BufferAttribute(track.values, outputItemSize)),
7145
+ input: this.processAccessor(new import_three18.BufferAttribute(track.times, inputItemSize)),
7146
+ output: this.processAccessor(new import_three18.BufferAttribute(track.values, outputItemSize)),
6797
7147
  interpolation
6798
7148
  });
6799
7149
  channels.push({
@@ -6825,7 +7175,7 @@ var GLTFWriter = class {
6825
7175
  if (rootJoint === void 0) return null;
6826
7176
  const joints = [];
6827
7177
  const inverseBindMatrices = new Float32Array(skeleton.bones.length * 16);
6828
- const temporaryBoneInverse = new import_three17.Matrix4();
7178
+ const temporaryBoneInverse = new import_three18.Matrix4();
6829
7179
  for (let i = 0; i < skeleton.bones.length; ++i) {
6830
7180
  joints.push(nodeMap.get(skeleton.bones[i]));
6831
7181
  temporaryBoneInverse.copy(skeleton.boneInverses[i]);
@@ -6833,7 +7183,7 @@ var GLTFWriter = class {
6833
7183
  }
6834
7184
  if (json.skins === void 0) json.skins = [];
6835
7185
  json.skins.push({
6836
- inverseBindMatrices: this.processAccessor(new import_three17.BufferAttribute(inverseBindMatrices, 16)),
7186
+ inverseBindMatrices: this.processAccessor(new import_three18.BufferAttribute(inverseBindMatrices, 16)),
6837
7187
  joints,
6838
7188
  skeleton: nodeMap.get(rootJoint)
6839
7189
  });
@@ -6929,7 +7279,7 @@ var GLTFWriter = class {
6929
7279
  * @param {Array} objects List of objects to process
6930
7280
  */
6931
7281
  processObjects(objects) {
6932
- const scene = new import_three17.Scene();
7282
+ const scene = new import_three18.Scene();
6933
7283
  scene.name = "AuxScene";
6934
7284
  for (let i = 0; i < objects.length; i++) {
6935
7285
  scene.children.push(objects[i]);
@@ -6947,7 +7297,7 @@ var GLTFWriter = class {
6947
7297
  });
6948
7298
  const objectsWithoutScene = [];
6949
7299
  for (let i = 0; i < input.length; i++) {
6950
- if (input[i] instanceof import_three17.Scene) {
7300
+ if (input[i] instanceof import_three18.Scene) {
6951
7301
  this.processScene(input[i]);
6952
7302
  } else {
6953
7303
  objectsWithoutScene.push(input[i]);
@@ -7291,10 +7641,10 @@ var GLTFMeshGpuInstancing = class {
7291
7641
  const translationAttr = new Float32Array(mesh.count * 3);
7292
7642
  const rotationAttr = new Float32Array(mesh.count * 4);
7293
7643
  const scaleAttr = new Float32Array(mesh.count * 3);
7294
- const matrix = new import_three17.Matrix4();
7295
- const position = new import_three17.Vector3();
7296
- const quaternion = new import_three17.Quaternion();
7297
- const scale = new import_three17.Vector3();
7644
+ const matrix = new import_three18.Matrix4();
7645
+ const position = new import_three18.Vector3();
7646
+ const quaternion = new import_three18.Quaternion();
7647
+ const scale = new import_three18.Vector3();
7298
7648
  for (let i = 0; i < mesh.count; i++) {
7299
7649
  mesh.getMatrixAt(i, matrix);
7300
7650
  matrix.decompose(position, quaternion, scale);
@@ -7303,9 +7653,9 @@ var GLTFMeshGpuInstancing = class {
7303
7653
  scale.toArray(scaleAttr, i * 3);
7304
7654
  }
7305
7655
  const attributes = {
7306
- TRANSLATION: writer.processAccessor(new import_three17.BufferAttribute(translationAttr, 3)),
7307
- ROTATION: writer.processAccessor(new import_three17.BufferAttribute(rotationAttr, 4)),
7308
- SCALE: writer.processAccessor(new import_three17.BufferAttribute(scaleAttr, 3))
7656
+ TRANSLATION: writer.processAccessor(new import_three18.BufferAttribute(translationAttr, 3)),
7657
+ ROTATION: writer.processAccessor(new import_three18.BufferAttribute(rotationAttr, 4)),
7658
+ SCALE: writer.processAccessor(new import_three18.BufferAttribute(scaleAttr, 3))
7309
7659
  };
7310
7660
  if (mesh.instanceColor)
7311
7661
  attributes._COLOR_0 = writer.processAccessor(mesh.instanceColor);
@@ -7370,8 +7720,8 @@ GLTFExporter.Utils = {
7370
7720
  const sourceTracks = clip.tracks;
7371
7721
  for (let i = 0; i < sourceTracks.length; ++i) {
7372
7722
  let sourceTrack = sourceTracks[i];
7373
- const sourceTrackBinding = import_three17.PropertyBinding.parseTrackName(sourceTrack.name);
7374
- const sourceTrackNode = import_three17.PropertyBinding.findNode(root, sourceTrackBinding.nodeName);
7723
+ const sourceTrackBinding = import_three18.PropertyBinding.parseTrackName(sourceTrack.name);
7724
+ const sourceTrackNode = import_three18.PropertyBinding.findNode(root, sourceTrackBinding.nodeName);
7375
7725
  if (sourceTrackBinding.propertyName !== "morphTargetInfluences" || sourceTrackBinding.propertyIndex === void 0) {
7376
7726
  tracks.push(sourceTrack);
7377
7727
  continue;
@@ -7382,7 +7732,7 @@ GLTFExporter.Utils = {
7382
7732
  }
7383
7733
  console.warn("THREE.GLTFExporter: Morph target interpolation mode not yet supported. Using LINEAR instead.");
7384
7734
  sourceTrack = sourceTrack.clone();
7385
- sourceTrack.setInterpolation(import_three17.InterpolateLinear);
7735
+ sourceTrack.setInterpolation(import_three18.InterpolateLinear);
7386
7736
  }
7387
7737
  const targetCount = sourceTrackNode.morphTargetInfluences.length;
7388
7738
  const targetIndex = sourceTrackNode.morphTargetDictionary[sourceTrackBinding.propertyIndex];
@@ -7465,10 +7815,10 @@ var SceneExporter = class {
7465
7815
  }
7466
7816
  };
7467
7817
  function localMatrix(object) {
7468
- return object.matrixAutoUpdate ? new import_three18.Matrix4().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7818
+ return object.matrixAutoUpdate ? new import_three19.Matrix4().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7469
7819
  }
7470
7820
  function createSnapshot(root, gltf, bakeColors = false) {
7471
- const scene = new import_three18.Scene();
7821
+ const scene = new import_three19.Scene();
7472
7822
  const geometries = [];
7473
7823
  const materials = [];
7474
7824
  const textures = [];
@@ -7486,7 +7836,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7486
7836
  if (!uniforms.map?.value?.isTexture || !uniforms.SHADE || !uniforms.BRIGHTNESS || !uniforms.EMISSIVE) {
7487
7837
  throw new MineRenderError("glTF export does not support this custom ShaderMaterial");
7488
7838
  }
7489
- material = new import_three18.MeshBasicMaterial({
7839
+ material = new import_three19.MeshBasicMaterial({
7490
7840
  map: uniforms.map.value,
7491
7841
  vertexColors: source.vertexColors,
7492
7842
  transparent: source.transparent,
@@ -7496,7 +7846,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7496
7846
  });
7497
7847
  material.name = source.name;
7498
7848
  } else if (shader.isShaderMaterial) {
7499
- material = new import_three18.MeshBasicMaterial({ vertexColors: source.vertexColors });
7849
+ material = new import_three19.MeshBasicMaterial({ vertexColors: source.vertexColors });
7500
7850
  material.name = source.name;
7501
7851
  } else {
7502
7852
  const copySource = Object.create(source);
@@ -7550,11 +7900,11 @@ function createSnapshot(root, gltf, bakeColors = false) {
7550
7900
  const material = copyMaterial(sourceMaterial, geometry);
7551
7901
  if (!sourceMaterial.vertexColors) geometry.deleteAttribute("color");
7552
7902
  if (bakeColors || instanceColor) {
7553
- const tint = (material.color ?? new import_three18.Color()).clone();
7903
+ const tint = (material.color ?? new import_three19.Color()).clone();
7554
7904
  if (instanceColor) tint.multiply(instanceColor);
7555
7905
  if (bakeColors) {
7556
7906
  const original = geometry.getAttribute("color");
7557
- const colors = new import_three18.Float32BufferAttribute(new Float32Array(geometry.getAttribute("position").count * 3), 3);
7907
+ const colors = new import_three19.Float32BufferAttribute(new Float32Array(geometry.getAttribute("position").count * 3), 3);
7558
7908
  for (let i = 0; i < colors.count; i++) {
7559
7909
  colors.setXYZ(i, (original?.getX(i) ?? 1) * tint.r, (original?.getY(i) ?? 1) * tint.g, (original?.getZ(i) ?? 1) * tint.b);
7560
7910
  }
@@ -7563,7 +7913,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7563
7913
  material.color.copy(tint);
7564
7914
  }
7565
7915
  }
7566
- const copy = new import_three18.Mesh(geometry, material);
7916
+ const copy = new import_three19.Mesh(geometry, material);
7567
7917
  copy.name = mesh.name;
7568
7918
  copy.renderOrder = mesh.renderOrder;
7569
7919
  scene.add(copy);
@@ -7577,9 +7927,9 @@ function createSnapshot(root, gltf, bakeColors = false) {
7577
7927
  const instanced = mesh;
7578
7928
  if (instanced.isInstancedMesh) {
7579
7929
  for (let i = 0; i < instanced.count; i++) {
7580
- const matrix = new import_three18.Matrix4();
7930
+ const matrix = new import_three19.Matrix4();
7581
7931
  instanced.getMatrixAt(i, matrix);
7582
- const color = instanced.instanceColor ? new import_three18.Color().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7932
+ const color = instanced.instanceColor ? new import_three19.Color().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7583
7933
  addMesh(mesh, world.clone().multiply(matrix), color);
7584
7934
  }
7585
7935
  } else {
@@ -7591,7 +7941,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7591
7941
  try {
7592
7942
  const ancestors = [];
7593
7943
  for (let parent = root.parent; parent; parent = parent.parent) ancestors.unshift(parent);
7594
- const world = new import_three18.Matrix4();
7944
+ const world = new import_three19.Matrix4();
7595
7945
  for (const ancestor of ancestors) {
7596
7946
  if (!ancestor.visible) return { scene, dispose };
7597
7947
  world.multiply(localMatrix(ancestor));
@@ -7605,7 +7955,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7605
7955
  }
7606
7956
  function selectAlphaMode(material, geometry) {
7607
7957
  const texture = material.map;
7608
- if (material.type !== "MeshBasicMaterial" || !material.transparent || !material.depthWrite || material.opacity !== 1 || material.alphaMap || !texture?.isDataTexture || texture.format !== import_three18.RGBAFormat || texture.type !== import_three18.UnsignedByteType || texture.wrapS !== import_three18.ClampToEdgeWrapping || texture.wrapT !== import_three18.ClampToEdgeWrapping || texture.magFilter !== import_three18.NearestFilter || texture.minFilter !== import_three18.NearestFilter || texture.anisotropy > 1 || texture.offset.x !== 0 || texture.offset.y !== 0 || texture.repeat.x !== 1 || texture.repeat.y !== 1 || texture.rotation !== 0 || !texture.matrixAutoUpdate && !texture.matrix.elements.every((value, i) => value === (i % 4 === 0 ? 1 : 0))) return;
7958
+ if (material.type !== "MeshBasicMaterial" || !material.transparent || !material.depthWrite || material.opacity !== 1 || material.alphaMap || !texture?.isDataTexture || texture.format !== import_three19.RGBAFormat || texture.type !== import_three19.UnsignedByteType || texture.wrapS !== import_three19.ClampToEdgeWrapping || texture.wrapT !== import_three19.ClampToEdgeWrapping || texture.magFilter !== import_three19.NearestFilter || texture.minFilter !== import_three19.NearestFilter || texture.anisotropy > 1 || texture.offset.x !== 0 || texture.offset.y !== 0 || texture.repeat.x !== 1 || texture.repeat.y !== 1 || texture.rotation !== 0 || !texture.matrixAutoUpdate && !texture.matrix.elements.every((value, i) => value === (i % 4 === 0 ? 1 : 0))) return;
7609
7959
  const uv = geometry.getAttribute(texture.channel === 0 ? "uv" : `uv${texture.channel}`);
7610
7960
  const colors = geometry.getAttribute("color");
7611
7961
  if (!uv || material.vertexColors && colors?.itemSize === 4) return;
@@ -7642,7 +7992,7 @@ function selectAlphaMode(material, geometry) {
7642
7992
  }
7643
7993
  function copyDataTexture(source) {
7644
7994
  const image = source.image;
7645
- if (source.format !== import_three18.RGBAFormat || source.type !== import_three18.UnsignedByteType) {
7995
+ if (source.format !== import_three19.RGBAFormat || source.type !== import_three19.UnsignedByteType) {
7646
7996
  throw new MineRenderError("glTF export requires RGBA unsigned-byte data textures");
7647
7997
  }
7648
7998
  const canvas = createCanvas(image.width, image.height);
@@ -7653,20 +8003,78 @@ function copyDataTexture(source) {
7653
8003
  context.putImageData(pixels, 0, 0);
7654
8004
  const copySource = Object.create(source);
7655
8005
  copySource.userData = {};
7656
- copySource.source = new import_three18.Source(canvas);
7657
- return new import_three18.Texture().copy(copySource);
8006
+ copySource.source = new import_three19.Source(canvas);
8007
+ return new import_three19.Texture().copy(copySource);
7658
8008
  }
7659
8009
 
7660
8010
  // src/gui/GuiHelper.ts
8011
+ init_AssetKey();
7661
8012
  var GuiHelper = class {
7662
8013
  static inventorySlot(slot, origin = [0, 0], offset = [18, 18], rowSize = 9) {
7663
8014
  const [column, row] = typeof slot === "number" ? [slot % rowSize, Math.floor(slot / rowSize)] : slot;
7664
8015
  return [origin[0] + column * offset[0], origin[1] + row * offset[1]];
7665
8016
  }
8017
+ /** Creates crafting-table layers for ingredients and the result; stack counts are not drawn. */
8018
+ static recipe(recipe, options = {}) {
8019
+ const layers = [
8020
+ { name: "background", texture: "minecraft:gui/container/crafting_table", crop: [0, 0, 176, 166] }
8021
+ ];
8022
+ const itemKey = (ingredient) => {
8023
+ const item = typeof ingredient === "string" && !ingredient.startsWith("#") ? ingredient : typeof ingredient === "object" && "item" in ingredient ? ingredient.item : options.resolveIngredient?.(ingredient);
8024
+ if (isAssetKey(item)) return item;
8025
+ if (!item || item.startsWith("#")) {
8026
+ throw new Error(`Select a concrete item for recipe ingredient ${JSON.stringify(ingredient)}`);
8027
+ }
8028
+ const key = AssetKey.parse("models", item);
8029
+ return new AssetKey(key.namespace, key.getFullPath(), "models", "item");
8030
+ };
8031
+ const addIngredient = (ingredient, slot) => {
8032
+ layers.push({
8033
+ name: `ingredient-${slot}`,
8034
+ item: itemKey(ingredient),
8035
+ position: this.inventorySlot(slot, [30, 17], [18, 18], 3)
8036
+ });
8037
+ };
8038
+ switch (recipe.type) {
8039
+ case "minecraft:crafting_shaped":
8040
+ case "crafting_shaped": {
8041
+ const pattern = recipe.pattern;
8042
+ if (!pattern.length || pattern.length > 3 || !pattern[0].length || pattern[0].length > 3 || pattern.some((row) => row.length !== pattern[0].length)) {
8043
+ throw new Error("Crafting patterns must be rectangular, with 1\u20133 rows and columns");
8044
+ }
8045
+ const cells = pattern.flatMap((row, y) => row.split("").map((symbol, x) => ({ symbol, x, y }))).filter((cell) => cell.symbol !== " ");
8046
+ if (!cells.length) throw new Error("Crafting patterns must contain an ingredient");
8047
+ const minX = Math.min(...cells.map((cell) => cell.x)), maxX = Math.max(...cells.map((cell) => cell.x));
8048
+ const minY = Math.min(...cells.map((cell) => cell.y)), maxY = Math.max(...cells.map((cell) => cell.y));
8049
+ const offsetX = minX === maxX ? 1 : 0, offsetY = minY === maxY ? 1 : 0;
8050
+ for (const { symbol, x, y } of cells) {
8051
+ const ingredient = recipe.key[symbol];
8052
+ if (!ingredient) throw new Error(`Missing recipe ingredient for symbol ${JSON.stringify(symbol)}`);
8053
+ addIngredient(ingredient, (y - minY + offsetY) * 3 + x - minX + offsetX);
8054
+ }
8055
+ break;
8056
+ }
8057
+ case "minecraft:crafting_shapeless":
8058
+ case "crafting_shapeless":
8059
+ if (!recipe.ingredients.length || recipe.ingredients.length > 9) {
8060
+ throw new Error("Shapeless crafting recipes require 1\u20139 ingredients");
8061
+ }
8062
+ recipe.ingredients.forEach(addIngredient);
8063
+ break;
8064
+ default:
8065
+ throw new Error(`Unsupported crafting recipe type: ${recipe.type}`);
8066
+ }
8067
+ layers.push({
8068
+ name: "result",
8069
+ item: itemKey("id" in recipe.result ? recipe.result.id : recipe.result.item),
8070
+ position: [124, 35]
8071
+ });
8072
+ return layers;
8073
+ }
7666
8074
  };
7667
8075
 
7668
8076
  // src/gui/scene/GuiObject.ts
7669
- var import_three22 = require("three");
8077
+ var import_three23 = require("three");
7670
8078
  init_AssetKey();
7671
8079
  init_ModelTextures();
7672
8080
  init_Models();
@@ -7690,7 +8098,7 @@ var GuiObject = class extends SceneObject {
7690
8098
  this.textureLayers = textureLayers;
7691
8099
  this.isGuiObject = true;
7692
8100
  /** Local bounds in GUI pixels, with y growing down from the origin. */
7693
- this.bounds = new import_three22.Box2();
8101
+ this.bounds = new import_three23.Box2();
7694
8102
  this.geometries = /* @__PURE__ */ new Set();
7695
8103
  this.ownedMaterials = /* @__PURE__ */ new Set();
7696
8104
  this.initialized = false;
@@ -7707,7 +8115,7 @@ var GuiObject = class extends SceneObject {
7707
8115
  item.position.set(x + width2 / 2, -y - height2 / 2, 0);
7708
8116
  item.scale.set(width2 / 16, height2 / 16, width2 / 16);
7709
8117
  item.updateMatrix();
7710
- const bounds = new import_three22.Box3();
8118
+ const bounds = new import_three23.Box3();
7711
8119
  item.iterateAllMeshes((mesh2) => {
7712
8120
  mesh2.geometry.computeBoundingBox();
7713
8121
  bounds.union(mesh2.geometry.boundingBox);
@@ -7715,10 +8123,10 @@ var GuiObject = class extends SceneObject {
7715
8123
  bounds.applyMatrix4(item.matrix);
7716
8124
  item.position.z = depth - bounds.min.z;
7717
8125
  depth += bounds.max.z - bounds.min.z + 0.01;
7718
- this.bounds.expandByPoint(new import_three22.Vector2(x, y));
7719
- this.bounds.expandByPoint(new import_three22.Vector2(x + width2, y + height2));
7720
- this.bounds.expandByPoint(new import_three22.Vector2(bounds.min.x, -bounds.max.y));
7721
- this.bounds.expandByPoint(new import_three22.Vector2(bounds.max.x, -bounds.min.y));
8126
+ this.bounds.expandByPoint(new import_three23.Vector2(x, y));
8127
+ this.bounds.expandByPoint(new import_three23.Vector2(x + width2, y + height2));
8128
+ this.bounds.expandByPoint(new import_three23.Vector2(bounds.min.x, -bounds.max.y));
8129
+ this.bounds.expandByPoint(new import_three23.Vector2(bounds.max.x, -bounds.min.y));
7722
8130
  continue;
7723
8131
  }
7724
8132
  const key = typeof layer.texture === "string" ? AssetKey.parse("textures", layer.texture) : layer.texture;
@@ -7726,7 +8134,7 @@ var GuiObject = class extends SceneObject {
7726
8134
  const image = material.map.image;
7727
8135
  const [cropX, cropY, cropWidth, cropHeight] = layer.crop ?? [0, 0, image.width, image.height];
7728
8136
  const [width, height] = layer.size ?? [cropWidth, cropHeight];
7729
- const geometry = new import_three22.PlaneGeometry(width, height);
8137
+ const geometry = new import_three23.PlaneGeometry(width, height);
7730
8138
  this.geometries.add(geometry);
7731
8139
  const uv = geometry.getAttribute("uv");
7732
8140
  for (let i = 0; i < uv.count; i++) {
@@ -7736,13 +8144,13 @@ var GuiObject = class extends SceneObject {
7736
8144
  1 - (cropY + (1 - uv.getY(i)) * cropHeight) / image.height
7737
8145
  );
7738
8146
  }
7739
- const mesh = new import_three22.Mesh(geometry, material);
8147
+ const mesh = new import_three23.Mesh(geometry, material);
7740
8148
  mesh.name = `mesh:${layer.name ?? index}`;
7741
8149
  mesh.position.set(x + width / 2, -y - height / 2, depth);
7742
8150
  mesh.renderOrder = index;
7743
8151
  this.add(mesh);
7744
- this.bounds.expandByPoint(new import_three22.Vector2(x, y));
7745
- this.bounds.expandByPoint(new import_three22.Vector2(x + width, y + height));
8152
+ this.bounds.expandByPoint(new import_three23.Vector2(x, y));
8153
+ this.bounds.expandByPoint(new import_three23.Vector2(x + width, y + height));
7746
8154
  depth += 0.01;
7747
8155
  }
7748
8156
  for (const child of this.children) child.position.z -= depth - 0.01;
@@ -7817,7 +8225,7 @@ function isGuiObject(obj) {
7817
8225
  init_image();
7818
8226
 
7819
8227
  // src/inspector/SceneInspector.ts
7820
- var import_three23 = require("three");
8228
+ var import_three24 = require("three");
7821
8229
  init_SceneObject();
7822
8230
  init_util();
7823
8231
  init_log();
@@ -7827,11 +8235,11 @@ var help = "<span>Ctrl/Cmd+Click to Select<br/></span><br/>";
7827
8235
  var SceneInspector = class {
7828
8236
  constructor(renderer) {
7829
8237
  this.renderer = renderer;
7830
- this.mouse = new import_three23.Vector2();
8238
+ this.mouse = new import_three24.Vector2();
7831
8239
  this.listeners = new AbortController();
7832
8240
  this.objectInfoContainer = document.createElement("div");
7833
8241
  this.objectControlsContainer = document.createElement("div");
7834
- this.raycaster = new import_three23.Raycaster();
8242
+ this.raycaster = new import_three24.Raycaster();
7835
8243
  this.init();
7836
8244
  }
7837
8245
  init() {
@@ -8247,7 +8655,7 @@ init_ModelGenerator();
8247
8655
  init_ModelMerger();
8248
8656
 
8249
8657
  // src/model/block/BlockStateResolver.ts
8250
- var import_three25 = require("three");
8658
+ var import_three26 = require("three");
8251
8659
  init_BlockStates();
8252
8660
  init_MineRenderError();
8253
8661
  init_util();
@@ -8325,7 +8733,7 @@ var BlockStateResolver = class {
8325
8733
  return variants[variants.length - 1];
8326
8734
  }
8327
8735
  static rotation(variant) {
8328
- const rotation = new import_three25.Euler();
8736
+ const rotation = new import_three26.Euler();
8329
8737
  if (typeof variant.x !== "undefined") {
8330
8738
  rotation.x = toRadians(clampRotationDegrees(variant.x));
8331
8739
  }
@@ -8432,7 +8840,7 @@ init_SceneObject();
8432
8840
  init_ModelObject();
8433
8841
  init_Models();
8434
8842
  var import_ts_deepmerge6 = __toESM(require_dist());
8435
- var import_three28 = require("three");
8843
+ var import_three29 = require("three");
8436
8844
  init_MineRenderError();
8437
8845
  init_InstanceReference();
8438
8846
  init_AssetKey();
@@ -8452,6 +8860,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
8452
8860
  this._variants = [];
8453
8861
  this._models = [];
8454
8862
  this._cullMask = 0;
8863
+ this._entities = [];
8864
+ this._entityPlacement = new import_three29.Matrix4();
8865
+ this._entityGeneration = 0;
8455
8866
  this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
8456
8867
  }
8457
8868
  async init() {
@@ -8471,6 +8882,8 @@ var _BlockObject = class _BlockObject extends SceneObject {
8471
8882
  }
8472
8883
  clearModels() {
8473
8884
  this.removeModels(this._models.splice(0));
8885
+ this._entityGeneration++;
8886
+ this.removeEntities(this._entities.splice(0));
8474
8887
  this._fluidKey = void 0;
8475
8888
  this._fluidModel = void 0;
8476
8889
  this._isInstanced = false;
@@ -8482,6 +8895,57 @@ var _BlockObject = class _BlockObject extends SceneObject {
8482
8895
  if (!isInstanceReference(model)) model.dispose();
8483
8896
  }
8484
8897
  }
8898
+ removeEntities(entities) {
8899
+ for (const entity of entities) {
8900
+ entity.removeFromScene();
8901
+ entity.dispose();
8902
+ }
8903
+ }
8904
+ /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */
8905
+ get blockEntities() {
8906
+ return this._entities;
8907
+ }
8908
+ /**
8909
+ * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
8910
+ * when the block is not listed or one of its models cannot be loaded.
8911
+ */
8912
+ async createBlockEntities() {
8913
+ const key = this.blockState.key;
8914
+ if (!key || this.options.displayPosition) return false;
8915
+ const generation = this._entityGeneration;
8916
+ const created = [];
8917
+ let resolved;
8918
+ try {
8919
+ resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);
8920
+ if (!resolved) return false;
8921
+ for (const part of resolved.parts) {
8922
+ const [namespace, path] = part.model.includes(":") ? part.model.split(":") : [key.namespace, part.model];
8923
+ const texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
8924
+ if (texture) texture.root = key.root;
8925
+ const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });
8926
+ if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);
8927
+ created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }));
8928
+ }
8929
+ } catch (error) {
8930
+ console.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);
8931
+ this.removeEntities(created);
8932
+ return false;
8933
+ }
8934
+ if (generation !== this._entityGeneration) {
8935
+ this.removeEntities(created);
8936
+ return true;
8937
+ }
8938
+ BlockEntities.matrix(resolved, this._entityPlacement);
8939
+ this._entities = created;
8940
+ this.placeEntities();
8941
+ return true;
8942
+ }
8943
+ placeEntities() {
8944
+ const matrix = new import_three29.Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
8945
+ for (const entity of this._entities) {
8946
+ matrix.decompose(entity.position, entity.quaternion, entity.scale);
8947
+ }
8948
+ }
8485
8949
  get isOccluding() {
8486
8950
  return this._models.some((model) => {
8487
8951
  const object = isInstanceReference(model) ? model.instanceable : model;
@@ -8496,12 +8960,12 @@ var _BlockObject = class _BlockObject extends SceneObject {
8496
8960
  getModelCullMask(model, worldMask) {
8497
8961
  const object = isInstanceReference(model) ? model.instanceable : model;
8498
8962
  if (object.options.displayPosition) return 0;
8499
- const position = new import_three28.Vector3();
8500
- const rotation = new import_three28.Quaternion();
8501
- const scale = new import_three28.Vector3();
8963
+ const position = new import_three29.Vector3();
8964
+ const rotation = new import_three29.Quaternion();
8965
+ const scale = new import_three29.Vector3();
8502
8966
  this.getModelMatrix(model).decompose(position, rotation, scale);
8503
- if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new import_three28.Vector3(1, 1, 1)) > 1e-10) return 0;
8504
- return ModelCulling.toLocalMask(worldMask, new import_three28.Euler().setFromQuaternion(rotation));
8967
+ if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new import_three29.Vector3(1, 1, 1)) > 1e-10) return 0;
8968
+ return ModelCulling.toLocalMask(worldMask, new import_three29.Euler().setFromQuaternion(rotation));
8505
8969
  }
8506
8970
  async setCullMask(worldMask) {
8507
8971
  worldMask &= 63;
@@ -8563,7 +9027,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
8563
9027
  () => new FluidModelObject2(kind, surface.sample, this.blockState.key, this.options)
8564
9028
  );
8565
9029
  const previous = this._fluidModel;
8566
- const matrix = previous ? this.getModelMatrix(previous) : new import_three28.Matrix4().makeTranslation(...this.position.toArray());
9030
+ const matrix = previous ? this.getModelMatrix(previous) : new import_three29.Matrix4().makeTranslation(...this.position.toArray());
8567
9031
  if (isInstanceReference(replacement)) replacement.setMatrix(matrix);
8568
9032
  else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
8569
9033
  this._models = this._models.filter((model) => model !== previous);
@@ -8593,13 +9057,20 @@ var _BlockObject = class _BlockObject extends SceneObject {
8593
9057
  await this.updateFluid(this._fluidSampler);
8594
9058
  return;
8595
9059
  }
9060
+ const hasEntities = await this.createBlockEntities();
8596
9061
  const variantsToCreate = await this.mapStateToVariant(this.state);
8597
9062
  this._variants = variantsToCreate;
8598
9063
  for (let blockStateVariant of variantsToCreate) {
9064
+ if (hasEntities && !await this.hasGeometry(blockStateVariant)) continue;
8599
9065
  this._models.push(await this.createVariant(blockStateVariant));
8600
9066
  }
8601
9067
  await this.updateFluid(this._fluidSampler);
8602
9068
  }
9069
+ async hasGeometry(variant) {
9070
+ const modelKey = AssetKey.parse("models", variant.model);
9071
+ modelKey.root = this.blockState.key?.root;
9072
+ return !!(await Models.getMerged(modelKey))?.elements?.length;
9073
+ }
8603
9074
  getSingleVariant(variants) {
8604
9075
  return BlockStateResolver.choose(variants);
8605
9076
  }
@@ -8694,7 +9165,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
8694
9165
  setPositionRotationScaleAt(index, position, rotation, scale) {
8695
9166
  super.setPositionRotationScaleAt(index, position, rotation, scale);
8696
9167
  }
8697
- getMatrixAt(index, matrix = new import_three28.Matrix4()) {
9168
+ getMatrixAt(index, matrix = new import_three29.Matrix4()) {
8698
9169
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
8699
9170
  const child = this._models[0];
8700
9171
  if (child && isModelObject(child)) {
@@ -8719,6 +9190,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
8719
9190
  for (let model of this._models) {
8720
9191
  model.setPosition(position);
8721
9192
  }
9193
+ this.placeEntities();
8722
9194
  this.notifyDirty();
8723
9195
  }
8724
9196
  //TODO: should override rotation + scale methods
@@ -10564,7 +11036,7 @@ init_ModelObject();
10564
11036
  init_nbt();
10565
11037
 
10566
11038
  // src/renderer/MineRenderScene.ts
10567
- var import_three30 = require("three");
11039
+ var import_three31 = require("three");
10568
11040
  init_SceneObject();
10569
11041
  var import_ts_deepmerge8 = __toESM(require_dist());
10570
11042
  init_ModelObject();
@@ -11297,7 +11769,7 @@ var import_ts_deepmerge7 = __toESM(require_dist());
11297
11769
  init_util();
11298
11770
 
11299
11771
  // src/skin/SkinTextures.ts
11300
- var import_three29 = require("three");
11772
+ var import_three30 = require("three");
11301
11773
  init_Caching();
11302
11774
  init_CacheKey();
11303
11775
  init_MineRenderError();
@@ -11381,11 +11853,11 @@ var SkinTextures = class {
11381
11853
  });
11382
11854
  }
11383
11855
  static createMaterial(pixels, width, height, transparent = true) {
11384
- const texture = Textures.initTextureProps(new import_three29.DataTexture(pixels, width, height));
11385
- texture.colorSpace = import_three29.SRGBColorSpace;
11856
+ const texture = Textures.initTextureProps(new import_three30.DataTexture(pixels, width, height));
11857
+ texture.colorSpace = import_three30.SRGBColorSpace;
11386
11858
  texture.flipY = true;
11387
11859
  texture.needsUpdate = true;
11388
- return new import_three29.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three29.DoubleSide : import_three29.FrontSide, alphaTest: transparent ? 0.1 : 0 });
11860
+ return new import_three30.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three30.DoubleSide : import_three30.FrontSide, alphaTest: transparent ? 0.1 : 0 });
11389
11861
  }
11390
11862
  static isSlim(image, scale) {
11391
11863
  for (const [x, y] of [[46, 52], [54, 20]]) {
@@ -11613,7 +12085,7 @@ var SkinObject = class extends SceneObject {
11613
12085
  };
11614
12086
 
11615
12087
  // src/renderer/MineRenderScene.ts
11616
- var _MineRenderScene = class _MineRenderScene extends import_three30.Scene {
12088
+ var _MineRenderScene = class _MineRenderScene extends import_three31.Scene {
11617
12089
  constructor(options) {
11618
12090
  super();
11619
12091
  this.isMineRenderScene = true;
@@ -11740,7 +12212,7 @@ function isMineRenderScene(obj) {
11740
12212
  }
11741
12213
 
11742
12214
  // src/renderer/Renderer.ts
11743
- var import_three32 = require("three");
12215
+ var import_three33 = require("three");
11744
12216
  var import_ts_deepmerge9 = __toESM(require_dist());
11745
12217
  var import_stats = __toESM(require("stats.js"));
11746
12218
  var import_postprocessing = require("postprocessing");
@@ -11748,11 +12220,11 @@ init_util();
11748
12220
  init_three();
11749
12221
 
11750
12222
  // src/three/OrbitControls.js
11751
- var import_three31 = require("three");
12223
+ var import_three32 = require("three");
11752
12224
  var _changeEvent = { type: "change" };
11753
12225
  var _startEvent = { type: "start" };
11754
12226
  var _endEvent = { type: "end" };
11755
- var OrbitControls = class extends import_three31.EventDispatcher {
12227
+ var OrbitControls = class extends import_three32.EventDispatcher {
11756
12228
  constructor(object, domElement) {
11757
12229
  super();
11758
12230
  if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
@@ -11761,7 +12233,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11761
12233
  this.domElement = domElement;
11762
12234
  this.domElement.style.touchAction = "none";
11763
12235
  this.enabled = true;
11764
- this.target = new import_three31.Vector3();
12236
+ this.target = new import_three32.Vector3();
11765
12237
  this.minDistance = 0;
11766
12238
  this.maxDistance = Infinity;
11767
12239
  this.minZoom = 0;
@@ -11783,8 +12255,8 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11783
12255
  this.autoRotate = false;
11784
12256
  this.autoRotateSpeed = 2;
11785
12257
  this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
11786
- this.mouseButtons = { LEFT: import_three31.MOUSE.ROTATE, MIDDLE: import_three31.MOUSE.DOLLY, RIGHT: import_three31.MOUSE.PAN };
11787
- this.touches = { ONE: import_three31.TOUCH.ROTATE, TWO: import_three31.TOUCH.DOLLY_PAN };
12258
+ this.mouseButtons = { LEFT: import_three32.MOUSE.ROTATE, MIDDLE: import_three32.MOUSE.DOLLY, RIGHT: import_three32.MOUSE.PAN };
12259
+ this.touches = { ONE: import_three32.TOUCH.ROTATE, TWO: import_three32.TOUCH.DOLLY_PAN };
11788
12260
  this.target0 = this.target.clone();
11789
12261
  this.position0 = this.object.position.clone();
11790
12262
  this.zoom0 = this.object.zoom;
@@ -11813,11 +12285,11 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11813
12285
  state = STATE.NONE;
11814
12286
  };
11815
12287
  this.update = function() {
11816
- const offset = new import_three31.Vector3();
11817
- const quat = new import_three31.Quaternion().setFromUnitVectors(object.up, new import_three31.Vector3(0, 1, 0));
12288
+ const offset = new import_three32.Vector3();
12289
+ const quat = new import_three32.Quaternion().setFromUnitVectors(object.up, new import_three32.Vector3(0, 1, 0));
11818
12290
  const quatInverse = quat.clone().invert();
11819
- const lastPosition = new import_three31.Vector3();
11820
- const lastQuaternion = new import_three31.Quaternion();
12291
+ const lastPosition = new import_three32.Vector3();
12292
+ const lastQuaternion = new import_three32.Quaternion();
11821
12293
  const twoPI = 2 * Math.PI;
11822
12294
  return function update() {
11823
12295
  const position = scope.object.position;
@@ -11903,20 +12375,20 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11903
12375
  };
11904
12376
  let state = STATE.NONE;
11905
12377
  const EPS = 1e-6;
11906
- const spherical = new import_three31.Spherical();
11907
- const sphericalDelta = new import_three31.Spherical();
12378
+ const spherical = new import_three32.Spherical();
12379
+ const sphericalDelta = new import_three32.Spherical();
11908
12380
  let scale = 1;
11909
- const panOffset = new import_three31.Vector3();
12381
+ const panOffset = new import_three32.Vector3();
11910
12382
  let zoomChanged = false;
11911
- const rotateStart = new import_three31.Vector2();
11912
- const rotateEnd = new import_three31.Vector2();
11913
- const rotateDelta = new import_three31.Vector2();
11914
- const panStart = new import_three31.Vector2();
11915
- const panEnd = new import_three31.Vector2();
11916
- const panDelta = new import_three31.Vector2();
11917
- const dollyStart = new import_three31.Vector2();
11918
- const dollyEnd = new import_three31.Vector2();
11919
- const dollyDelta = new import_three31.Vector2();
12383
+ const rotateStart = new import_three32.Vector2();
12384
+ const rotateEnd = new import_three32.Vector2();
12385
+ const rotateDelta = new import_three32.Vector2();
12386
+ const panStart = new import_three32.Vector2();
12387
+ const panEnd = new import_three32.Vector2();
12388
+ const panDelta = new import_three32.Vector2();
12389
+ const dollyStart = new import_three32.Vector2();
12390
+ const dollyEnd = new import_three32.Vector2();
12391
+ const dollyDelta = new import_three32.Vector2();
11920
12392
  const pointers = [];
11921
12393
  const pointerPositions = {};
11922
12394
  function getAutoRotationAngle() {
@@ -11932,7 +12404,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11932
12404
  sphericalDelta.phi -= angle;
11933
12405
  }
11934
12406
  const panLeft = function() {
11935
- const v = new import_three31.Vector3();
12407
+ const v = new import_three32.Vector3();
11936
12408
  return function panLeft2(distance, objectMatrix) {
11937
12409
  v.setFromMatrixColumn(objectMatrix, 0);
11938
12410
  v.multiplyScalar(-distance);
@@ -11940,7 +12412,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11940
12412
  };
11941
12413
  }();
11942
12414
  const panUp = function() {
11943
- const v = new import_three31.Vector3();
12415
+ const v = new import_three32.Vector3();
11944
12416
  return function panUp2(distance, objectMatrix) {
11945
12417
  if (scope.screenSpacePanning === true) {
11946
12418
  v.setFromMatrixColumn(objectMatrix, 1);
@@ -11953,7 +12425,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11953
12425
  };
11954
12426
  }();
11955
12427
  const pan = function() {
11956
- const offset = new import_three31.Vector3();
12428
+ const offset = new import_three32.Vector3();
11957
12429
  return function pan2(deltaX, deltaY) {
11958
12430
  const element = scope.domElement;
11959
12431
  if (scope.object.isPerspectiveCamera) {
@@ -12202,12 +12674,12 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12202
12674
  mouseAction = -1;
12203
12675
  }
12204
12676
  switch (mouseAction) {
12205
- case import_three31.MOUSE.DOLLY:
12677
+ case import_three32.MOUSE.DOLLY:
12206
12678
  if (scope.enableZoom === false) return;
12207
12679
  handleMouseDownDolly(event);
12208
12680
  state = STATE.DOLLY;
12209
12681
  break;
12210
- case import_three31.MOUSE.ROTATE:
12682
+ case import_three32.MOUSE.ROTATE:
12211
12683
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
12212
12684
  if (scope.enablePan === false) return;
12213
12685
  handleMouseDownPan(event);
@@ -12218,7 +12690,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12218
12690
  state = STATE.ROTATE;
12219
12691
  }
12220
12692
  break;
12221
- case import_three31.MOUSE.PAN:
12693
+ case import_three32.MOUSE.PAN:
12222
12694
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
12223
12695
  if (scope.enableRotate === false) return;
12224
12696
  handleMouseDownRotate(event);
@@ -12274,12 +12746,12 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12274
12746
  switch (pointers.length) {
12275
12747
  case 1:
12276
12748
  switch (scope.touches.ONE) {
12277
- case import_three31.TOUCH.ROTATE:
12749
+ case import_three32.TOUCH.ROTATE:
12278
12750
  if (scope.enableRotate === false) return;
12279
12751
  handleTouchStartRotate();
12280
12752
  state = STATE.TOUCH_ROTATE;
12281
12753
  break;
12282
- case import_three31.TOUCH.PAN:
12754
+ case import_three32.TOUCH.PAN:
12283
12755
  if (scope.enablePan === false) return;
12284
12756
  handleTouchStartPan();
12285
12757
  state = STATE.TOUCH_PAN;
@@ -12290,12 +12762,12 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12290
12762
  break;
12291
12763
  case 2:
12292
12764
  switch (scope.touches.TWO) {
12293
- case import_three31.TOUCH.DOLLY_PAN:
12765
+ case import_three32.TOUCH.DOLLY_PAN:
12294
12766
  if (scope.enableZoom === false && scope.enablePan === false) return;
12295
12767
  handleTouchStartDollyPan();
12296
12768
  state = STATE.TOUCH_DOLLY_PAN;
12297
12769
  break;
12298
- case import_three31.TOUCH.DOLLY_ROTATE:
12770
+ case import_three32.TOUCH.DOLLY_ROTATE:
12299
12771
  if (scope.enableZoom === false && scope.enableRotate === false) return;
12300
12772
  handleTouchStartDollyRotate();
12301
12773
  state = STATE.TOUCH_DOLLY_ROTATE;
@@ -12362,7 +12834,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12362
12834
  function trackPointer(event) {
12363
12835
  let position = pointerPositions[event.pointerId];
12364
12836
  if (position === void 0) {
12365
- position = new import_three31.Vector2();
12837
+ position = new import_three32.Vector2();
12366
12838
  pointerPositions[event.pointerId] = position;
12367
12839
  }
12368
12840
  position.set(event.pageX, event.pageY);
@@ -12382,10 +12854,10 @@ var MapControls = class extends OrbitControls {
12382
12854
  constructor(object, domElement) {
12383
12855
  super(object, domElement);
12384
12856
  this.screenSpacePanning = false;
12385
- this.mouseButtons.LEFT = import_three31.MOUSE.PAN;
12386
- this.mouseButtons.RIGHT = import_three31.MOUSE.ROTATE;
12387
- this.touches.ONE = import_three31.TOUCH.PAN;
12388
- this.touches.TWO = import_three31.TOUCH.DOLLY_ROTATE;
12857
+ this.mouseButtons.LEFT = import_three32.MOUSE.PAN;
12858
+ this.mouseButtons.RIGHT = import_three32.MOUSE.ROTATE;
12859
+ this.touches.ONE = import_three32.TOUCH.PAN;
12860
+ this.touches.TWO = import_three32.TOUCH.DOLLY_ROTATE;
12389
12861
  }
12390
12862
  };
12391
12863
 
@@ -12436,14 +12908,14 @@ var _Renderer = class _Renderer {
12436
12908
  switch (this.options.camera.type) {
12437
12909
  case "perspective":
12438
12910
  default:
12439
- return new import_three32.PerspectiveCamera(
12911
+ return new import_three33.PerspectiveCamera(
12440
12912
  this.options.camera.perspective.fov,
12441
12913
  this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
12442
12914
  this.options.camera.near,
12443
12915
  this.options.camera.far
12444
12916
  );
12445
12917
  case "orthographic":
12446
- return new import_three32.OrthographicCamera(
12918
+ return new import_three33.OrthographicCamera(
12447
12919
  this.options.camera.orthographic.left ?? this.viewWidth / -2,
12448
12920
  this.options.camera.orthographic.right ?? this.viewWidth / 2,
12449
12921
  this.options.camera.orthographic.top ?? this.viewHeight / 2,
@@ -12454,7 +12926,7 @@ var _Renderer = class _Renderer {
12454
12926
  }
12455
12927
  }
12456
12928
  createRenderer() {
12457
- const renderer = new import_three32.WebGLRenderer({
12929
+ const renderer = new import_three33.WebGLRenderer({
12458
12930
  antialias: this.options.render.antialias,
12459
12931
  alpha: true,
12460
12932
  powerPreference: "high-performance",
@@ -12462,8 +12934,8 @@ var _Renderer = class _Renderer {
12462
12934
  });
12463
12935
  renderer.setClearColor(0, 0);
12464
12936
  renderer.shadowMap.enabled = true;
12465
- renderer.shadowMap.type = import_three32.PCFSoftShadowMap;
12466
- renderer.outputColorSpace = import_three32.SRGBColorSpace;
12937
+ renderer.shadowMap.type = import_three33.PCFSoftShadowMap;
12938
+ renderer.outputColorSpace = import_three33.SRGBColorSpace;
12467
12939
  renderer.setPixelRatio(this.options.render.pixelRatio ?? 1);
12468
12940
  renderer.setSize(this.viewWidth, this.viewHeight);
12469
12941
  return renderer;
@@ -12498,20 +12970,20 @@ var _Renderer = class _Renderer {
12498
12970
  window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
12499
12971
  }
12500
12972
  if (this.options.debug.grid) {
12501
- const gridHelper = new import_three32.GridHelper(128, 16);
12973
+ const gridHelper = new import_three33.GridHelper(128, 16);
12502
12974
  this._debugHelpers.push(gridHelper);
12503
12975
  this.scene.add(gridHelper);
12504
- const gridHelper2 = new import_three32.GridHelper(128, 16);
12976
+ const gridHelper2 = new import_three33.GridHelper(128, 16);
12505
12977
  this._debugHelpers.push(gridHelper2);
12506
12978
  gridHelper2.rotation.x = 90 * (Math.PI / 180);
12507
12979
  this.scene.add(gridHelper2);
12508
- const gridHelper3 = new import_three32.GridHelper(128, 16);
12980
+ const gridHelper3 = new import_three33.GridHelper(128, 16);
12509
12981
  this._debugHelpers.push(gridHelper3);
12510
12982
  gridHelper3.rotation.z = 90 * (Math.PI / 180);
12511
12983
  this.scene.add(gridHelper3);
12512
12984
  }
12513
12985
  if (this.options.debug.axes) {
12514
- const axesHelper = new import_three32.AxesHelper(64);
12986
+ const axesHelper = new import_three33.AxesHelper(64);
12515
12987
  this._debugHelpers.push(axesHelper);
12516
12988
  this.scene.add(axesHelper);
12517
12989
  }
@@ -12770,8 +13242,8 @@ _Renderer.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {
12770
13242
  top: void 0,
12771
13243
  bottom: void 0
12772
13244
  },
12773
- position: new import_three32.Vector3(50, 50, 50),
12774
- lookingAt: new import_three32.Vector3(0, 0, 0)
13245
+ position: new import_three33.Vector3(50, 50, 50),
13246
+ lookingAt: new import_three33.Vector3(0, 0, 0)
12775
13247
  },
12776
13248
  render: {
12777
13249
  fpsLimit: 60,
@@ -13235,19 +13707,19 @@ var AnvilParser = class {
13235
13707
  };
13236
13708
 
13237
13709
  // src/world/Chunk.ts
13238
- var import_three37 = require("three");
13710
+ var import_three38 = require("three");
13239
13711
  init_BlockStates();
13240
13712
  init_AssetKey();
13241
13713
 
13242
13714
  // src/world/MineRenderWorld.ts
13243
- var import_three35 = require("three");
13715
+ var import_three36 = require("three");
13244
13716
  init_BatchedExecutor();
13245
13717
  init_AssetKey();
13246
13718
  init_BlockStates();
13247
13719
  init_CubeFace();
13248
13720
 
13249
13721
  // src/world/SectionModels.ts
13250
- var import_three34 = require("three");
13722
+ var import_three35 = require("three");
13251
13723
  init_AssetKey();
13252
13724
  init_Models();
13253
13725
  init_CubeFace();
@@ -13313,12 +13785,12 @@ var SectionModels = class {
13313
13785
  });
13314
13786
  await object.init();
13315
13787
  const geometry = object.children[0].geometry;
13316
- geometry.applyMatrix4(new import_three34.Matrix4().makeRotationFromEuler(rotation));
13788
+ geometry.applyMatrix4(new import_three35.Matrix4().makeRotationFromEuler(rotation));
13317
13789
  object.clear();
13318
13790
  const cullFaces = CUBE_FACES.map((face) => {
13319
13791
  const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
13320
13792
  if (local < 0) return 0;
13321
- const normal = new import_three34.Vector3(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
13793
+ const normal = new import_three35.Vector3(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
13322
13794
  const world = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
13323
13795
  return 1 << world;
13324
13796
  });
@@ -13348,20 +13820,20 @@ var MineRenderWorld = class {
13348
13820
  }
13349
13821
  getBlockAt(posOrX, y, z) {
13350
13822
  if (typeof posOrX == "number") {
13351
- return this.getBlockAt(new import_three35.Vector3(posOrX, y, z));
13823
+ return this.getBlockAt(new import_three36.Vector3(posOrX, y, z));
13352
13824
  }
13353
13825
  if (isTripleArray(posOrX)) {
13354
- return this.getBlockAt(new import_three35.Vector3(posOrX[0], posOrX[1], posOrX[2]));
13826
+ return this.getBlockAt(new import_three36.Vector3(posOrX[0], posOrX[1], posOrX[2]));
13355
13827
  }
13356
13828
  this.validatePosBounds(posOrX);
13357
13829
  return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
13358
13830
  }
13359
13831
  async setBlockAt(posOrX, yOrBlock, z, block) {
13360
13832
  if (typeof posOrX == "number") {
13361
- return this.setBlockAt(new import_three35.Vector3(posOrX, yOrBlock, z), block);
13833
+ return this.setBlockAt(new import_three36.Vector3(posOrX, yOrBlock, z), block);
13362
13834
  }
13363
13835
  if (isTripleArray(posOrX)) {
13364
- return this.setBlockAt(new import_three35.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
13836
+ return this.setBlockAt(new import_three36.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
13365
13837
  }
13366
13838
  return this.placeBlock(posOrX, yOrBlock);
13367
13839
  }
@@ -13382,7 +13854,7 @@ var MineRenderWorld = class {
13382
13854
  const collect = async (positions2) => {
13383
13855
  for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
13384
13856
  };
13385
- const place = (block) => this.placeBlock(new import_three35.Vector3(...block.position), block, collect);
13857
+ const place = (block) => this.placeBlock(new import_three36.Vector3(...block.position), block, collect);
13386
13858
  const keys = /* @__PURE__ */ new Map();
13387
13859
  for (const block of multiblock.blocks) {
13388
13860
  if (Chunk.isAir(block)) continue;
@@ -13460,13 +13932,13 @@ var MineRenderWorld = class {
13460
13932
  for (const pos of positions) {
13461
13933
  this.pendingCulling.set(pos.toArray().join(","), pos.clone());
13462
13934
  for (const offset of CUBE_FACE_OFFSETS) {
13463
- const neighbor = pos.clone().add(new import_three35.Vector3(...offset));
13935
+ const neighbor = pos.clone().add(new import_three36.Vector3(...offset));
13464
13936
  this.pendingCulling.set(neighbor.toArray().join(","), neighbor);
13465
13937
  }
13466
13938
  for (let y = -1; y <= 1; y++) {
13467
13939
  for (let z = -1; z <= 1; z++) {
13468
13940
  for (let x = -1; x <= 1; x++) {
13469
- const neighbor = pos.clone().add(new import_three35.Vector3(x, y, z));
13941
+ const neighbor = pos.clone().add(new import_three36.Vector3(x, y, z));
13470
13942
  if (this.getBlockAt(neighbor)?.object?.fluidKind) {
13471
13943
  this.pendingCulling.set(neighbor.toArray().join(","), neighbor);
13472
13944
  }
@@ -13488,7 +13960,7 @@ var MineRenderWorld = class {
13488
13960
  if (!block) continue;
13489
13961
  if (block.object?.fluidKind) {
13490
13962
  await block.object.updateFluid((x, y, z) => {
13491
- const neighbor = pos.clone().add(new import_three35.Vector3(x, y, z));
13963
+ const neighbor = pos.clone().add(new import_three36.Vector3(x, y, z));
13492
13964
  const section = this.getChunkAt(neighbor);
13493
13965
  const object = section?.getBlockAt(neighbor)?.object;
13494
13966
  return {
@@ -13500,7 +13972,7 @@ var MineRenderWorld = class {
13500
13972
  }
13501
13973
  let mask = 0;
13502
13974
  for (const [face, offset] of CUBE_FACE_OFFSETS.entries()) {
13503
- const neighbor = pos.clone().add(new import_three35.Vector3(...offset));
13975
+ const neighbor = pos.clone().add(new import_three36.Vector3(...offset));
13504
13976
  if (this.getChunkAt(neighbor)?.isOccludingAt(neighbor)) {
13505
13977
  mask |= 1 << face;
13506
13978
  }
@@ -13534,14 +14006,14 @@ var MineRenderWorld = class {
13534
14006
  return this._chunks.get(this.worldPosToChunkKey(pos));
13535
14007
  }
13536
14008
  static worldToScenePosition(pos) {
13537
- return new import_three35.Vector3(
14009
+ return new import_three36.Vector3(
13538
14010
  pos.x * 16,
13539
14011
  pos.y * 16,
13540
14012
  pos.z * 16
13541
14013
  );
13542
14014
  }
13543
14015
  static sceneToWorldPosition(pos) {
13544
- return new import_three35.Vector3(
14016
+ return new import_three36.Vector3(
13545
14017
  pos.x / 16,
13546
14018
  pos.y / 16,
13547
14019
  pos.z / 16
@@ -13561,10 +14033,10 @@ var MineRenderWorld = class {
13561
14033
  };
13562
14034
 
13563
14035
  // src/world/SectionMesh.ts
13564
- var import_three36 = require("three");
14036
+ var import_three37 = require("three");
13565
14037
  init_CanvasCompat();
13566
14038
  init_Materials();
13567
- var SectionMesh = class _SectionMesh extends import_three36.Group {
14039
+ var SectionMesh = class _SectionMesh extends import_three37.Group {
13568
14040
  constructor() {
13569
14041
  super(...arguments);
13570
14042
  this.ownedMeshes = [];
@@ -13637,18 +14109,18 @@ var SectionMesh = class _SectionMesh extends import_three36.Group {
13637
14109
  for (let corner = 0; corner < 6; corner++) indices.push(start + sourceIndices.getX(face * 6 + corner) - face * 4);
13638
14110
  }
13639
14111
  }
13640
- const geometry = new import_three36.BufferGeometry();
13641
- geometry.setAttribute("position", new import_three36.Float32BufferAttribute(positions, 3));
13642
- geometry.setAttribute("normal", new import_three36.Float32BufferAttribute(normals, 3));
13643
- geometry.setAttribute("uv", new import_three36.Float32BufferAttribute(uvs, 2));
13644
- geometry.setAttribute("color", new import_three36.Float32BufferAttribute(colors, 3));
14112
+ const geometry = new import_three37.BufferGeometry();
14113
+ geometry.setAttribute("position", new import_three37.Float32BufferAttribute(positions, 3));
14114
+ geometry.setAttribute("normal", new import_three37.Float32BufferAttribute(normals, 3));
14115
+ geometry.setAttribute("uv", new import_three37.Float32BufferAttribute(uvs, 2));
14116
+ geometry.setAttribute("color", new import_three37.Float32BufferAttribute(colors, 3));
13645
14117
  geometry.setIndex(indices);
13646
14118
  geometry.computeBoundingBox();
13647
14119
  geometry.computeBoundingSphere();
13648
14120
  const material = Materials.createShadedCanvasMaterial(canvas, false);
13649
14121
  material.vertexColors = true;
13650
14122
  const texture = material.uniforms?.map?.value ?? material.map;
13651
- const mesh = new import_three36.Mesh(geometry, material);
14123
+ const mesh = new import_three37.Mesh(geometry, material);
13652
14124
  section.add(mesh);
13653
14125
  section.ownedMeshes.push({ mesh, texture });
13654
14126
  }
@@ -13682,10 +14154,10 @@ var Chunk = class _Chunk {
13682
14154
  }
13683
14155
  getBlockAt(posOrX, y, z) {
13684
14156
  if (typeof posOrX == "number") {
13685
- return this.getBlockAt(new import_three37.Vector3(posOrX, y, z));
14157
+ return this.getBlockAt(new import_three38.Vector3(posOrX, y, z));
13686
14158
  }
13687
14159
  if (isTripleArray(posOrX)) {
13688
- return this.getBlockAt(new import_three37.Vector3(posOrX[0], posOrX[1], posOrX[2]));
14160
+ return this.getBlockAt(new import_three38.Vector3(posOrX[0], posOrX[1], posOrX[2]));
13689
14161
  }
13690
14162
  const pos = this.worldPosToChunkPos(posOrX);
13691
14163
  const index = _Chunk.chunkPosToBlockIndex(pos);
@@ -13693,10 +14165,10 @@ var Chunk = class _Chunk {
13693
14165
  }
13694
14166
  async setBlockAt(posOrX, yOrBlock, z, block) {
13695
14167
  if (typeof posOrX == "number") {
13696
- return this.setBlockAt(new import_three37.Vector3(posOrX, yOrBlock, z), block);
14168
+ return this.setBlockAt(new import_three38.Vector3(posOrX, yOrBlock, z), block);
13697
14169
  }
13698
14170
  if (isTripleArray(posOrX)) {
13699
- return this.setBlockAt(new import_three37.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
14171
+ return this.setBlockAt(new import_three38.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
13700
14172
  }
13701
14173
  const worldPos = posOrX;
13702
14174
  const pos = this.worldPosToChunkPos(worldPos);
@@ -13725,7 +14197,8 @@ var Chunk = class _Chunk {
13725
14197
  this.data.set(index, void 0);
13726
14198
  return void 0;
13727
14199
  }
13728
- const template = getFluidKind(blockState.key, stored.properties) ? void 0 : await this.sectionModels?.get(blockState, stored.properties);
14200
+ const perBlock = !this.sectionModels || getFluidKind(blockState.key, stored.properties) || blockState.key && BlockEntities.entry(await BlockEntities.getIndex(blockState.key.root), blockState.key.toNamespacedString());
14201
+ const template = perBlock ? void 0 : await this.sectionModels.get(blockState, stored.properties);
13729
14202
  if (template) {
13730
14203
  this.sectionBlocks.set(index, { index, template, cullMask: 0 });
13731
14204
  this.meshDirty = true;
@@ -13781,7 +14254,7 @@ var Chunk = class _Chunk {
13781
14254
  }
13782
14255
  async clear(onBlocksChanged = this.onBlocksChanged) {
13783
14256
  const positions = [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
13784
- new import_three37.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
14257
+ new import_three38.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
13785
14258
  ));
13786
14259
  for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
13787
14260
  this.sectionBlocks.clear();
@@ -13805,14 +14278,14 @@ var Chunk = class _Chunk {
13805
14278
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
13806
14279
  }
13807
14280
  worldPosToChunkPos(pos) {
13808
- return new import_three37.Vector3(
14281
+ return new import_three38.Vector3(
13809
14282
  pos.x - this.x * 16,
13810
14283
  pos.y - this.y * 16,
13811
14284
  pos.z - this.z * 16
13812
14285
  );
13813
14286
  }
13814
14287
  chunkPosToWorldPos(pos) {
13815
- return new import_three37.Vector3(
14288
+ return new import_three38.Vector3(
13816
14289
  this.x * 16 + pos.x,
13817
14290
  this.y * 16 + pos.y,
13818
14291
  this.z * 16 + pos.z