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.
@@ -291,6 +291,12 @@ var init_Caching = __esm({
291
291
  static {
292
292
  this.entityTextureCache = _Caching.createAssetCache();
293
293
  }
294
+ static {
295
+ this.entityAnimationCache = _Caching.createAssetCache();
296
+ }
297
+ static {
298
+ this.blockEntityIndexCache = _Caching.createAssetCache();
299
+ }
294
300
  static createAssetCache() {
295
301
  return import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
296
302
  }
@@ -315,7 +321,9 @@ var init_Caching = __esm({
315
321
  this.defaultBlockStatesCache,
316
322
  this.blockTintCache,
317
323
  this.entityModelCache,
318
- this.entityTextureCache
324
+ this.entityTextureCache,
325
+ this.entityAnimationCache,
326
+ this.blockEntityIndexCache
319
327
  ];
320
328
  }
321
329
  static clear() {
@@ -886,6 +894,71 @@ var init_Materials = __esm({
886
894
  alphaTest: 0.5
887
895
  });
888
896
  }
897
+ /** Whether vanilla's render type for the mode culls back faces. */
898
+ static entityModeCulls(mode = "cutout") {
899
+ return mode === "cutout_cull" || mode === "solid" || mode === "eyes" || mode === "water_mask";
900
+ }
901
+ /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */
902
+ static entityModeScroll(mode = "cutout") {
903
+ if (mode === "energy_swirl") return [0.01, 0.01];
904
+ if (mode === "breeze_wind") return [0.02, 0];
905
+ return void 0;
906
+ }
907
+ /**
908
+ * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes
909
+ * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides
910
+ * whether the geometry gets inward faces.
911
+ */
912
+ static createEntityCanvasMaterial(canvas, mode = "cutout", tint) {
913
+ const material = _Materials.createBasicCanvasMaterial(canvas);
914
+ switch (mode) {
915
+ case "cutout":
916
+ case "cutout_cull":
917
+ break;
918
+ case "cutout_z_offset":
919
+ material.polygonOffset = true;
920
+ material.polygonOffsetFactor = -1;
921
+ material.polygonOffsetUnits = -10;
922
+ break;
923
+ case "solid":
924
+ material.alphaTest = 0;
925
+ break;
926
+ case "translucent":
927
+ case "breeze_wind":
928
+ material.transparent = true;
929
+ material.alphaTest = 0.1;
930
+ break;
931
+ case "translucent_emissive":
932
+ material.transparent = true;
933
+ material.alphaTest = 0.1;
934
+ material.depthWrite = false;
935
+ break;
936
+ case "eyes":
937
+ material.transparent = true;
938
+ material.alphaTest = 0;
939
+ material.depthWrite = false;
940
+ break;
941
+ case "energy_swirl":
942
+ material.transparent = true;
943
+ material.alphaTest = 0.1;
944
+ material.blending = import_three5.CustomBlending;
945
+ material.blendSrc = import_three5.OneFactor;
946
+ material.blendDst = import_three5.OneFactor;
947
+ material.blendSrcAlpha = import_three5.ZeroFactor;
948
+ material.blendDstAlpha = import_three5.OneFactor;
949
+ material.color.set(8421504);
950
+ break;
951
+ case "water_mask":
952
+ material.alphaTest = 0;
953
+ material.colorWrite = false;
954
+ break;
955
+ }
956
+ if (_Materials.entityModeScroll(mode)) {
957
+ material.map.wrapS = material.map.wrapT = import_three5.RepeatWrapping;
958
+ }
959
+ if (tint !== void 0) material.color.multiply(new import_three5.Color(tint));
960
+ return material;
961
+ }
889
962
  static createGuiCanvasMaterial(canvas) {
890
963
  const material = new import_three5.MeshBasicMaterial({
891
964
  map: Textures.createCanvasTexture(canvas),
@@ -3101,10 +3174,10 @@ var init_InstanceReference = __esm({
3101
3174
  function isSceneObject(obj) {
3102
3175
  return obj.isSceneObject;
3103
3176
  }
3104
- var import_three10, import_ts_deepmerge3, p6, SceneObject;
3177
+ var import_three11, import_ts_deepmerge3, p6, SceneObject;
3105
3178
  var init_SceneObject = __esm({
3106
3179
  "src/renderer/SceneObject.ts"() {
3107
- import_three10 = require("three");
3180
+ import_three11 = require("three");
3108
3181
  init_Geometries();
3109
3182
  init_UVMapper();
3110
3183
  init_Axis();
@@ -3116,7 +3189,7 @@ var init_SceneObject = __esm({
3116
3189
  import_ts_deepmerge3 = __toESM(require_dist());
3117
3190
  init_log();
3118
3191
  p6 = prefix("SceneObject");
3119
- SceneObject = class _SceneObject extends import_three10.Object3D {
3192
+ SceneObject = class _SceneObject extends import_three11.Object3D {
3120
3193
  constructor(options) {
3121
3194
  super();
3122
3195
  this.isSceneObject = true;
@@ -3168,7 +3241,7 @@ var init_SceneObject = __esm({
3168
3241
  return group;
3169
3242
  }
3170
3243
  createGroup(name, x = 0, y = 0, z = 0, offsetAxis, offset = 0) {
3171
- const obj = new import_three10.Object3D();
3244
+ const obj = new import_three11.Object3D();
3172
3245
  if (name) {
3173
3246
  obj.name = `group:${name}`;
3174
3247
  }
@@ -3218,7 +3291,7 @@ var init_SceneObject = __esm({
3218
3291
  return mesh;
3219
3292
  }
3220
3293
  createMesh(name, geometry, material, offsetAxis, offset = 0) {
3221
- const mesh = new import_three10.Mesh(geometry, material);
3294
+ const mesh = new import_three11.Mesh(geometry, material);
3222
3295
  if (name) {
3223
3296
  mesh.name = `mesh:${name}`;
3224
3297
  }
@@ -3230,7 +3303,7 @@ var init_SceneObject = __esm({
3230
3303
  return mesh;
3231
3304
  }
3232
3305
  createInstancedMesh(name, geometry, material, count) {
3233
- const mesh = new import_three10.InstancedMesh(geometry, material, count);
3306
+ const mesh = new import_three11.InstancedMesh(geometry, material, count);
3234
3307
  mesh.count = 0;
3235
3308
  this.instanceMesh = mesh;
3236
3309
  this._isInstanced = true;
@@ -3310,11 +3383,11 @@ var init_SceneObject = __esm({
3310
3383
  this._instanceCounter = this.instanceReferences.size;
3311
3384
  mesh.count = Math.max(mesh.count, index + 1);
3312
3385
  if (mesh.instanceColor) {
3313
- mesh.setColorAt(index, new import_three10.Color(16777215));
3386
+ mesh.setColorAt(index, new import_three11.Color(16777215));
3314
3387
  mesh.instanceColor.needsUpdate = true;
3315
3388
  }
3316
3389
  if (this._scene) this._scene.stats.instanceCount++;
3317
- this.setMatrixAt(index, new import_three10.Matrix4());
3390
+ this.setMatrixAt(index, new import_three11.Matrix4());
3318
3391
  return reference;
3319
3392
  }
3320
3393
  /** Returns the live reference for a raycast hit on this object's instance mesh. */
@@ -3327,7 +3400,7 @@ var init_SceneObject = __esm({
3327
3400
  removeInstanceAt(index) {
3328
3401
  if (!this.instanceReferences.has(index)) return;
3329
3402
  const mesh = this.instanceMesh;
3330
- this.setMatrixAt(index, new import_three10.Matrix4().makeScale(0, 0, 0));
3403
+ this.setMatrixAt(index, new import_three11.Matrix4().makeScale(0, 0, 0));
3331
3404
  this.instanceReferences.delete(index);
3332
3405
  this.freeInstanceIndices.push(index);
3333
3406
  this._instanceCounter = this.instanceReferences.size;
@@ -3340,7 +3413,7 @@ var init_SceneObject = __esm({
3340
3413
  const grow = (attribute, fill) => {
3341
3414
  const array = new Float32Array(capacity * attribute.itemSize).fill(fill);
3342
3415
  array.set(attribute.array);
3343
- return new import_three10.InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
3416
+ return new import_three11.InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
3344
3417
  };
3345
3418
  const matrix = grow(mesh.instanceMatrix, 0);
3346
3419
  const color = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;
@@ -3357,7 +3430,7 @@ var init_SceneObject = __esm({
3357
3430
  }
3358
3431
  //</editor-fold>
3359
3432
  //<editor-fold desc="TRANSFORMATION">
3360
- getMatrixAt(index, matrix = new import_three10.Matrix4()) {
3433
+ getMatrixAt(index, matrix = new import_three11.Matrix4()) {
3361
3434
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3362
3435
  this.instanceMesh.getMatrixAt(index, matrix);
3363
3436
  return matrix;
@@ -3373,16 +3446,16 @@ var init_SceneObject = __esm({
3373
3446
  }
3374
3447
  setPositionRotationScaleAt(index, position, rotation, scale) {
3375
3448
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3376
- const oldPosition = new import_three10.Vector3();
3377
- const oldRotation = new import_three10.Quaternion();
3378
- const oldScale = new import_three10.Vector3();
3379
- const matrix = new import_three10.Matrix4();
3449
+ const oldPosition = new import_three11.Vector3();
3450
+ const oldRotation = new import_three11.Quaternion();
3451
+ const oldScale = new import_three11.Vector3();
3452
+ const matrix = new import_three11.Matrix4();
3380
3453
  if (!scale || !rotation || !position) {
3381
3454
  this.getMatrixAt(index, matrix).decompose(oldPosition, oldRotation, oldScale);
3382
3455
  }
3383
3456
  matrix.compose(
3384
3457
  position ? position : oldPosition,
3385
- rotation ? new import_three10.Quaternion().setFromEuler(rotation) : oldRotation,
3458
+ rotation ? new import_three11.Quaternion().setFromEuler(rotation) : oldRotation,
3386
3459
  scale ? scale : oldScale
3387
3460
  );
3388
3461
  this.setMatrixAt(index, matrix);
@@ -3391,7 +3464,7 @@ var init_SceneObject = __esm({
3391
3464
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3392
3465
  this.setPositionRotationScaleAt(index, position);
3393
3466
  }
3394
- getPositionAt(index, vector = new import_three10.Vector3()) {
3467
+ getPositionAt(index, vector = new import_three11.Vector3()) {
3395
3468
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3396
3469
  const matrix = this.getMatrixAt(index);
3397
3470
  vector.setFromMatrixPosition(matrix);
@@ -3401,17 +3474,17 @@ var init_SceneObject = __esm({
3401
3474
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3402
3475
  this.setPositionRotationScaleAt(index, void 0, rotation, void 0);
3403
3476
  }
3404
- getRotationAt(index, euler = new import_three10.Euler()) {
3477
+ getRotationAt(index, euler = new import_three11.Euler()) {
3405
3478
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3406
- const rotation = new import_three10.Quaternion();
3407
- this.getMatrixAt(index).decompose(new import_three10.Vector3(), rotation, new import_three10.Vector3());
3479
+ const rotation = new import_three11.Quaternion();
3480
+ this.getMatrixAt(index).decompose(new import_three11.Vector3(), rotation, new import_three11.Vector3());
3408
3481
  return euler.setFromQuaternion(rotation);
3409
3482
  }
3410
3483
  setScaleAt(index, scale) {
3411
3484
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3412
3485
  this.setPositionRotationScaleAt(index, void 0, void 0, scale);
3413
3486
  }
3414
- getScaleAt(index, vector = new import_three10.Vector3()) {
3487
+ getScaleAt(index, vector = new import_three11.Vector3()) {
3415
3488
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3416
3489
  const matrix = this.getMatrixAt(index);
3417
3490
  vector.setFromMatrixScale(matrix);
@@ -3547,7 +3620,7 @@ function mergeBufferGeometries(geometries, useGroups = false) {
3547
3620
  const attributes = {};
3548
3621
  const morphAttributes = {};
3549
3622
  const morphTargetsRelative = geometries[0].morphTargetsRelative;
3550
- const mergedGeometry = new import_three19.BufferGeometry();
3623
+ const mergedGeometry = new import_three20.BufferGeometry();
3551
3624
  let offset = 0;
3552
3625
  for (let i = 0; i < geometries.length; ++i) {
3553
3626
  const geometry = geometries[i];
@@ -3671,7 +3744,7 @@ function mergeBufferAttributes(attributes) {
3671
3744
  array.set(attributes[i].array, offset);
3672
3745
  offset += attributes[i].array.length;
3673
3746
  }
3674
- return new import_three19.BufferAttribute(array, itemSize, normalized);
3747
+ return new import_three20.BufferAttribute(array, itemSize, normalized);
3675
3748
  }
3676
3749
  function interleaveAttributes(attributes) {
3677
3750
  let TypedArray;
@@ -3687,7 +3760,7 @@ function interleaveAttributes(attributes) {
3687
3760
  arrayLength += attribute.array.length;
3688
3761
  stride += attribute.itemSize;
3689
3762
  }
3690
- const interleavedBuffer = new import_three19.InterleavedBuffer(new TypedArray(arrayLength), stride);
3763
+ const interleavedBuffer = new import_three20.InterleavedBuffer(new TypedArray(arrayLength), stride);
3691
3764
  let offset = 0;
3692
3765
  const res = [];
3693
3766
  const getters = ["getX", "getY", "getZ", "getW"];
@@ -3696,7 +3769,7 @@ function interleaveAttributes(attributes) {
3696
3769
  const attribute = attributes[j];
3697
3770
  const itemSize = attribute.itemSize;
3698
3771
  const count = attribute.count;
3699
- const iba = new import_three19.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
3772
+ const iba = new import_three20.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
3700
3773
  res.push(iba);
3701
3774
  offset += itemSize;
3702
3775
  for (let c = 0; c < count; c++) {
@@ -3780,13 +3853,13 @@ function mergeVertices(geometry, tolerance = 1e-4) {
3780
3853
  const name = attributeNames[i];
3781
3854
  const oldAttribute = geometry.getAttribute(name);
3782
3855
  const buffer = new oldAttribute.array.constructor(attrArrays[name]);
3783
- const attribute = new import_three19.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
3856
+ const attribute = new import_three20.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
3784
3857
  result.setAttribute(name, attribute);
3785
3858
  if (name in morphAttrsArrays) {
3786
3859
  for (let j = 0; j < morphAttrsArrays[name].length; j++) {
3787
3860
  const oldMorphAttribute = geometry.morphAttributes[name][j];
3788
3861
  const buffer2 = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
3789
- const morphAttribute = new import_three19.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
3862
+ const morphAttribute = new import_three20.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
3790
3863
  result.morphAttributes[name][j] = morphAttribute;
3791
3864
  }
3792
3865
  }
@@ -3795,11 +3868,11 @@ function mergeVertices(geometry, tolerance = 1e-4) {
3795
3868
  return result;
3796
3869
  }
3797
3870
  function toTrianglesDrawMode(geometry, drawMode) {
3798
- if (drawMode === import_three19.TrianglesDrawMode) {
3871
+ if (drawMode === import_three20.TrianglesDrawMode) {
3799
3872
  console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.");
3800
3873
  return geometry;
3801
3874
  }
3802
- if (drawMode === import_three19.TriangleFanDrawMode || drawMode === import_three19.TriangleStripDrawMode) {
3875
+ if (drawMode === import_three20.TriangleFanDrawMode || drawMode === import_three20.TriangleStripDrawMode) {
3803
3876
  let index = geometry.getIndex();
3804
3877
  if (index === null) {
3805
3878
  const indices = [];
@@ -3817,7 +3890,7 @@ function toTrianglesDrawMode(geometry, drawMode) {
3817
3890
  }
3818
3891
  const numberOfTriangles = index.count - 2;
3819
3892
  const newIndices = [];
3820
- if (drawMode === import_three19.TriangleFanDrawMode) {
3893
+ if (drawMode === import_three20.TriangleFanDrawMode) {
3821
3894
  for (let i = 1; i <= numberOfTriangles; i++) {
3822
3895
  newIndices.push(index.getX(0));
3823
3896
  newIndices.push(index.getX(i));
@@ -3853,15 +3926,15 @@ function computeMorphedAttributes(object) {
3853
3926
  console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
3854
3927
  return null;
3855
3928
  }
3856
- const _vA = new import_three19.Vector3();
3857
- const _vB = new import_three19.Vector3();
3858
- const _vC = new import_three19.Vector3();
3859
- const _tempA = new import_three19.Vector3();
3860
- const _tempB = new import_three19.Vector3();
3861
- const _tempC = new import_three19.Vector3();
3862
- const _morphA = new import_three19.Vector3();
3863
- const _morphB = new import_three19.Vector3();
3864
- const _morphC = new import_three19.Vector3();
3929
+ const _vA = new import_three20.Vector3();
3930
+ const _vB = new import_three20.Vector3();
3931
+ const _vC = new import_three20.Vector3();
3932
+ const _tempA = new import_three20.Vector3();
3933
+ const _tempB = new import_three20.Vector3();
3934
+ const _tempC = new import_three20.Vector3();
3935
+ const _morphA = new import_three20.Vector3();
3936
+ const _morphB = new import_three20.Vector3();
3937
+ const _morphC = new import_three20.Vector3();
3865
3938
  function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
3866
3939
  _vA.fromBufferAttribute(attribute, a2);
3867
3940
  _vB.fromBufferAttribute(attribute, b2);
@@ -4056,8 +4129,8 @@ function computeMorphedAttributes(object) {
4056
4129
  }
4057
4130
  }
4058
4131
  }
4059
- const morphedPositionAttribute = new import_three19.Float32BufferAttribute(modifiedPosition, 3);
4060
- const morphedNormalAttribute = new import_three19.Float32BufferAttribute(modifiedNormal, 3);
4132
+ const morphedPositionAttribute = new import_three20.Float32BufferAttribute(modifiedPosition, 3);
4133
+ const morphedNormalAttribute = new import_three20.Float32BufferAttribute(modifiedNormal, 3);
4061
4134
  return {
4062
4135
  positionAttribute,
4063
4136
  normalAttribute,
@@ -4065,24 +4138,24 @@ function computeMorphedAttributes(object) {
4065
4138
  morphedNormalAttribute
4066
4139
  };
4067
4140
  }
4068
- var import_three19;
4141
+ var import_three20;
4069
4142
  var init_BufferGeometryUtils = __esm({
4070
4143
  "src/three/BufferGeometryUtils.js"() {
4071
- import_three19 = require("three");
4144
+ import_three20 = require("three");
4072
4145
  }
4073
4146
  });
4074
4147
 
4075
4148
  // src/model/ModelCulling.ts
4076
- var import_three20, ModelCulling;
4149
+ var import_three21, ModelCulling;
4077
4150
  var init_ModelCulling = __esm({
4078
4151
  "src/model/ModelCulling.ts"() {
4079
- import_three20 = require("three");
4152
+ import_three21 = require("three");
4080
4153
  init_CubeFace();
4081
4154
  ModelCulling = class {
4082
4155
  static toLocalMask(worldMask, rotation) {
4083
4156
  let localMask = 0;
4084
4157
  for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
4085
- const normal = new import_three20.Vector3(...offset).applyEuler(rotation);
4158
+ const normal = new import_three21.Vector3(...offset).applyEuler(rotation);
4086
4159
  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);
4087
4160
  if (worldFace < 0) return 0;
4088
4161
  if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
@@ -4118,13 +4191,13 @@ var init_ModelCulling = __esm({
4118
4191
  function isModelObject(obj) {
4119
4192
  return obj.isModelObject;
4120
4193
  }
4121
- var import_three21, import_ts_deepmerge5, p7, ModelObject;
4194
+ var import_three22, import_ts_deepmerge5, p7, ModelObject;
4122
4195
  var init_ModelObject = __esm({
4123
4196
  "src/model/scene/ModelObject.ts"() {
4124
4197
  init_SceneObject();
4125
4198
  init_Materials();
4126
4199
  init_UVMapper();
4127
- import_three21 = require("three");
4200
+ import_three22 = require("three");
4128
4201
  init_BufferGeometryUtils();
4129
4202
  init_model();
4130
4203
  import_ts_deepmerge5 = __toESM(require_dist());
@@ -4181,7 +4254,7 @@ var init_ModelObject = __esm({
4181
4254
  elGeo.clearGroups();
4182
4255
  }
4183
4256
  if (this.options.uvLockRotation) {
4184
- UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three21.Euler(...this.options.uvLockRotation));
4257
+ UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three22.Euler(...this.options.uvLockRotation));
4185
4258
  }
4186
4259
  if (this.options.tints) {
4187
4260
  const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
@@ -4190,19 +4263,19 @@ var init_ModelObject = __esm({
4190
4263
  if (tintIndex === void 0 || tintIndex < 0) continue;
4191
4264
  const tint = this.options.tints[tintIndex];
4192
4265
  if (tint === void 0) continue;
4193
- const color = new import_three21.Color(tint);
4266
+ const color = new import_three22.Color(tint);
4194
4267
  for (let vertex = 0; vertex < 4; vertex++) {
4195
4268
  color.toArray(colors, (faceIndex * 4 + vertex) * 3);
4196
4269
  }
4197
4270
  }
4198
- elGeo.setAttribute("color", new import_three21.BufferAttribute(colors, 3));
4271
+ elGeo.setAttribute("color", new import_three22.BufferAttribute(colors, 3));
4199
4272
  }
4200
- 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));
4201
- elGeo.applyMatrix4(new import_three21.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4273
+ 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));
4274
+ elGeo.applyMatrix4(new import_three22.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4202
4275
  if (el.rotation) {
4203
4276
  applyElementRotation(el.rotation, elGeo);
4204
4277
  }
4205
- elGeo.applyMatrix4(new import_three21.Matrix4().makeTranslation(-8, -8, -8));
4278
+ elGeo.applyMatrix4(new import_three22.Matrix4().makeTranslation(-8, -8, -8));
4206
4279
  if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
4207
4280
  if (this.options.mergeMeshes) {
4208
4281
  allGeos.push(elGeo);
@@ -4224,7 +4297,7 @@ var init_ModelObject = __esm({
4224
4297
  if (allGeos.length > 0) {
4225
4298
  combinedGeo = mergeBufferGeometries(allGeos);
4226
4299
  } else {
4227
- combinedGeo = new import_three21.BoxGeometry(16, 16, 16);
4300
+ combinedGeo = new import_three22.BoxGeometry(16, 16, 16);
4228
4301
  if (displayTransform) DisplayTransforms.apply(combinedGeo, displayTransform);
4229
4302
  }
4230
4303
  combinedGeo.computeBoundingBox();
@@ -4332,7 +4405,7 @@ function ownHeight(sample) {
4332
4405
  return (level === 0 || level >= 8 ? 8 : 8 - level) / 9;
4333
4406
  }
4334
4407
  function createFluidGeometry(kind, sample) {
4335
- const geometry = new import_three26.BufferGeometry();
4408
+ const geometry = new import_three27.BufferGeometry();
4336
4409
  const positions = [], normals = [], uvs = [], indices = [];
4337
4410
  const self = sample(0, 0, 0);
4338
4411
  const height = (x, z) => {
@@ -4431,16 +4504,16 @@ function createFluidGeometry(kind, sample) {
4431
4504
  1
4432
4505
  );
4433
4506
  }
4434
- geometry.setAttribute("position", new import_three26.Float32BufferAttribute(positions, 3));
4435
- geometry.setAttribute("normal", new import_three26.Float32BufferAttribute(normals, 3));
4436
- geometry.setAttribute("uv", new import_three26.Float32BufferAttribute(uvs, 2));
4507
+ geometry.setAttribute("position", new import_three27.Float32BufferAttribute(positions, 3));
4508
+ geometry.setAttribute("normal", new import_three27.Float32BufferAttribute(normals, 3));
4509
+ geometry.setAttribute("uv", new import_three27.Float32BufferAttribute(uvs, 2));
4437
4510
  geometry.setIndex(indices);
4438
4511
  return geometry;
4439
4512
  }
4440
- var import_three26, fluidRules, HORIZONTAL, EPSILON;
4513
+ var import_three27, fluidRules, HORIZONTAL, EPSILON;
4441
4514
  var init_FluidGeometry = __esm({
4442
4515
  "src/model/fluid/FluidGeometry.ts"() {
4443
- import_three26 = require("three");
4516
+ import_three27 = require("three");
4444
4517
  init_fluidBlocks();
4445
4518
  fluidRules = fluidBlocks_default;
4446
4519
  HORIZONTAL = [[0, -1], [0, 1], [-1, 0], [1, 0]];
@@ -4469,10 +4542,10 @@ function sampleFluid(kind, sample) {
4469
4542
  }
4470
4543
  return { key: key.join(""), sample: (x, y, z) => cells[(y + 1) * 9 + (z + 1) * 3 + x + 1] };
4471
4544
  }
4472
- var import_three27, FluidModelObject;
4545
+ var import_three28, FluidModelObject;
4473
4546
  var init_FluidModelObject = __esm({
4474
4547
  "src/model/fluid/FluidModelObject.ts"() {
4475
- import_three27 = require("three");
4548
+ import_three28 = require("three");
4476
4549
  init_AssetKey();
4477
4550
  init_Materials();
4478
4551
  init_ModelObject();
@@ -4505,10 +4578,10 @@ var init_FluidModelObject = __esm({
4505
4578
  }
4506
4579
  }
4507
4580
  geometry.clearGroups();
4508
- const color = new import_three27.Color(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4581
+ const color = new import_three28.Color(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4509
4582
  const colors = new Float32Array(geometry.getAttribute("position").count * 3);
4510
4583
  for (let i = 0; i < colors.length; i += 3) color.toArray(colors, i);
4511
- geometry.setAttribute("color", new import_three27.BufferAttribute(colors, 3));
4584
+ geometry.setAttribute("color", new import_three28.BufferAttribute(colors, 3));
4512
4585
  geometry.computeBoundingBox();
4513
4586
  geometry.computeBoundingSphere();
4514
4587
  if (this.options.instanceMeshes) {
@@ -4522,7 +4595,7 @@ var init_FluidModelObject = __esm({
4522
4595
  super.applyTextures();
4523
4596
  this.iterateAllMeshes((mesh) => {
4524
4597
  const material = mesh.material;
4525
- material.side = import_three27.DoubleSide;
4598
+ material.side = import_three28.DoubleSide;
4526
4599
  material.forceSinglePass = true;
4527
4600
  material.depthWrite = !material.transparent;
4528
4601
  });
@@ -4553,6 +4626,7 @@ __export(index_node_exports, {
4553
4626
  BUILTIN_GENERATED: () => BUILTIN_GENERATED,
4554
4627
  BasicAssetKey: () => BasicAssetKey,
4555
4628
  BatchedExecutor: () => BatchedExecutor,
4629
+ BlockEntities: () => BlockEntities,
4556
4630
  BlockObject: () => BlockObject,
4557
4631
  BlockStateResolver: () => BlockStateResolver,
4558
4632
  BlockStates: () => BlockStates,
@@ -4574,7 +4648,9 @@ __export(index_node_exports, {
4574
4648
  DefaultBlockStates: () => DefaultBlockStates,
4575
4649
  DisplayPosition: () => DisplayPosition,
4576
4650
  DisplayTransforms: () => DisplayTransforms,
4651
+ ENTITY_ANIMATION_CHANNELS: () => ENTITY_ANIMATION_CHANNELS,
4577
4652
  Entities: () => Entities,
4653
+ EntityAnimationPlayer: () => EntityAnimationPlayer,
4578
4654
  EntityObject: () => EntityObject,
4579
4655
  Env: () => Env,
4580
4656
  FluidModelObject: () => FluidModelObject,
@@ -4650,6 +4726,7 @@ __export(index_node_exports, {
4650
4726
  createCanvas: () => createCanvas2,
4651
4727
  createFluidGeometry: () => createFluidGeometry,
4652
4728
  createImage: () => createImage,
4729
+ entityAnimationTime: () => entityAnimationTime,
4653
4730
  estimateBytesUsed: () => estimateBytesUsed,
4654
4731
  getBlockFluidState: () => getBlockFluidState,
4655
4732
  getFluidKind: () => getFluidKind,
@@ -4682,6 +4759,8 @@ __export(index_node_exports, {
4682
4759
  mergeVertices: () => mergeVertices,
4683
4760
  prefix: () => prefix,
4684
4761
  registerNodeEnv: () => registerNodeEnv,
4762
+ sampleEntityAnimation: () => sampleEntityAnimation,
4763
+ sampleEntityKeyframes: () => sampleEntityKeyframes,
4685
4764
  sampleFluid: () => sampleFluid,
4686
4765
  serializeBoxGeometryKey: () => serializeBoxGeometryKey,
4687
4766
  serializeImageKey: () => serializeImageKey,
@@ -4939,6 +5018,59 @@ function shutdown() {
4939
5018
  init_AssetKey();
4940
5019
  init_AssetLoader();
4941
5020
  init_Assets();
5021
+
5022
+ // src/assets/BlockEntities.ts
5023
+ var import_three10 = require("three");
5024
+ init_AssetKey();
5025
+ init_AssetLoader();
5026
+ init_source();
5027
+ init_Caching();
5028
+ var BlockEntities = class {
5029
+ /**
5030
+ * Loads the block index of a version. Versions and sources without one yield an empty index, and so does
5031
+ * a failed load: the index is optional, and blocks must not retry or fail with it one by one. The empty
5032
+ * result is cached like any other; `Caching.clear()` or `AssetLoader.setVersion()` forces a new attempt.
5033
+ */
5034
+ static async getIndex(root) {
5035
+ const key = new AssetKey("entity-models", "blocks", void 0, void 0, void 0, ".json", root);
5036
+ key.rootType = void 0;
5037
+ const index = await Caching.blockEntityIndexCache.get(key.serialize(), async () => {
5038
+ try {
5039
+ return await AssetLoader.get(key, "json" /* JSON */) ?? {};
5040
+ } catch (error) {
5041
+ console.warn("Could not load the block entity index; block entities are drawn as plain block models", error);
5042
+ return {};
5043
+ }
5044
+ });
5045
+ return index ?? {};
5046
+ }
5047
+ /** The index entry of a block ID such as `minecraft:chest`. */
5048
+ static entry(index, block) {
5049
+ const entry = Object.prototype.hasOwnProperty.call(index, block) ? index[block] : void 0;
5050
+ return Array.isArray(entry?.parts) ? entry : void 0;
5051
+ }
5052
+ /** Selects the parts and placement for a block ID such as `minecraft:chest`; undefined when nothing is drawn. */
5053
+ static resolve(index, block, state = {}) {
5054
+ const entry = this.entry(index, block);
5055
+ if (!entry) return void 0;
5056
+ const value = (property) => String(state[property]).toLowerCase();
5057
+ const parts = entry.parts.filter((part) => Object.entries(part.when ?? {}).every(([property, values]) => String(values).split("|").includes(value(property))));
5058
+ if (!parts.length) return void 0;
5059
+ let rotation = 0;
5060
+ if (entry.rotation) {
5061
+ const selected = value(entry.rotation.property);
5062
+ rotation = "degrees" in entry.rotation ? entry.rotation.degrees[selected] : Number(selected) * entry.rotation.step;
5063
+ if (!Number.isFinite(rotation)) rotation = 0;
5064
+ }
5065
+ return { parts, rotation, translation: entry.translation ?? [0, 0, 0] };
5066
+ }
5067
+ /** Placement in block space (0..16 per axis), applied on top of the model's own transform. */
5068
+ static matrix(resolved, matrix = new import_three10.Matrix4()) {
5069
+ 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));
5070
+ }
5071
+ };
5072
+
5073
+ // src/assets/index.ts
4942
5074
  init_BlockStates();
4943
5075
 
4944
5076
  // src/assets/Entities.ts
@@ -4970,32 +5102,53 @@ var Entities = class {
4970
5102
  static async getLayerList(modelKey) {
4971
5103
  return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
4972
5104
  }
5105
+ /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
5106
+ static async getPassList(modelKey) {
5107
+ return (await this.getModelFile(modelKey))?.passes ?? [];
5108
+ }
4973
5109
  static async getEntity(modelKey, textureKey, options) {
4974
5110
  const model = await this.getModelFile(modelKey);
4975
5111
  if (!model) return void 0;
4976
- const names = [...new Set(options?.layers ?? [options?.layer ?? "main"])];
4977
- if (names.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
4978
- const selected = names.map((name) => {
4979
- const layer = model.layers[name];
5112
+ const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
5113
+ const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
5114
+ if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
5115
+ draws.push(...passes);
5116
+ const names = [];
5117
+ const selected = draws.map((pass) => {
5118
+ const layer = model.layers[pass.layer];
4980
5119
  if (!layer) {
4981
- throw new MineRenderError(`Entity ${model.id} has no layer "${name}". Available layers: ${Object.keys(model.layers).join(", ")}`);
5120
+ throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
4982
5121
  }
4983
- return { name, layer };
5122
+ let name = pass.layer;
5123
+ for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
5124
+ names.push(name);
5125
+ return { name, layer, pass };
4984
5126
  });
4985
- const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer }, index) => {
5127
+ const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
4986
5128
  const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
5129
+ const textureLocation = pass.textureLocation ?? layer.textureLocation;
4987
5130
  let texture;
4988
5131
  if (override) {
4989
5132
  const path = isAssetKey(override) ? override.getFullPath() : override.path;
4990
5133
  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);
4991
- } else if (layer.textureLocation !== void 0) {
4992
- texture = AssetKey.parse("textures", layer.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
5134
+ } else if (textureLocation !== void 0) {
5135
+ texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
4993
5136
  } else {
4994
5137
  texture = await this.resolveTexture(modelKey);
4995
5138
  }
4996
- return [name, { key: override ?? modelKey, texture, layer }];
5139
+ const render = pass.render ?? layer.render;
5140
+ return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
4997
5141
  })));
4998
- return { ...layers[names[0]], id: model.id, layers };
5142
+ return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
5143
+ }
5144
+ /**
5145
+ * Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
5146
+ */
5147
+ static async getAnimations(modelKey) {
5148
+ const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
5149
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
5150
+ const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
5151
+ return file?.animations;
4999
5152
  }
5000
5153
  static async resolveTexture(modelKey) {
5001
5154
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
@@ -5073,11 +5226,125 @@ function trimCanvas(source) {
5073
5226
  return canvas;
5074
5227
  }
5075
5228
 
5229
+ // src/entity/EntityAnimation.ts
5230
+ var ENTITY_ANIMATION_CHANNELS = ["position", "rotation", "scale"];
5231
+ function catmullRom(delta, p0, p1, p22, p32) {
5232
+ 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);
5233
+ }
5234
+ function sampleEntityKeyframes(keyframes, time) {
5235
+ if (keyframes.length === 0) return [0, 0, 0];
5236
+ let low = 0, high = keyframes.length;
5237
+ while (low < high) {
5238
+ const middle = low + high >>> 1;
5239
+ if (time <= keyframes[middle].time) high = middle;
5240
+ else low = middle + 1;
5241
+ }
5242
+ const a = Math.max(0, low - 1);
5243
+ const b = Math.min(keyframes.length - 1, a + 1);
5244
+ const from = keyframes[a];
5245
+ const to = keyframes[b];
5246
+ const delta = a === b ? 0 : Math.min(1, Math.max(0, (time - from.time) / (to.time - from.time)));
5247
+ if (to.interpolation === "catmullrom") {
5248
+ const before = keyframes[Math.max(0, a - 1)].value;
5249
+ const after = keyframes[Math.min(keyframes.length - 1, b + 1)].value;
5250
+ return [0, 1, 2].map((i) => catmullRom(delta, before[i], from.value[i], to.value[i], after[i]));
5251
+ }
5252
+ const target = to.pre ?? to.value;
5253
+ return [0, 1, 2].map((i) => from.value[i] + (target[i] - from.value[i]) * delta);
5254
+ }
5255
+ function entityAnimationTime(animation, time, loop = animation.loop) {
5256
+ return loop && animation.length > 0 ? time % animation.length : time;
5257
+ }
5258
+ function sampleEntityAnimation(animation, time, loop = animation.loop) {
5259
+ const elapsed = entityAnimationTime(animation, time, loop);
5260
+ const pose = {};
5261
+ for (const [name, bone] of Object.entries(animation.bones)) {
5262
+ const sampled = pose[name] = {};
5263
+ for (const channel of ENTITY_ANIMATION_CHANNELS) {
5264
+ const keyframes = bone[channel];
5265
+ if (keyframes?.length) sampled[channel] = sampleEntityKeyframes(keyframes, elapsed);
5266
+ }
5267
+ }
5268
+ return pose;
5269
+ }
5270
+
5271
+ // src/entity/scene/EntityAnimationPlayer.ts
5272
+ var ZERO = [0, 0, 0];
5273
+ var EntityAnimationPlayer = class {
5274
+ constructor() {
5275
+ this.parts = [];
5276
+ this._time = 0;
5277
+ this.loop = false;
5278
+ this.speed = 1;
5279
+ }
5280
+ get animation() {
5281
+ return this._animation;
5282
+ }
5283
+ get time() {
5284
+ return this._time;
5285
+ }
5286
+ /**
5287
+ * Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
5288
+ * bones without a matching part are skipped.
5289
+ */
5290
+ play(layers, animation, options = {}) {
5291
+ this.stop();
5292
+ this._animation = animation;
5293
+ this._time = options.time ?? 0;
5294
+ this.loop = options.loop ?? animation.loop;
5295
+ this.speed = options.speed ?? 1;
5296
+ for (const layer of layers) {
5297
+ for (const bone of Object.keys(animation.bones)) {
5298
+ const object = layer.getObjectByName(`group:${bone}`);
5299
+ if (!object) continue;
5300
+ this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
5301
+ }
5302
+ }
5303
+ this.apply();
5304
+ }
5305
+ /** Restores the default poses. Returns whether an animation was active. */
5306
+ stop() {
5307
+ if (!this._animation) return false;
5308
+ for (const part of this.parts) {
5309
+ part.object.position.copy(part.position);
5310
+ part.object.rotation.copy(part.rotation);
5311
+ part.object.scale.copy(part.scale);
5312
+ }
5313
+ this.clear();
5314
+ return true;
5315
+ }
5316
+ /** Forgets the animation without touching the parts, for parts that no longer exist. */
5317
+ clear() {
5318
+ this.parts = [];
5319
+ this._animation = void 0;
5320
+ this._time = 0;
5321
+ }
5322
+ setTime(seconds) {
5323
+ if (!this._animation) return false;
5324
+ this._time = seconds;
5325
+ this.apply();
5326
+ return true;
5327
+ }
5328
+ advance(deltaSeconds) {
5329
+ return this.setTime(this._time + deltaSeconds * this.speed);
5330
+ }
5331
+ apply() {
5332
+ const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
5333
+ for (const part of this.parts) {
5334
+ const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
5335
+ part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
5336
+ part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
5337
+ part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
5338
+ }
5339
+ }
5340
+ };
5341
+
5076
5342
  // src/entity/scene/EntityObject.ts
5077
5343
  init_SceneObject();
5078
5344
  init_Caching();
5079
5345
  var import_ts_deepmerge4 = __toESM(require_dist());
5080
- var import_three12 = require("three");
5346
+ var import_three13 = require("three");
5347
+ init_Ticker();
5081
5348
  init_model();
5082
5349
  init_ModelTextures();
5083
5350
  init_AssetKey();
@@ -5089,10 +5356,15 @@ var EntityObject = class _EntityObject extends SceneObject {
5089
5356
  this.entity = entity;
5090
5357
  this.isEntityObject = true;
5091
5358
  this.meshesCreated = false;
5359
+ /** Scrolling materials are owned: their texture offset follows this entity's age. */
5360
+ this.scrollMaterials = [];
5361
+ /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
5362
+ this.age = 0;
5363
+ this.animationPlayer = new EntityAnimationPlayer();
5092
5364
  this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
5093
5365
  }
5094
5366
  static {
5095
- this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, { flip: true });
5367
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
5096
5368
  }
5097
5369
  async init() {
5098
5370
  this.createMeshes();
@@ -5101,6 +5373,59 @@ var EntityObject = class _EntityObject extends SceneObject {
5101
5373
  dispose() {
5102
5374
  super.dispose();
5103
5375
  }
5376
+ disposeAndRemoveAllChildren() {
5377
+ this.clearScrollMaterials();
5378
+ this.animationPlayer.clear();
5379
+ super.disposeAndRemoveAllChildren();
5380
+ }
5381
+ clearScrollMaterials() {
5382
+ Ticker.remove(this.scrollTicker);
5383
+ this.scrollTicker = void 0;
5384
+ for (const { material } of this.scrollMaterials.splice(0)) {
5385
+ material.map?.dispose();
5386
+ material.dispose();
5387
+ }
5388
+ }
5389
+ /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
5390
+ updateScroll() {
5391
+ for (const { offset, speed } of this.scrollMaterials) {
5392
+ offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
5393
+ }
5394
+ this.notifyDirty();
5395
+ }
5396
+ //<editor-fold desc="ANIMATION">
5397
+ /** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
5398
+ get animation() {
5399
+ return this.animationPlayer.animation;
5400
+ }
5401
+ /** Seconds since the animation started, before looping. */
5402
+ get animationTime() {
5403
+ return this.animationPlayer.time;
5404
+ }
5405
+ /**
5406
+ * Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
5407
+ * Parts of every layer are matched by name and their current pose is the default the offsets add to.
5408
+ * The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
5409
+ */
5410
+ playAnimation(animation, options) {
5411
+ this.createMeshes();
5412
+ const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
5413
+ this.animationPlayer.play(layers, animation, options);
5414
+ this.notifyDirty();
5415
+ }
5416
+ /** Stops the animation and restores the default pose. */
5417
+ stopAnimation() {
5418
+ if (this.animationPlayer.stop()) this.notifyDirty();
5419
+ }
5420
+ /** Poses the object at an explicit time in seconds. Has no effect without an animation. */
5421
+ setAnimationTime(seconds) {
5422
+ if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
5423
+ }
5424
+ /** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
5425
+ advanceAnimation(deltaSeconds) {
5426
+ if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
5427
+ }
5428
+ //</editor-fold>
5104
5429
  getLayerGroup(name) {
5105
5430
  return super.getGroupByName(`layer:${name}`);
5106
5431
  }
@@ -5130,17 +5455,30 @@ var EntityObject = class _EntityObject extends SceneObject {
5130
5455
  }
5131
5456
  createMeshes(force = false) {
5132
5457
  if (this.meshesCreated && !force) return;
5133
- const modelRoot = new import_three12.Object3D();
5134
- if (this.options.flip) modelRoot.scale.set(-1, -1, 1);
5458
+ const modelRoot = new import_three13.Object3D();
5459
+ const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
5460
+ if (transform) {
5461
+ for (const op of transform) {
5462
+ const matrix = new import_three13.Matrix4();
5463
+ if ("scale" in op) matrix.makeScale(...op.scale);
5464
+ else if ("translate" in op) matrix.makeTranslation(...op.translate);
5465
+ else matrix.makeRotationFromEuler(new import_three13.Euler(...op.rotate, "ZYX"));
5466
+ modelRoot.matrix.multiply(matrix);
5467
+ }
5468
+ modelRoot.matrixAutoUpdate = false;
5469
+ } else if (this.options.flip ?? true) {
5470
+ modelRoot.scale.set(-1, -1, 1);
5471
+ }
5135
5472
  this.add(modelRoot);
5136
5473
  Object.entries(this.entityLayers).forEach(([name, layer], index) => {
5137
5474
  const group = this.createGroup(`layer:${name}`);
5138
5475
  modelRoot.add(group);
5139
- this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index);
5476
+ const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
5477
+ this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
5140
5478
  });
5141
5479
  this.meshesCreated = true;
5142
5480
  }
5143
- createPart(name, part, parent, textureSize, material, renderOrder) {
5481
+ createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
5144
5482
  const anchor = this.createGroup(name);
5145
5483
  anchor.position.fromArray(part.pose.offset);
5146
5484
  anchor.rotation.set(...part.pose.rotation, "ZYX");
@@ -5159,7 +5497,7 @@ var EntityObject = class _EntityObject extends SceneObject {
5159
5497
  uv
5160
5498
  ).clone();
5161
5499
  geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
5162
- if (Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
5500
+ if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
5163
5501
  const index = Array.from(geometry.getIndex().array);
5164
5502
  geometry.setIndex(index.concat(index.slice().reverse()));
5165
5503
  }
@@ -5169,26 +5507,42 @@ var EntityObject = class _EntityObject extends SceneObject {
5169
5507
  if (this.options.wireframe) addWireframeToMesh(geometry, mesh);
5170
5508
  }
5171
5509
  for (const [childName, child] of Object.entries(part.children)) {
5172
- this.createPart(childName, child, anchor, size, material, renderOrder);
5510
+ this.createPart(childName, child, anchor, size, material, renderOrder, inward);
5173
5511
  }
5174
5512
  }
5175
5513
  async applyTextures() {
5514
+ this.clearScrollMaterials();
5176
5515
  await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
5516
+ const mode = layer.render ?? layer.layer.render ?? "cutout";
5517
+ const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
5518
+ const scroll = Materials.entityModeScroll(mode);
5177
5519
  const assetKeyStr = this.getTextureKey(layer).serialize();
5178
- const keyStr = `entity:${assetKeyStr}`;
5179
- let mat = Caching.materialCache.getIfPresent(keyStr);
5520
+ const keyStr = `entity:${mode}:${tint === void 0 ? "" : new import_three13.Color(tint).getHexString()}:${assetKeyStr}`;
5521
+ let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
5180
5522
  if (!mat) {
5181
5523
  const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
5182
5524
  const imageData = await this.loadTextures(layer);
5183
5525
  if (!imageData) return;
5184
5526
  const canvas = imageData.data.canvas;
5185
- const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
5186
- mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5527
+ const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
5528
+ mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5529
+ if (scroll) {
5530
+ this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
5531
+ }
5187
5532
  }
5188
5533
  this.getLayerGroup(name)?.traverse((object) => {
5189
5534
  if (isMesh(object)) object.material = mat;
5190
5535
  });
5191
5536
  }));
5537
+ if (!this.children.length) {
5538
+ this.clearScrollMaterials();
5539
+ } else if (this.scrollMaterials.length) {
5540
+ this.updateScroll();
5541
+ this.scrollTicker = Ticker.add(() => {
5542
+ this.age++;
5543
+ this.updateScroll();
5544
+ });
5545
+ }
5192
5546
  this.notifyDirty();
5193
5547
  }
5194
5548
  };
@@ -5200,27 +5554,27 @@ function isEntityObject(obj) {
5200
5554
  init_MineRenderError();
5201
5555
 
5202
5556
  // src/export/SceneExporter.ts
5203
- var import_three18 = require("three");
5557
+ var import_three19 = require("three");
5204
5558
 
5205
5559
  // ../../node_modules/three/examples/jsm/exporters/OBJExporter.js
5206
- var import_three14 = require("three");
5560
+ var import_three15 = require("three");
5207
5561
  var OBJExporter = class {
5208
5562
  parse(object) {
5209
5563
  let output = "";
5210
5564
  let indexVertex = 0;
5211
5565
  let indexVertexUvs = 0;
5212
5566
  let indexNormals = 0;
5213
- const vertex = new import_three14.Vector3();
5214
- const color = new import_three14.Color();
5215
- const normal = new import_three14.Vector3();
5216
- const uv = new import_three14.Vector2();
5567
+ const vertex = new import_three15.Vector3();
5568
+ const color = new import_three15.Color();
5569
+ const normal = new import_three15.Vector3();
5570
+ const uv = new import_three15.Vector2();
5217
5571
  const face = [];
5218
5572
  function parseMesh(mesh) {
5219
5573
  let nbVertex = 0;
5220
5574
  let nbNormals = 0;
5221
5575
  let nbVertexUvs = 0;
5222
5576
  const geometry = mesh.geometry;
5223
- const normalMatrixWorld = new import_three14.Matrix3();
5577
+ const normalMatrixWorld = new import_three15.Matrix3();
5224
5578
  const vertices = geometry.getAttribute("position");
5225
5579
  const normals = geometry.getAttribute("normal");
5226
5580
  const uvs = geometry.getAttribute("uv");
@@ -5339,7 +5693,7 @@ var OBJExporter = class {
5339
5693
  };
5340
5694
 
5341
5695
  // ../../node_modules/three/examples/jsm/exporters/PLYExporter.js
5342
- var import_three15 = require("three");
5696
+ var import_three16 = require("three");
5343
5697
  var PLYExporter = class {
5344
5698
  parse(object, onDone, options = {}) {
5345
5699
  function traverseMeshes(cb) {
@@ -5396,7 +5750,7 @@ var PLYExporter = class {
5396
5750
  includeIndices = false;
5397
5751
  }
5398
5752
  });
5399
- const tempColor = new import_three15.Color();
5753
+ const tempColor = new import_three16.Color();
5400
5754
  includeIndices = includeIndices && excludeAttributes.indexOf("index") === -1;
5401
5755
  includeNormals = includeNormals && excludeAttributes.indexOf("normal") === -1;
5402
5756
  includeColors = includeColors && excludeAttributes.indexOf("color") === -1;
@@ -5430,8 +5784,8 @@ property list uchar int vertex_index
5430
5784
  `;
5431
5785
  }
5432
5786
  header += "end_header\n";
5433
- const vertex = new import_three15.Vector3();
5434
- const normalMatrixWorld = new import_three15.Matrix3();
5787
+ const vertex = new import_three16.Vector3();
5788
+ const normalMatrixWorld = new import_three16.Matrix3();
5435
5789
  let result = null;
5436
5790
  if (options.binary === true) {
5437
5791
  const headerBin = new TextEncoder().encode(header);
@@ -5605,18 +5959,18 @@ property list uchar int vertex_index
5605
5959
  };
5606
5960
 
5607
5961
  // ../../node_modules/three/examples/jsm/exporters/GLTFExporter.js
5608
- var import_three17 = require("three");
5962
+ var import_three18 = require("three");
5609
5963
 
5610
5964
  // ../../node_modules/three/examples/jsm/utils/TextureUtils.js
5611
- var import_three16 = require("three");
5965
+ var import_three17 = require("three");
5612
5966
  var _renderer;
5613
5967
  var fullscreenQuadGeometry;
5614
5968
  var fullscreenQuadMaterial;
5615
5969
  var fullscreenQuad;
5616
5970
  function decompress(texture, maxTextureSize = Infinity, renderer = null) {
5617
- if (!fullscreenQuadGeometry) fullscreenQuadGeometry = new import_three16.PlaneGeometry(2, 2, 1, 1);
5618
- if (!fullscreenQuadMaterial) fullscreenQuadMaterial = new import_three16.ShaderMaterial({
5619
- uniforms: { blitTexture: new import_three16.Uniform(texture) },
5971
+ if (!fullscreenQuadGeometry) fullscreenQuadGeometry = new import_three17.PlaneGeometry(2, 2, 1, 1);
5972
+ if (!fullscreenQuadMaterial) fullscreenQuadMaterial = new import_three17.ShaderMaterial({
5973
+ uniforms: { blitTexture: new import_three17.Uniform(texture) },
5620
5974
  vertexShader: `
5621
5975
  varying vec2 vUv;
5622
5976
  void main(){
@@ -5638,22 +5992,22 @@ function decompress(texture, maxTextureSize = Infinity, renderer = null) {
5638
5992
  }`
5639
5993
  });
5640
5994
  fullscreenQuadMaterial.uniforms.blitTexture.value = texture;
5641
- fullscreenQuadMaterial.defines.IS_SRGB = texture.colorSpace == import_three16.SRGBColorSpace;
5995
+ fullscreenQuadMaterial.defines.IS_SRGB = texture.colorSpace == import_three17.SRGBColorSpace;
5642
5996
  fullscreenQuadMaterial.needsUpdate = true;
5643
5997
  if (!fullscreenQuad) {
5644
- fullscreenQuad = new import_three16.Mesh(fullscreenQuadGeometry, fullscreenQuadMaterial);
5998
+ fullscreenQuad = new import_three17.Mesh(fullscreenQuadGeometry, fullscreenQuadMaterial);
5645
5999
  fullscreenQuad.frustrumCulled = false;
5646
6000
  }
5647
- const _camera = new import_three16.PerspectiveCamera();
5648
- const _scene = new import_three16.Scene();
6001
+ const _camera = new import_three17.PerspectiveCamera();
6002
+ const _scene = new import_three17.Scene();
5649
6003
  _scene.add(fullscreenQuad);
5650
6004
  if (!renderer) {
5651
- renderer = _renderer = new import_three16.WebGLRenderer({ antialias: false });
6005
+ renderer = _renderer = new import_three17.WebGLRenderer({ antialias: false });
5652
6006
  }
5653
6007
  renderer.setSize(Math.min(texture.image.width, maxTextureSize), Math.min(texture.image.height, maxTextureSize));
5654
6008
  renderer.clear();
5655
6009
  renderer.render(_scene, _camera);
5656
- const readableTexture = new import_three16.Texture(renderer.domElement);
6010
+ const readableTexture = new import_three17.Texture(renderer.domElement);
5657
6011
  readableTexture.minFilter = texture.minFilter;
5658
6012
  readableTexture.magFilter = texture.magFilter;
5659
6013
  readableTexture.wrapS = texture.wrapS;
@@ -5799,22 +6153,22 @@ var WEBGL_CONSTANTS = {
5799
6153
  };
5800
6154
  var KHR_MESH_QUANTIZATION = "KHR_mesh_quantization";
5801
6155
  var THREE_TO_WEBGL = {};
5802
- THREE_TO_WEBGL[import_three17.NearestFilter] = WEBGL_CONSTANTS.NEAREST;
5803
- THREE_TO_WEBGL[import_three17.NearestMipmapNearestFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_NEAREST;
5804
- THREE_TO_WEBGL[import_three17.NearestMipmapLinearFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_LINEAR;
5805
- THREE_TO_WEBGL[import_three17.LinearFilter] = WEBGL_CONSTANTS.LINEAR;
5806
- THREE_TO_WEBGL[import_three17.LinearMipmapNearestFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST;
5807
- THREE_TO_WEBGL[import_three17.LinearMipmapLinearFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR;
5808
- THREE_TO_WEBGL[import_three17.ClampToEdgeWrapping] = WEBGL_CONSTANTS.CLAMP_TO_EDGE;
5809
- THREE_TO_WEBGL[import_three17.RepeatWrapping] = WEBGL_CONSTANTS.REPEAT;
5810
- THREE_TO_WEBGL[import_three17.MirroredRepeatWrapping] = WEBGL_CONSTANTS.MIRRORED_REPEAT;
6156
+ THREE_TO_WEBGL[import_three18.NearestFilter] = WEBGL_CONSTANTS.NEAREST;
6157
+ THREE_TO_WEBGL[import_three18.NearestMipmapNearestFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_NEAREST;
6158
+ THREE_TO_WEBGL[import_three18.NearestMipmapLinearFilter] = WEBGL_CONSTANTS.NEAREST_MIPMAP_LINEAR;
6159
+ THREE_TO_WEBGL[import_three18.LinearFilter] = WEBGL_CONSTANTS.LINEAR;
6160
+ THREE_TO_WEBGL[import_three18.LinearMipmapNearestFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST;
6161
+ THREE_TO_WEBGL[import_three18.LinearMipmapLinearFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR;
6162
+ THREE_TO_WEBGL[import_three18.ClampToEdgeWrapping] = WEBGL_CONSTANTS.CLAMP_TO_EDGE;
6163
+ THREE_TO_WEBGL[import_three18.RepeatWrapping] = WEBGL_CONSTANTS.REPEAT;
6164
+ THREE_TO_WEBGL[import_three18.MirroredRepeatWrapping] = WEBGL_CONSTANTS.MIRRORED_REPEAT;
5811
6165
  var PATH_PROPERTIES = {
5812
6166
  scale: "scale",
5813
6167
  position: "translation",
5814
6168
  quaternion: "rotation",
5815
6169
  morphTargetInfluences: "weights"
5816
6170
  };
5817
- var DEFAULT_SPECULAR_COLOR = new import_three17.Color();
6171
+ var DEFAULT_SPECULAR_COLOR = new import_three18.Color();
5818
6172
  var GLB_HEADER_BYTES = 12;
5819
6173
  var GLB_HEADER_MAGIC = 1179937895;
5820
6174
  var GLB_VERSION = 2;
@@ -5848,7 +6202,7 @@ function getMinMax(attribute, start, count) {
5848
6202
  else if (a === 2) value = attribute.getZ(i);
5849
6203
  else if (a === 3) value = attribute.getW(i);
5850
6204
  if (attribute.normalized === true) {
5851
- value = import_three17.MathUtils.normalize(value, attribute.array);
6205
+ value = import_three18.MathUtils.normalize(value, attribute.array);
5852
6206
  }
5853
6207
  }
5854
6208
  output.min[a] = Math.min(output.min[a], value);
@@ -6054,7 +6408,7 @@ var GLTFWriter = class {
6054
6408
  isNormalizedNormalAttribute(normal) {
6055
6409
  const cache = this.cache;
6056
6410
  if (cache.attributesNormalized.has(normal)) return false;
6057
- const v = new import_three17.Vector3();
6411
+ const v = new import_three18.Vector3();
6058
6412
  for (let i = 0, il = normal.count; i < il; i++) {
6059
6413
  if (Math.abs(v.fromBufferAttribute(normal, i).length() - 1) > 5e-4) return false;
6060
6414
  }
@@ -6071,7 +6425,7 @@ var GLTFWriter = class {
6071
6425
  const cache = this.cache;
6072
6426
  if (cache.attributesNormalized.has(normal)) return cache.attributesNormalized.get(normal);
6073
6427
  const attribute = normal.clone();
6074
- const v = new import_three17.Vector3();
6428
+ const v = new import_three18.Vector3();
6075
6429
  for (let i = 0, il = attribute.count; i < il; i++) {
6076
6430
  v.fromBufferAttribute(attribute, i);
6077
6431
  if (v.x === 0 && v.y === 0 && v.z === 0) {
@@ -6115,7 +6469,7 @@ var GLTFWriter = class {
6115
6469
  buildMetalRoughTexture(metalnessMap, roughnessMap) {
6116
6470
  if (metalnessMap === roughnessMap) return metalnessMap;
6117
6471
  function getEncodingConversion(map) {
6118
- if (map.colorSpace === import_three17.SRGBColorSpace) {
6472
+ if (map.colorSpace === import_three18.SRGBColorSpace) {
6119
6473
  return function SRGBToLinear(c) {
6120
6474
  return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);
6121
6475
  };
@@ -6125,10 +6479,10 @@ var GLTFWriter = class {
6125
6479
  };
6126
6480
  }
6127
6481
  console.warn("THREE.GLTFExporter: Merged metalnessMap and roughnessMap textures.");
6128
- if (metalnessMap instanceof import_three17.CompressedTexture) {
6482
+ if (metalnessMap instanceof import_three18.CompressedTexture) {
6129
6483
  metalnessMap = decompress(metalnessMap);
6130
6484
  }
6131
- if (roughnessMap instanceof import_three17.CompressedTexture) {
6485
+ if (roughnessMap instanceof import_three18.CompressedTexture) {
6132
6486
  roughnessMap = decompress(roughnessMap);
6133
6487
  }
6134
6488
  const metalness = metalnessMap ? metalnessMap.image : null;
@@ -6161,8 +6515,8 @@ var GLTFWriter = class {
6161
6515
  context.putImageData(composite, 0, 0);
6162
6516
  const reference = metalnessMap || roughnessMap;
6163
6517
  const texture = reference.clone();
6164
- texture.source = new import_three17.Source(canvas);
6165
- texture.colorSpace = import_three17.NoColorSpace;
6518
+ texture.source = new import_three18.Source(canvas);
6519
+ texture.colorSpace = import_three18.NoColorSpace;
6166
6520
  texture.channel = (metalnessMap || roughnessMap).channel;
6167
6521
  if (metalnessMap && roughnessMap && metalnessMap.channel !== roughnessMap.channel) {
6168
6522
  console.warn("THREE.GLTFExporter: UV channels for metalnessMap and roughnessMap textures must match.");
@@ -6220,7 +6574,7 @@ var GLTFWriter = class {
6220
6574
  else if (a === 2) value = attribute.getZ(i);
6221
6575
  else if (a === 3) value = attribute.getW(i);
6222
6576
  if (attribute.normalized === true) {
6223
- value = import_three17.MathUtils.normalize(value, attribute.array);
6577
+ value = import_three18.MathUtils.normalize(value, attribute.array);
6224
6578
  }
6225
6579
  }
6226
6580
  if (componentType === WEBGL_CONSTANTS.FLOAT) {
@@ -6370,7 +6724,7 @@ var GLTFWriter = class {
6370
6724
  ctx.scale(1, -1);
6371
6725
  }
6372
6726
  if (image.data !== void 0) {
6373
- if (format !== import_three17.RGBAFormat) {
6727
+ if (format !== import_three18.RGBAFormat) {
6374
6728
  console.error("GLTFExporter: Only RGBAFormat is supported.", format);
6375
6729
  }
6376
6730
  if (image.width > options.maxTextureSize || image.height > options.maxTextureSize) {
@@ -6439,7 +6793,7 @@ var GLTFWriter = class {
6439
6793
  const json = this.json;
6440
6794
  if (cache.textures.has(map)) return cache.textures.get(map);
6441
6795
  if (!json.textures) json.textures = [];
6442
- if (map instanceof import_three17.CompressedTexture) {
6796
+ if (map instanceof import_three18.CompressedTexture) {
6443
6797
  map = decompress(map, options.maxTextureSize);
6444
6798
  }
6445
6799
  let mimeType = map.userData.mimeType;
@@ -6547,7 +6901,7 @@ var GLTFWriter = class {
6547
6901
  materialDef.alphaCutoff = material.alphaTest;
6548
6902
  }
6549
6903
  }
6550
- if (material.side === import_three17.DoubleSide) materialDef.doubleSided = true;
6904
+ if (material.side === import_three18.DoubleSide) materialDef.doubleSided = true;
6551
6905
  if (material.name !== "") materialDef.name = material.name;
6552
6906
  this.serializeUserData(material, materialDef);
6553
6907
  this._invokeAll(function(ext) {
@@ -6621,7 +6975,7 @@ var GLTFWriter = class {
6621
6975
  const array = attribute.array;
6622
6976
  if (attributeName === "JOINTS_0" && !(array instanceof Uint16Array) && !(array instanceof Uint8Array)) {
6623
6977
  console.warn('GLTFExporter: Attribute "skinIndex" converted to type UNSIGNED_SHORT.');
6624
- modifiedAttribute = new import_three17.BufferAttribute(new Uint16Array(array), attribute.itemSize, attribute.normalized);
6978
+ modifiedAttribute = new import_three18.BufferAttribute(new Uint16Array(array), attribute.itemSize, attribute.normalized);
6625
6979
  }
6626
6980
  const accessor = this.processAccessor(modifiedAttribute || attribute, geometry);
6627
6981
  if (accessor !== null) {
@@ -6781,7 +7135,7 @@ var GLTFWriter = class {
6781
7135
  } else {
6782
7136
  cameraDef.perspective = {
6783
7137
  aspectRatio: camera.aspect,
6784
- yfov: import_three17.MathUtils.degToRad(camera.fov),
7138
+ yfov: import_three18.MathUtils.degToRad(camera.fov),
6785
7139
  zfar: camera.far <= 0 ? 1e-3 : camera.far,
6786
7140
  znear: camera.near < 0 ? 0 : camera.near
6787
7141
  };
@@ -6809,8 +7163,8 @@ var GLTFWriter = class {
6809
7163
  const samplers = [];
6810
7164
  for (let i = 0; i < tracks.length; ++i) {
6811
7165
  const track = tracks[i];
6812
- const trackBinding = import_three17.PropertyBinding.parseTrackName(track.name);
6813
- let trackNode = import_three17.PropertyBinding.findNode(root, trackBinding.nodeName);
7166
+ const trackBinding = import_three18.PropertyBinding.parseTrackName(track.name);
7167
+ let trackNode = import_three18.PropertyBinding.findNode(root, trackBinding.nodeName);
6814
7168
  const trackProperty = PATH_PROPERTIES[trackBinding.propertyName];
6815
7169
  if (trackBinding.objectName === "bones") {
6816
7170
  if (trackNode.isSkinnedMesh === true) {
@@ -6832,14 +7186,14 @@ var GLTFWriter = class {
6832
7186
  if (track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true) {
6833
7187
  interpolation = "CUBICSPLINE";
6834
7188
  outputItemSize /= 3;
6835
- } else if (track.getInterpolation() === import_three17.InterpolateDiscrete) {
7189
+ } else if (track.getInterpolation() === import_three18.InterpolateDiscrete) {
6836
7190
  interpolation = "STEP";
6837
7191
  } else {
6838
7192
  interpolation = "LINEAR";
6839
7193
  }
6840
7194
  samplers.push({
6841
- input: this.processAccessor(new import_three17.BufferAttribute(track.times, inputItemSize)),
6842
- output: this.processAccessor(new import_three17.BufferAttribute(track.values, outputItemSize)),
7195
+ input: this.processAccessor(new import_three18.BufferAttribute(track.times, inputItemSize)),
7196
+ output: this.processAccessor(new import_three18.BufferAttribute(track.values, outputItemSize)),
6843
7197
  interpolation
6844
7198
  });
6845
7199
  channels.push({
@@ -6871,7 +7225,7 @@ var GLTFWriter = class {
6871
7225
  if (rootJoint === void 0) return null;
6872
7226
  const joints = [];
6873
7227
  const inverseBindMatrices = new Float32Array(skeleton.bones.length * 16);
6874
- const temporaryBoneInverse = new import_three17.Matrix4();
7228
+ const temporaryBoneInverse = new import_three18.Matrix4();
6875
7229
  for (let i = 0; i < skeleton.bones.length; ++i) {
6876
7230
  joints.push(nodeMap.get(skeleton.bones[i]));
6877
7231
  temporaryBoneInverse.copy(skeleton.boneInverses[i]);
@@ -6879,7 +7233,7 @@ var GLTFWriter = class {
6879
7233
  }
6880
7234
  if (json.skins === void 0) json.skins = [];
6881
7235
  json.skins.push({
6882
- inverseBindMatrices: this.processAccessor(new import_three17.BufferAttribute(inverseBindMatrices, 16)),
7236
+ inverseBindMatrices: this.processAccessor(new import_three18.BufferAttribute(inverseBindMatrices, 16)),
6883
7237
  joints,
6884
7238
  skeleton: nodeMap.get(rootJoint)
6885
7239
  });
@@ -6975,7 +7329,7 @@ var GLTFWriter = class {
6975
7329
  * @param {Array} objects List of objects to process
6976
7330
  */
6977
7331
  processObjects(objects) {
6978
- const scene = new import_three17.Scene();
7332
+ const scene = new import_three18.Scene();
6979
7333
  scene.name = "AuxScene";
6980
7334
  for (let i = 0; i < objects.length; i++) {
6981
7335
  scene.children.push(objects[i]);
@@ -6993,7 +7347,7 @@ var GLTFWriter = class {
6993
7347
  });
6994
7348
  const objectsWithoutScene = [];
6995
7349
  for (let i = 0; i < input.length; i++) {
6996
- if (input[i] instanceof import_three17.Scene) {
7350
+ if (input[i] instanceof import_three18.Scene) {
6997
7351
  this.processScene(input[i]);
6998
7352
  } else {
6999
7353
  objectsWithoutScene.push(input[i]);
@@ -7337,10 +7691,10 @@ var GLTFMeshGpuInstancing = class {
7337
7691
  const translationAttr = new Float32Array(mesh.count * 3);
7338
7692
  const rotationAttr = new Float32Array(mesh.count * 4);
7339
7693
  const scaleAttr = new Float32Array(mesh.count * 3);
7340
- const matrix = new import_three17.Matrix4();
7341
- const position = new import_three17.Vector3();
7342
- const quaternion = new import_three17.Quaternion();
7343
- const scale = new import_three17.Vector3();
7694
+ const matrix = new import_three18.Matrix4();
7695
+ const position = new import_three18.Vector3();
7696
+ const quaternion = new import_three18.Quaternion();
7697
+ const scale = new import_three18.Vector3();
7344
7698
  for (let i = 0; i < mesh.count; i++) {
7345
7699
  mesh.getMatrixAt(i, matrix);
7346
7700
  matrix.decompose(position, quaternion, scale);
@@ -7349,9 +7703,9 @@ var GLTFMeshGpuInstancing = class {
7349
7703
  scale.toArray(scaleAttr, i * 3);
7350
7704
  }
7351
7705
  const attributes = {
7352
- TRANSLATION: writer.processAccessor(new import_three17.BufferAttribute(translationAttr, 3)),
7353
- ROTATION: writer.processAccessor(new import_three17.BufferAttribute(rotationAttr, 4)),
7354
- SCALE: writer.processAccessor(new import_three17.BufferAttribute(scaleAttr, 3))
7706
+ TRANSLATION: writer.processAccessor(new import_three18.BufferAttribute(translationAttr, 3)),
7707
+ ROTATION: writer.processAccessor(new import_three18.BufferAttribute(rotationAttr, 4)),
7708
+ SCALE: writer.processAccessor(new import_three18.BufferAttribute(scaleAttr, 3))
7355
7709
  };
7356
7710
  if (mesh.instanceColor)
7357
7711
  attributes._COLOR_0 = writer.processAccessor(mesh.instanceColor);
@@ -7416,8 +7770,8 @@ GLTFExporter.Utils = {
7416
7770
  const sourceTracks = clip.tracks;
7417
7771
  for (let i = 0; i < sourceTracks.length; ++i) {
7418
7772
  let sourceTrack = sourceTracks[i];
7419
- const sourceTrackBinding = import_three17.PropertyBinding.parseTrackName(sourceTrack.name);
7420
- const sourceTrackNode = import_three17.PropertyBinding.findNode(root, sourceTrackBinding.nodeName);
7773
+ const sourceTrackBinding = import_three18.PropertyBinding.parseTrackName(sourceTrack.name);
7774
+ const sourceTrackNode = import_three18.PropertyBinding.findNode(root, sourceTrackBinding.nodeName);
7421
7775
  if (sourceTrackBinding.propertyName !== "morphTargetInfluences" || sourceTrackBinding.propertyIndex === void 0) {
7422
7776
  tracks.push(sourceTrack);
7423
7777
  continue;
@@ -7428,7 +7782,7 @@ GLTFExporter.Utils = {
7428
7782
  }
7429
7783
  console.warn("THREE.GLTFExporter: Morph target interpolation mode not yet supported. Using LINEAR instead.");
7430
7784
  sourceTrack = sourceTrack.clone();
7431
- sourceTrack.setInterpolation(import_three17.InterpolateLinear);
7785
+ sourceTrack.setInterpolation(import_three18.InterpolateLinear);
7432
7786
  }
7433
7787
  const targetCount = sourceTrackNode.morphTargetInfluences.length;
7434
7788
  const targetIndex = sourceTrackNode.morphTargetDictionary[sourceTrackBinding.propertyIndex];
@@ -7511,10 +7865,10 @@ var SceneExporter = class {
7511
7865
  }
7512
7866
  };
7513
7867
  function localMatrix(object) {
7514
- return object.matrixAutoUpdate ? new import_three18.Matrix4().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7868
+ return object.matrixAutoUpdate ? new import_three19.Matrix4().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7515
7869
  }
7516
7870
  function createSnapshot(root, gltf, bakeColors = false) {
7517
- const scene = new import_three18.Scene();
7871
+ const scene = new import_three19.Scene();
7518
7872
  const geometries = [];
7519
7873
  const materials = [];
7520
7874
  const textures = [];
@@ -7532,7 +7886,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7532
7886
  if (!uniforms.map?.value?.isTexture || !uniforms.SHADE || !uniforms.BRIGHTNESS || !uniforms.EMISSIVE) {
7533
7887
  throw new MineRenderError("glTF export does not support this custom ShaderMaterial");
7534
7888
  }
7535
- material = new import_three18.MeshBasicMaterial({
7889
+ material = new import_three19.MeshBasicMaterial({
7536
7890
  map: uniforms.map.value,
7537
7891
  vertexColors: source.vertexColors,
7538
7892
  transparent: source.transparent,
@@ -7542,7 +7896,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7542
7896
  });
7543
7897
  material.name = source.name;
7544
7898
  } else if (shader.isShaderMaterial) {
7545
- material = new import_three18.MeshBasicMaterial({ vertexColors: source.vertexColors });
7899
+ material = new import_three19.MeshBasicMaterial({ vertexColors: source.vertexColors });
7546
7900
  material.name = source.name;
7547
7901
  } else {
7548
7902
  const copySource = Object.create(source);
@@ -7596,11 +7950,11 @@ function createSnapshot(root, gltf, bakeColors = false) {
7596
7950
  const material = copyMaterial(sourceMaterial, geometry);
7597
7951
  if (!sourceMaterial.vertexColors) geometry.deleteAttribute("color");
7598
7952
  if (bakeColors || instanceColor) {
7599
- const tint = (material.color ?? new import_three18.Color()).clone();
7953
+ const tint = (material.color ?? new import_three19.Color()).clone();
7600
7954
  if (instanceColor) tint.multiply(instanceColor);
7601
7955
  if (bakeColors) {
7602
7956
  const original = geometry.getAttribute("color");
7603
- const colors = new import_three18.Float32BufferAttribute(new Float32Array(geometry.getAttribute("position").count * 3), 3);
7957
+ const colors = new import_three19.Float32BufferAttribute(new Float32Array(geometry.getAttribute("position").count * 3), 3);
7604
7958
  for (let i = 0; i < colors.count; i++) {
7605
7959
  colors.setXYZ(i, (original?.getX(i) ?? 1) * tint.r, (original?.getY(i) ?? 1) * tint.g, (original?.getZ(i) ?? 1) * tint.b);
7606
7960
  }
@@ -7609,7 +7963,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7609
7963
  material.color.copy(tint);
7610
7964
  }
7611
7965
  }
7612
- const copy = new import_three18.Mesh(geometry, material);
7966
+ const copy = new import_three19.Mesh(geometry, material);
7613
7967
  copy.name = mesh.name;
7614
7968
  copy.renderOrder = mesh.renderOrder;
7615
7969
  scene.add(copy);
@@ -7623,9 +7977,9 @@ function createSnapshot(root, gltf, bakeColors = false) {
7623
7977
  const instanced = mesh;
7624
7978
  if (instanced.isInstancedMesh) {
7625
7979
  for (let i = 0; i < instanced.count; i++) {
7626
- const matrix = new import_three18.Matrix4();
7980
+ const matrix = new import_three19.Matrix4();
7627
7981
  instanced.getMatrixAt(i, matrix);
7628
- const color = instanced.instanceColor ? new import_three18.Color().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7982
+ const color = instanced.instanceColor ? new import_three19.Color().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7629
7983
  addMesh(mesh, world.clone().multiply(matrix), color);
7630
7984
  }
7631
7985
  } else {
@@ -7637,7 +7991,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7637
7991
  try {
7638
7992
  const ancestors = [];
7639
7993
  for (let parent = root.parent; parent; parent = parent.parent) ancestors.unshift(parent);
7640
- const world = new import_three18.Matrix4();
7994
+ const world = new import_three19.Matrix4();
7641
7995
  for (const ancestor of ancestors) {
7642
7996
  if (!ancestor.visible) return { scene, dispose };
7643
7997
  world.multiply(localMatrix(ancestor));
@@ -7651,7 +8005,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7651
8005
  }
7652
8006
  function selectAlphaMode(material, geometry) {
7653
8007
  const texture = material.map;
7654
- 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;
8008
+ 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;
7655
8009
  const uv = geometry.getAttribute(texture.channel === 0 ? "uv" : `uv${texture.channel}`);
7656
8010
  const colors = geometry.getAttribute("color");
7657
8011
  if (!uv || material.vertexColors && colors?.itemSize === 4) return;
@@ -7688,7 +8042,7 @@ function selectAlphaMode(material, geometry) {
7688
8042
  }
7689
8043
  function copyDataTexture(source) {
7690
8044
  const image = source.image;
7691
- if (source.format !== import_three18.RGBAFormat || source.type !== import_three18.UnsignedByteType) {
8045
+ if (source.format !== import_three19.RGBAFormat || source.type !== import_three19.UnsignedByteType) {
7692
8046
  throw new MineRenderError("glTF export requires RGBA unsigned-byte data textures");
7693
8047
  }
7694
8048
  const canvas = createCanvas2(image.width, image.height);
@@ -7699,20 +8053,78 @@ function copyDataTexture(source) {
7699
8053
  context.putImageData(pixels, 0, 0);
7700
8054
  const copySource = Object.create(source);
7701
8055
  copySource.userData = {};
7702
- copySource.source = new import_three18.Source(canvas);
7703
- return new import_three18.Texture().copy(copySource);
8056
+ copySource.source = new import_three19.Source(canvas);
8057
+ return new import_three19.Texture().copy(copySource);
7704
8058
  }
7705
8059
 
7706
8060
  // src/gui/GuiHelper.ts
8061
+ init_AssetKey();
7707
8062
  var GuiHelper = class {
7708
8063
  static inventorySlot(slot, origin = [0, 0], offset = [18, 18], rowSize = 9) {
7709
8064
  const [column, row] = typeof slot === "number" ? [slot % rowSize, Math.floor(slot / rowSize)] : slot;
7710
8065
  return [origin[0] + column * offset[0], origin[1] + row * offset[1]];
7711
8066
  }
8067
+ /** Creates crafting-table layers for ingredients and the result; stack counts are not drawn. */
8068
+ static recipe(recipe, options = {}) {
8069
+ const layers = [
8070
+ { name: "background", texture: "minecraft:gui/container/crafting_table", crop: [0, 0, 176, 166] }
8071
+ ];
8072
+ const itemKey = (ingredient) => {
8073
+ const item = typeof ingredient === "string" && !ingredient.startsWith("#") ? ingredient : typeof ingredient === "object" && "item" in ingredient ? ingredient.item : options.resolveIngredient?.(ingredient);
8074
+ if (isAssetKey(item)) return item;
8075
+ if (!item || item.startsWith("#")) {
8076
+ throw new Error(`Select a concrete item for recipe ingredient ${JSON.stringify(ingredient)}`);
8077
+ }
8078
+ const key = AssetKey.parse("models", item);
8079
+ return new AssetKey(key.namespace, key.getFullPath(), "models", "item");
8080
+ };
8081
+ const addIngredient = (ingredient, slot) => {
8082
+ layers.push({
8083
+ name: `ingredient-${slot}`,
8084
+ item: itemKey(ingredient),
8085
+ position: this.inventorySlot(slot, [30, 17], [18, 18], 3)
8086
+ });
8087
+ };
8088
+ switch (recipe.type) {
8089
+ case "minecraft:crafting_shaped":
8090
+ case "crafting_shaped": {
8091
+ const pattern = recipe.pattern;
8092
+ if (!pattern.length || pattern.length > 3 || !pattern[0].length || pattern[0].length > 3 || pattern.some((row) => row.length !== pattern[0].length)) {
8093
+ throw new Error("Crafting patterns must be rectangular, with 1\u20133 rows and columns");
8094
+ }
8095
+ const cells = pattern.flatMap((row, y) => row.split("").map((symbol, x) => ({ symbol, x, y }))).filter((cell) => cell.symbol !== " ");
8096
+ if (!cells.length) throw new Error("Crafting patterns must contain an ingredient");
8097
+ const minX = Math.min(...cells.map((cell) => cell.x)), maxX = Math.max(...cells.map((cell) => cell.x));
8098
+ const minY = Math.min(...cells.map((cell) => cell.y)), maxY = Math.max(...cells.map((cell) => cell.y));
8099
+ const offsetX = minX === maxX ? 1 : 0, offsetY = minY === maxY ? 1 : 0;
8100
+ for (const { symbol, x, y } of cells) {
8101
+ const ingredient = recipe.key[symbol];
8102
+ if (!ingredient) throw new Error(`Missing recipe ingredient for symbol ${JSON.stringify(symbol)}`);
8103
+ addIngredient(ingredient, (y - minY + offsetY) * 3 + x - minX + offsetX);
8104
+ }
8105
+ break;
8106
+ }
8107
+ case "minecraft:crafting_shapeless":
8108
+ case "crafting_shapeless":
8109
+ if (!recipe.ingredients.length || recipe.ingredients.length > 9) {
8110
+ throw new Error("Shapeless crafting recipes require 1\u20139 ingredients");
8111
+ }
8112
+ recipe.ingredients.forEach(addIngredient);
8113
+ break;
8114
+ default:
8115
+ throw new Error(`Unsupported crafting recipe type: ${recipe.type}`);
8116
+ }
8117
+ layers.push({
8118
+ name: "result",
8119
+ item: itemKey("id" in recipe.result ? recipe.result.id : recipe.result.item),
8120
+ position: [124, 35]
8121
+ });
8122
+ return layers;
8123
+ }
7712
8124
  };
7713
8125
 
7714
8126
  // src/gui/scene/GuiObject.ts
7715
- var import_three22 = require("three");
8127
+ var import_three23 = require("three");
7716
8128
  init_AssetKey();
7717
8129
  init_ModelTextures();
7718
8130
  init_Models();
@@ -7736,7 +8148,7 @@ var GuiObject = class extends SceneObject {
7736
8148
  this.textureLayers = textureLayers;
7737
8149
  this.isGuiObject = true;
7738
8150
  /** Local bounds in GUI pixels, with y growing down from the origin. */
7739
- this.bounds = new import_three22.Box2();
8151
+ this.bounds = new import_three23.Box2();
7740
8152
  this.geometries = /* @__PURE__ */ new Set();
7741
8153
  this.ownedMaterials = /* @__PURE__ */ new Set();
7742
8154
  this.initialized = false;
@@ -7753,7 +8165,7 @@ var GuiObject = class extends SceneObject {
7753
8165
  item.position.set(x + width2 / 2, -y - height2 / 2, 0);
7754
8166
  item.scale.set(width2 / 16, height2 / 16, width2 / 16);
7755
8167
  item.updateMatrix();
7756
- const bounds = new import_three22.Box3();
8168
+ const bounds = new import_three23.Box3();
7757
8169
  item.iterateAllMeshes((mesh2) => {
7758
8170
  mesh2.geometry.computeBoundingBox();
7759
8171
  bounds.union(mesh2.geometry.boundingBox);
@@ -7761,10 +8173,10 @@ var GuiObject = class extends SceneObject {
7761
8173
  bounds.applyMatrix4(item.matrix);
7762
8174
  item.position.z = depth - bounds.min.z;
7763
8175
  depth += bounds.max.z - bounds.min.z + 0.01;
7764
- this.bounds.expandByPoint(new import_three22.Vector2(x, y));
7765
- this.bounds.expandByPoint(new import_three22.Vector2(x + width2, y + height2));
7766
- this.bounds.expandByPoint(new import_three22.Vector2(bounds.min.x, -bounds.max.y));
7767
- this.bounds.expandByPoint(new import_three22.Vector2(bounds.max.x, -bounds.min.y));
8176
+ this.bounds.expandByPoint(new import_three23.Vector2(x, y));
8177
+ this.bounds.expandByPoint(new import_three23.Vector2(x + width2, y + height2));
8178
+ this.bounds.expandByPoint(new import_three23.Vector2(bounds.min.x, -bounds.max.y));
8179
+ this.bounds.expandByPoint(new import_three23.Vector2(bounds.max.x, -bounds.min.y));
7768
8180
  continue;
7769
8181
  }
7770
8182
  const key = typeof layer.texture === "string" ? AssetKey.parse("textures", layer.texture) : layer.texture;
@@ -7772,7 +8184,7 @@ var GuiObject = class extends SceneObject {
7772
8184
  const image = material.map.image;
7773
8185
  const [cropX, cropY, cropWidth, cropHeight] = layer.crop ?? [0, 0, image.width, image.height];
7774
8186
  const [width, height] = layer.size ?? [cropWidth, cropHeight];
7775
- const geometry = new import_three22.PlaneGeometry(width, height);
8187
+ const geometry = new import_three23.PlaneGeometry(width, height);
7776
8188
  this.geometries.add(geometry);
7777
8189
  const uv = geometry.getAttribute("uv");
7778
8190
  for (let i = 0; i < uv.count; i++) {
@@ -7782,13 +8194,13 @@ var GuiObject = class extends SceneObject {
7782
8194
  1 - (cropY + (1 - uv.getY(i)) * cropHeight) / image.height
7783
8195
  );
7784
8196
  }
7785
- const mesh = new import_three22.Mesh(geometry, material);
8197
+ const mesh = new import_three23.Mesh(geometry, material);
7786
8198
  mesh.name = `mesh:${layer.name ?? index}`;
7787
8199
  mesh.position.set(x + width / 2, -y - height / 2, depth);
7788
8200
  mesh.renderOrder = index;
7789
8201
  this.add(mesh);
7790
- this.bounds.expandByPoint(new import_three22.Vector2(x, y));
7791
- this.bounds.expandByPoint(new import_three22.Vector2(x + width, y + height));
8202
+ this.bounds.expandByPoint(new import_three23.Vector2(x, y));
8203
+ this.bounds.expandByPoint(new import_three23.Vector2(x + width, y + height));
7792
8204
  depth += 0.01;
7793
8205
  }
7794
8206
  for (const child of this.children) child.position.z -= depth - 0.01;
@@ -7863,7 +8275,7 @@ function isGuiObject(obj) {
7863
8275
  init_image();
7864
8276
 
7865
8277
  // src/inspector/SceneInspector.ts
7866
- var import_three23 = require("three");
8278
+ var import_three24 = require("three");
7867
8279
  init_SceneObject();
7868
8280
  init_util();
7869
8281
  init_log();
@@ -7873,11 +8285,11 @@ var help = "<span>Ctrl/Cmd+Click to Select<br/></span><br/>";
7873
8285
  var SceneInspector = class {
7874
8286
  constructor(renderer) {
7875
8287
  this.renderer = renderer;
7876
- this.mouse = new import_three23.Vector2();
8288
+ this.mouse = new import_three24.Vector2();
7877
8289
  this.listeners = new AbortController();
7878
8290
  this.objectInfoContainer = document.createElement("div");
7879
8291
  this.objectControlsContainer = document.createElement("div");
7880
- this.raycaster = new import_three23.Raycaster();
8292
+ this.raycaster = new import_three24.Raycaster();
7881
8293
  this.init();
7882
8294
  }
7883
8295
  init() {
@@ -8293,7 +8705,7 @@ init_ModelGenerator();
8293
8705
  init_ModelMerger();
8294
8706
 
8295
8707
  // src/model/block/BlockStateResolver.ts
8296
- var import_three25 = require("three");
8708
+ var import_three26 = require("three");
8297
8709
  init_BlockStates();
8298
8710
  init_MineRenderError();
8299
8711
  init_util();
@@ -8371,7 +8783,7 @@ var BlockStateResolver = class {
8371
8783
  return variants[variants.length - 1];
8372
8784
  }
8373
8785
  static rotation(variant) {
8374
- const rotation = new import_three25.Euler();
8786
+ const rotation = new import_three26.Euler();
8375
8787
  if (typeof variant.x !== "undefined") {
8376
8788
  rotation.x = toRadians(clampRotationDegrees(variant.x));
8377
8789
  }
@@ -8478,7 +8890,7 @@ init_SceneObject();
8478
8890
  init_ModelObject();
8479
8891
  init_Models();
8480
8892
  var import_ts_deepmerge6 = __toESM(require_dist());
8481
- var import_three28 = require("three");
8893
+ var import_three29 = require("three");
8482
8894
  init_MineRenderError();
8483
8895
  init_InstanceReference();
8484
8896
  init_AssetKey();
@@ -8498,6 +8910,9 @@ var BlockObject = class _BlockObject extends SceneObject {
8498
8910
  this._variants = [];
8499
8911
  this._models = [];
8500
8912
  this._cullMask = 0;
8913
+ this._entities = [];
8914
+ this._entityPlacement = new import_three29.Matrix4();
8915
+ this._entityGeneration = 0;
8501
8916
  this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
8502
8917
  }
8503
8918
  static {
@@ -8522,6 +8937,8 @@ var BlockObject = class _BlockObject extends SceneObject {
8522
8937
  }
8523
8938
  clearModels() {
8524
8939
  this.removeModels(this._models.splice(0));
8940
+ this._entityGeneration++;
8941
+ this.removeEntities(this._entities.splice(0));
8525
8942
  this._fluidKey = void 0;
8526
8943
  this._fluidModel = void 0;
8527
8944
  this._isInstanced = false;
@@ -8533,6 +8950,57 @@ var BlockObject = class _BlockObject extends SceneObject {
8533
8950
  if (!isInstanceReference(model)) model.dispose();
8534
8951
  }
8535
8952
  }
8953
+ removeEntities(entities) {
8954
+ for (const entity of entities) {
8955
+ entity.removeFromScene();
8956
+ entity.dispose();
8957
+ }
8958
+ }
8959
+ /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */
8960
+ get blockEntities() {
8961
+ return this._entities;
8962
+ }
8963
+ /**
8964
+ * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
8965
+ * when the block is not listed or one of its models cannot be loaded.
8966
+ */
8967
+ async createBlockEntities() {
8968
+ const key = this.blockState.key;
8969
+ if (!key || this.options.displayPosition) return false;
8970
+ const generation = this._entityGeneration;
8971
+ const created = [];
8972
+ let resolved;
8973
+ try {
8974
+ resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);
8975
+ if (!resolved) return false;
8976
+ for (const part of resolved.parts) {
8977
+ const [namespace, path] = part.model.includes(":") ? part.model.split(":") : [key.namespace, part.model];
8978
+ const texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
8979
+ if (texture) texture.root = key.root;
8980
+ const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });
8981
+ if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);
8982
+ created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }));
8983
+ }
8984
+ } catch (error) {
8985
+ console.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);
8986
+ this.removeEntities(created);
8987
+ return false;
8988
+ }
8989
+ if (generation !== this._entityGeneration) {
8990
+ this.removeEntities(created);
8991
+ return true;
8992
+ }
8993
+ BlockEntities.matrix(resolved, this._entityPlacement);
8994
+ this._entities = created;
8995
+ this.placeEntities();
8996
+ return true;
8997
+ }
8998
+ placeEntities() {
8999
+ const matrix = new import_three29.Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
9000
+ for (const entity of this._entities) {
9001
+ matrix.decompose(entity.position, entity.quaternion, entity.scale);
9002
+ }
9003
+ }
8536
9004
  get isOccluding() {
8537
9005
  return this._models.some((model) => {
8538
9006
  const object = isInstanceReference(model) ? model.instanceable : model;
@@ -8547,12 +9015,12 @@ var BlockObject = class _BlockObject extends SceneObject {
8547
9015
  getModelCullMask(model, worldMask) {
8548
9016
  const object = isInstanceReference(model) ? model.instanceable : model;
8549
9017
  if (object.options.displayPosition) return 0;
8550
- const position = new import_three28.Vector3();
8551
- const rotation = new import_three28.Quaternion();
8552
- const scale = new import_three28.Vector3();
9018
+ const position = new import_three29.Vector3();
9019
+ const rotation = new import_three29.Quaternion();
9020
+ const scale = new import_three29.Vector3();
8553
9021
  this.getModelMatrix(model).decompose(position, rotation, scale);
8554
- if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new import_three28.Vector3(1, 1, 1)) > 1e-10) return 0;
8555
- return ModelCulling.toLocalMask(worldMask, new import_three28.Euler().setFromQuaternion(rotation));
9022
+ if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new import_three29.Vector3(1, 1, 1)) > 1e-10) return 0;
9023
+ return ModelCulling.toLocalMask(worldMask, new import_three29.Euler().setFromQuaternion(rotation));
8556
9024
  }
8557
9025
  async setCullMask(worldMask) {
8558
9026
  worldMask &= 63;
@@ -8614,7 +9082,7 @@ var BlockObject = class _BlockObject extends SceneObject {
8614
9082
  () => new FluidModelObject2(kind, surface.sample, this.blockState.key, this.options)
8615
9083
  );
8616
9084
  const previous = this._fluidModel;
8617
- const matrix = previous ? this.getModelMatrix(previous) : new import_three28.Matrix4().makeTranslation(...this.position.toArray());
9085
+ const matrix = previous ? this.getModelMatrix(previous) : new import_three29.Matrix4().makeTranslation(...this.position.toArray());
8618
9086
  if (isInstanceReference(replacement)) replacement.setMatrix(matrix);
8619
9087
  else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
8620
9088
  this._models = this._models.filter((model) => model !== previous);
@@ -8644,13 +9112,20 @@ var BlockObject = class _BlockObject extends SceneObject {
8644
9112
  await this.updateFluid(this._fluidSampler);
8645
9113
  return;
8646
9114
  }
9115
+ const hasEntities = await this.createBlockEntities();
8647
9116
  const variantsToCreate = await this.mapStateToVariant(this.state);
8648
9117
  this._variants = variantsToCreate;
8649
9118
  for (let blockStateVariant of variantsToCreate) {
9119
+ if (hasEntities && !await this.hasGeometry(blockStateVariant)) continue;
8650
9120
  this._models.push(await this.createVariant(blockStateVariant));
8651
9121
  }
8652
9122
  await this.updateFluid(this._fluidSampler);
8653
9123
  }
9124
+ async hasGeometry(variant) {
9125
+ const modelKey = AssetKey.parse("models", variant.model);
9126
+ modelKey.root = this.blockState.key?.root;
9127
+ return !!(await Models.getMerged(modelKey))?.elements?.length;
9128
+ }
8654
9129
  getSingleVariant(variants) {
8655
9130
  return BlockStateResolver.choose(variants);
8656
9131
  }
@@ -8745,7 +9220,7 @@ var BlockObject = class _BlockObject extends SceneObject {
8745
9220
  setPositionRotationScaleAt(index, position, rotation, scale) {
8746
9221
  super.setPositionRotationScaleAt(index, position, rotation, scale);
8747
9222
  }
8748
- getMatrixAt(index, matrix = new import_three28.Matrix4()) {
9223
+ getMatrixAt(index, matrix = new import_three29.Matrix4()) {
8749
9224
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
8750
9225
  const child = this._models[0];
8751
9226
  if (child && isModelObject(child)) {
@@ -8770,6 +9245,7 @@ var BlockObject = class _BlockObject extends SceneObject {
8770
9245
  for (let model of this._models) {
8771
9246
  model.setPosition(position);
8772
9247
  }
9248
+ this.placeEntities();
8773
9249
  this.notifyDirty();
8774
9250
  }
8775
9251
  //TODO: should override rotation + scale methods
@@ -10611,7 +11087,7 @@ init_ModelObject();
10611
11087
  init_nbt();
10612
11088
 
10613
11089
  // src/renderer/MineRenderScene.ts
10614
- var import_three30 = require("three");
11090
+ var import_three31 = require("three");
10615
11091
  init_SceneObject();
10616
11092
  var import_ts_deepmerge8 = __toESM(require_dist());
10617
11093
  init_ModelObject();
@@ -11344,7 +11820,7 @@ var import_ts_deepmerge7 = __toESM(require_dist());
11344
11820
  init_util();
11345
11821
 
11346
11822
  // src/skin/SkinTextures.ts
11347
- var import_three29 = require("three");
11823
+ var import_three30 = require("three");
11348
11824
  init_Caching();
11349
11825
  init_CacheKey();
11350
11826
  init_MineRenderError();
@@ -11428,11 +11904,11 @@ var SkinTextures = class {
11428
11904
  });
11429
11905
  }
11430
11906
  static createMaterial(pixels, width, height, transparent = true) {
11431
- const texture = Textures.initTextureProps(new import_three29.DataTexture(pixels, width, height));
11432
- texture.colorSpace = import_three29.SRGBColorSpace;
11907
+ const texture = Textures.initTextureProps(new import_three30.DataTexture(pixels, width, height));
11908
+ texture.colorSpace = import_three30.SRGBColorSpace;
11433
11909
  texture.flipY = true;
11434
11910
  texture.needsUpdate = true;
11435
- return new import_three29.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three29.DoubleSide : import_three29.FrontSide, alphaTest: transparent ? 0.1 : 0 });
11911
+ return new import_three30.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three30.DoubleSide : import_three30.FrontSide, alphaTest: transparent ? 0.1 : 0 });
11436
11912
  }
11437
11913
  static isSlim(image, scale) {
11438
11914
  for (const [x, y] of [[46, 52], [54, 20]]) {
@@ -11660,7 +12136,7 @@ var SkinObject = class extends SceneObject {
11660
12136
  };
11661
12137
 
11662
12138
  // src/renderer/MineRenderScene.ts
11663
- var MineRenderScene = class _MineRenderScene extends import_three30.Scene {
12139
+ var MineRenderScene = class _MineRenderScene extends import_three31.Scene {
11664
12140
  constructor(options) {
11665
12141
  super();
11666
12142
  this.isMineRenderScene = true;
@@ -11788,7 +12264,7 @@ function isMineRenderScene(obj) {
11788
12264
  }
11789
12265
 
11790
12266
  // src/renderer/Renderer.ts
11791
- var import_three32 = require("three");
12267
+ var import_three33 = require("three");
11792
12268
  var import_ts_deepmerge9 = __toESM(require_dist());
11793
12269
  var import_stats = __toESM(require("stats.js"));
11794
12270
  var import_postprocessing = require("postprocessing");
@@ -11796,11 +12272,11 @@ init_util();
11796
12272
  init_three();
11797
12273
 
11798
12274
  // src/three/OrbitControls.js
11799
- var import_three31 = require("three");
12275
+ var import_three32 = require("three");
11800
12276
  var _changeEvent = { type: "change" };
11801
12277
  var _startEvent = { type: "start" };
11802
12278
  var _endEvent = { type: "end" };
11803
- var OrbitControls = class extends import_three31.EventDispatcher {
12279
+ var OrbitControls = class extends import_three32.EventDispatcher {
11804
12280
  constructor(object, domElement) {
11805
12281
  super();
11806
12282
  if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
@@ -11809,7 +12285,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11809
12285
  this.domElement = domElement;
11810
12286
  this.domElement.style.touchAction = "none";
11811
12287
  this.enabled = true;
11812
- this.target = new import_three31.Vector3();
12288
+ this.target = new import_three32.Vector3();
11813
12289
  this.minDistance = 0;
11814
12290
  this.maxDistance = Infinity;
11815
12291
  this.minZoom = 0;
@@ -11831,8 +12307,8 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11831
12307
  this.autoRotate = false;
11832
12308
  this.autoRotateSpeed = 2;
11833
12309
  this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
11834
- this.mouseButtons = { LEFT: import_three31.MOUSE.ROTATE, MIDDLE: import_three31.MOUSE.DOLLY, RIGHT: import_three31.MOUSE.PAN };
11835
- this.touches = { ONE: import_three31.TOUCH.ROTATE, TWO: import_three31.TOUCH.DOLLY_PAN };
12310
+ this.mouseButtons = { LEFT: import_three32.MOUSE.ROTATE, MIDDLE: import_three32.MOUSE.DOLLY, RIGHT: import_three32.MOUSE.PAN };
12311
+ this.touches = { ONE: import_three32.TOUCH.ROTATE, TWO: import_three32.TOUCH.DOLLY_PAN };
11836
12312
  this.target0 = this.target.clone();
11837
12313
  this.position0 = this.object.position.clone();
11838
12314
  this.zoom0 = this.object.zoom;
@@ -11861,11 +12337,11 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11861
12337
  state = STATE.NONE;
11862
12338
  };
11863
12339
  this.update = function() {
11864
- const offset = new import_three31.Vector3();
11865
- const quat = new import_three31.Quaternion().setFromUnitVectors(object.up, new import_three31.Vector3(0, 1, 0));
12340
+ const offset = new import_three32.Vector3();
12341
+ const quat = new import_three32.Quaternion().setFromUnitVectors(object.up, new import_three32.Vector3(0, 1, 0));
11866
12342
  const quatInverse = quat.clone().invert();
11867
- const lastPosition = new import_three31.Vector3();
11868
- const lastQuaternion = new import_three31.Quaternion();
12343
+ const lastPosition = new import_three32.Vector3();
12344
+ const lastQuaternion = new import_three32.Quaternion();
11869
12345
  const twoPI = 2 * Math.PI;
11870
12346
  return function update() {
11871
12347
  const position = scope.object.position;
@@ -11951,20 +12427,20 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11951
12427
  };
11952
12428
  let state = STATE.NONE;
11953
12429
  const EPS = 1e-6;
11954
- const spherical = new import_three31.Spherical();
11955
- const sphericalDelta = new import_three31.Spherical();
12430
+ const spherical = new import_three32.Spherical();
12431
+ const sphericalDelta = new import_three32.Spherical();
11956
12432
  let scale = 1;
11957
- const panOffset = new import_three31.Vector3();
12433
+ const panOffset = new import_three32.Vector3();
11958
12434
  let zoomChanged = false;
11959
- const rotateStart = new import_three31.Vector2();
11960
- const rotateEnd = new import_three31.Vector2();
11961
- const rotateDelta = new import_three31.Vector2();
11962
- const panStart = new import_three31.Vector2();
11963
- const panEnd = new import_three31.Vector2();
11964
- const panDelta = new import_three31.Vector2();
11965
- const dollyStart = new import_three31.Vector2();
11966
- const dollyEnd = new import_three31.Vector2();
11967
- const dollyDelta = new import_three31.Vector2();
12435
+ const rotateStart = new import_three32.Vector2();
12436
+ const rotateEnd = new import_three32.Vector2();
12437
+ const rotateDelta = new import_three32.Vector2();
12438
+ const panStart = new import_three32.Vector2();
12439
+ const panEnd = new import_three32.Vector2();
12440
+ const panDelta = new import_three32.Vector2();
12441
+ const dollyStart = new import_three32.Vector2();
12442
+ const dollyEnd = new import_three32.Vector2();
12443
+ const dollyDelta = new import_three32.Vector2();
11968
12444
  const pointers = [];
11969
12445
  const pointerPositions = {};
11970
12446
  function getAutoRotationAngle() {
@@ -11980,7 +12456,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11980
12456
  sphericalDelta.phi -= angle;
11981
12457
  }
11982
12458
  const panLeft = function() {
11983
- const v = new import_three31.Vector3();
12459
+ const v = new import_three32.Vector3();
11984
12460
  return function panLeft2(distance, objectMatrix) {
11985
12461
  v.setFromMatrixColumn(objectMatrix, 0);
11986
12462
  v.multiplyScalar(-distance);
@@ -11988,7 +12464,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
11988
12464
  };
11989
12465
  }();
11990
12466
  const panUp = function() {
11991
- const v = new import_three31.Vector3();
12467
+ const v = new import_three32.Vector3();
11992
12468
  return function panUp2(distance, objectMatrix) {
11993
12469
  if (scope.screenSpacePanning === true) {
11994
12470
  v.setFromMatrixColumn(objectMatrix, 1);
@@ -12001,7 +12477,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12001
12477
  };
12002
12478
  }();
12003
12479
  const pan = function() {
12004
- const offset = new import_three31.Vector3();
12480
+ const offset = new import_three32.Vector3();
12005
12481
  return function pan2(deltaX, deltaY) {
12006
12482
  const element = scope.domElement;
12007
12483
  if (scope.object.isPerspectiveCamera) {
@@ -12250,12 +12726,12 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12250
12726
  mouseAction = -1;
12251
12727
  }
12252
12728
  switch (mouseAction) {
12253
- case import_three31.MOUSE.DOLLY:
12729
+ case import_three32.MOUSE.DOLLY:
12254
12730
  if (scope.enableZoom === false) return;
12255
12731
  handleMouseDownDolly(event);
12256
12732
  state = STATE.DOLLY;
12257
12733
  break;
12258
- case import_three31.MOUSE.ROTATE:
12734
+ case import_three32.MOUSE.ROTATE:
12259
12735
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
12260
12736
  if (scope.enablePan === false) return;
12261
12737
  handleMouseDownPan(event);
@@ -12266,7 +12742,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12266
12742
  state = STATE.ROTATE;
12267
12743
  }
12268
12744
  break;
12269
- case import_three31.MOUSE.PAN:
12745
+ case import_three32.MOUSE.PAN:
12270
12746
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
12271
12747
  if (scope.enableRotate === false) return;
12272
12748
  handleMouseDownRotate(event);
@@ -12322,12 +12798,12 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12322
12798
  switch (pointers.length) {
12323
12799
  case 1:
12324
12800
  switch (scope.touches.ONE) {
12325
- case import_three31.TOUCH.ROTATE:
12801
+ case import_three32.TOUCH.ROTATE:
12326
12802
  if (scope.enableRotate === false) return;
12327
12803
  handleTouchStartRotate();
12328
12804
  state = STATE.TOUCH_ROTATE;
12329
12805
  break;
12330
- case import_three31.TOUCH.PAN:
12806
+ case import_three32.TOUCH.PAN:
12331
12807
  if (scope.enablePan === false) return;
12332
12808
  handleTouchStartPan();
12333
12809
  state = STATE.TOUCH_PAN;
@@ -12338,12 +12814,12 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12338
12814
  break;
12339
12815
  case 2:
12340
12816
  switch (scope.touches.TWO) {
12341
- case import_three31.TOUCH.DOLLY_PAN:
12817
+ case import_three32.TOUCH.DOLLY_PAN:
12342
12818
  if (scope.enableZoom === false && scope.enablePan === false) return;
12343
12819
  handleTouchStartDollyPan();
12344
12820
  state = STATE.TOUCH_DOLLY_PAN;
12345
12821
  break;
12346
- case import_three31.TOUCH.DOLLY_ROTATE:
12822
+ case import_three32.TOUCH.DOLLY_ROTATE:
12347
12823
  if (scope.enableZoom === false && scope.enableRotate === false) return;
12348
12824
  handleTouchStartDollyRotate();
12349
12825
  state = STATE.TOUCH_DOLLY_ROTATE;
@@ -12410,7 +12886,7 @@ var OrbitControls = class extends import_three31.EventDispatcher {
12410
12886
  function trackPointer(event) {
12411
12887
  let position = pointerPositions[event.pointerId];
12412
12888
  if (position === void 0) {
12413
- position = new import_three31.Vector2();
12889
+ position = new import_three32.Vector2();
12414
12890
  pointerPositions[event.pointerId] = position;
12415
12891
  }
12416
12892
  position.set(event.pageX, event.pageY);
@@ -12430,10 +12906,10 @@ var MapControls = class extends OrbitControls {
12430
12906
  constructor(object, domElement) {
12431
12907
  super(object, domElement);
12432
12908
  this.screenSpacePanning = false;
12433
- this.mouseButtons.LEFT = import_three31.MOUSE.PAN;
12434
- this.mouseButtons.RIGHT = import_three31.MOUSE.ROTATE;
12435
- this.touches.ONE = import_three31.TOUCH.PAN;
12436
- this.touches.TWO = import_three31.TOUCH.DOLLY_ROTATE;
12909
+ this.mouseButtons.LEFT = import_three32.MOUSE.PAN;
12910
+ this.mouseButtons.RIGHT = import_three32.MOUSE.ROTATE;
12911
+ this.touches.ONE = import_three32.TOUCH.PAN;
12912
+ this.touches.TWO = import_three32.TOUCH.DOLLY_ROTATE;
12437
12913
  }
12438
12914
  };
12439
12915
 
@@ -12492,8 +12968,8 @@ var Renderer = class _Renderer {
12492
12968
  top: void 0,
12493
12969
  bottom: void 0
12494
12970
  },
12495
- position: new import_three32.Vector3(50, 50, 50),
12496
- lookingAt: new import_three32.Vector3(0, 0, 0)
12971
+ position: new import_three33.Vector3(50, 50, 50),
12972
+ lookingAt: new import_three33.Vector3(0, 0, 0)
12497
12973
  },
12498
12974
  render: {
12499
12975
  fpsLimit: 60,
@@ -12524,14 +13000,14 @@ var Renderer = class _Renderer {
12524
13000
  switch (this.options.camera.type) {
12525
13001
  case "perspective":
12526
13002
  default:
12527
- return new import_three32.PerspectiveCamera(
13003
+ return new import_three33.PerspectiveCamera(
12528
13004
  this.options.camera.perspective.fov,
12529
13005
  this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
12530
13006
  this.options.camera.near,
12531
13007
  this.options.camera.far
12532
13008
  );
12533
13009
  case "orthographic":
12534
- return new import_three32.OrthographicCamera(
13010
+ return new import_three33.OrthographicCamera(
12535
13011
  this.options.camera.orthographic.left ?? this.viewWidth / -2,
12536
13012
  this.options.camera.orthographic.right ?? this.viewWidth / 2,
12537
13013
  this.options.camera.orthographic.top ?? this.viewHeight / 2,
@@ -12542,7 +13018,7 @@ var Renderer = class _Renderer {
12542
13018
  }
12543
13019
  }
12544
13020
  createRenderer() {
12545
- const renderer = new import_three32.WebGLRenderer({
13021
+ const renderer = new import_three33.WebGLRenderer({
12546
13022
  antialias: this.options.render.antialias,
12547
13023
  alpha: true,
12548
13024
  powerPreference: "high-performance",
@@ -12550,8 +13026,8 @@ var Renderer = class _Renderer {
12550
13026
  });
12551
13027
  renderer.setClearColor(0, 0);
12552
13028
  renderer.shadowMap.enabled = true;
12553
- renderer.shadowMap.type = import_three32.PCFSoftShadowMap;
12554
- renderer.outputColorSpace = import_three32.SRGBColorSpace;
13029
+ renderer.shadowMap.type = import_three33.PCFSoftShadowMap;
13030
+ renderer.outputColorSpace = import_three33.SRGBColorSpace;
12555
13031
  renderer.setPixelRatio(this.options.render.pixelRatio ?? 1);
12556
13032
  renderer.setSize(this.viewWidth, this.viewHeight);
12557
13033
  return renderer;
@@ -12586,20 +13062,20 @@ var Renderer = class _Renderer {
12586
13062
  window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
12587
13063
  }
12588
13064
  if (this.options.debug.grid) {
12589
- const gridHelper = new import_three32.GridHelper(128, 16);
13065
+ const gridHelper = new import_three33.GridHelper(128, 16);
12590
13066
  this._debugHelpers.push(gridHelper);
12591
13067
  this.scene.add(gridHelper);
12592
- const gridHelper2 = new import_three32.GridHelper(128, 16);
13068
+ const gridHelper2 = new import_three33.GridHelper(128, 16);
12593
13069
  this._debugHelpers.push(gridHelper2);
12594
13070
  gridHelper2.rotation.x = 90 * (Math.PI / 180);
12595
13071
  this.scene.add(gridHelper2);
12596
- const gridHelper3 = new import_three32.GridHelper(128, 16);
13072
+ const gridHelper3 = new import_three33.GridHelper(128, 16);
12597
13073
  this._debugHelpers.push(gridHelper3);
12598
13074
  gridHelper3.rotation.z = 90 * (Math.PI / 180);
12599
13075
  this.scene.add(gridHelper3);
12600
13076
  }
12601
13077
  if (this.options.debug.axes) {
12602
- const axesHelper = new import_three32.AxesHelper(64);
13078
+ const axesHelper = new import_three33.AxesHelper(64);
12603
13079
  this._debugHelpers.push(axesHelper);
12604
13080
  this.scene.add(axesHelper);
12605
13081
  }
@@ -13284,19 +13760,19 @@ var AnvilParser = class {
13284
13760
  };
13285
13761
 
13286
13762
  // src/world/Chunk.ts
13287
- var import_three37 = require("three");
13763
+ var import_three38 = require("three");
13288
13764
  init_BlockStates();
13289
13765
  init_AssetKey();
13290
13766
 
13291
13767
  // src/world/MineRenderWorld.ts
13292
- var import_three35 = require("three");
13768
+ var import_three36 = require("three");
13293
13769
  init_BatchedExecutor();
13294
13770
  init_AssetKey();
13295
13771
  init_BlockStates();
13296
13772
  init_CubeFace();
13297
13773
 
13298
13774
  // src/world/SectionModels.ts
13299
- var import_three34 = require("three");
13775
+ var import_three35 = require("three");
13300
13776
  init_AssetKey();
13301
13777
  init_Models();
13302
13778
  init_CubeFace();
@@ -13362,12 +13838,12 @@ var SectionModels = class {
13362
13838
  });
13363
13839
  await object.init();
13364
13840
  const geometry = object.children[0].geometry;
13365
- geometry.applyMatrix4(new import_three34.Matrix4().makeRotationFromEuler(rotation));
13841
+ geometry.applyMatrix4(new import_three35.Matrix4().makeRotationFromEuler(rotation));
13366
13842
  object.clear();
13367
13843
  const cullFaces = CUBE_FACES.map((face) => {
13368
13844
  const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
13369
13845
  if (local < 0) return 0;
13370
- const normal = new import_three34.Vector3(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
13846
+ const normal = new import_three35.Vector3(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
13371
13847
  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);
13372
13848
  return 1 << world;
13373
13849
  });
@@ -13397,20 +13873,20 @@ var MineRenderWorld = class {
13397
13873
  }
13398
13874
  getBlockAt(posOrX, y, z) {
13399
13875
  if (typeof posOrX == "number") {
13400
- return this.getBlockAt(new import_three35.Vector3(posOrX, y, z));
13876
+ return this.getBlockAt(new import_three36.Vector3(posOrX, y, z));
13401
13877
  }
13402
13878
  if (isTripleArray(posOrX)) {
13403
- return this.getBlockAt(new import_three35.Vector3(posOrX[0], posOrX[1], posOrX[2]));
13879
+ return this.getBlockAt(new import_three36.Vector3(posOrX[0], posOrX[1], posOrX[2]));
13404
13880
  }
13405
13881
  this.validatePosBounds(posOrX);
13406
13882
  return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
13407
13883
  }
13408
13884
  async setBlockAt(posOrX, yOrBlock, z, block) {
13409
13885
  if (typeof posOrX == "number") {
13410
- return this.setBlockAt(new import_three35.Vector3(posOrX, yOrBlock, z), block);
13886
+ return this.setBlockAt(new import_three36.Vector3(posOrX, yOrBlock, z), block);
13411
13887
  }
13412
13888
  if (isTripleArray(posOrX)) {
13413
- return this.setBlockAt(new import_three35.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
13889
+ return this.setBlockAt(new import_three36.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
13414
13890
  }
13415
13891
  return this.placeBlock(posOrX, yOrBlock);
13416
13892
  }
@@ -13431,7 +13907,7 @@ var MineRenderWorld = class {
13431
13907
  const collect = async (positions2) => {
13432
13908
  for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
13433
13909
  };
13434
- const place = (block) => this.placeBlock(new import_three35.Vector3(...block.position), block, collect);
13910
+ const place = (block) => this.placeBlock(new import_three36.Vector3(...block.position), block, collect);
13435
13911
  const keys = /* @__PURE__ */ new Map();
13436
13912
  for (const block of multiblock.blocks) {
13437
13913
  if (Chunk.isAir(block)) continue;
@@ -13509,13 +13985,13 @@ var MineRenderWorld = class {
13509
13985
  for (const pos of positions) {
13510
13986
  this.pendingCulling.set(pos.toArray().join(","), pos.clone());
13511
13987
  for (const offset of CUBE_FACE_OFFSETS) {
13512
- const neighbor = pos.clone().add(new import_three35.Vector3(...offset));
13988
+ const neighbor = pos.clone().add(new import_three36.Vector3(...offset));
13513
13989
  this.pendingCulling.set(neighbor.toArray().join(","), neighbor);
13514
13990
  }
13515
13991
  for (let y = -1; y <= 1; y++) {
13516
13992
  for (let z = -1; z <= 1; z++) {
13517
13993
  for (let x = -1; x <= 1; x++) {
13518
- const neighbor = pos.clone().add(new import_three35.Vector3(x, y, z));
13994
+ const neighbor = pos.clone().add(new import_three36.Vector3(x, y, z));
13519
13995
  if (this.getBlockAt(neighbor)?.object?.fluidKind) {
13520
13996
  this.pendingCulling.set(neighbor.toArray().join(","), neighbor);
13521
13997
  }
@@ -13537,7 +14013,7 @@ var MineRenderWorld = class {
13537
14013
  if (!block) continue;
13538
14014
  if (block.object?.fluidKind) {
13539
14015
  await block.object.updateFluid((x, y, z) => {
13540
- const neighbor = pos.clone().add(new import_three35.Vector3(x, y, z));
14016
+ const neighbor = pos.clone().add(new import_three36.Vector3(x, y, z));
13541
14017
  const section = this.getChunkAt(neighbor);
13542
14018
  const object = section?.getBlockAt(neighbor)?.object;
13543
14019
  return {
@@ -13549,7 +14025,7 @@ var MineRenderWorld = class {
13549
14025
  }
13550
14026
  let mask = 0;
13551
14027
  for (const [face, offset] of CUBE_FACE_OFFSETS.entries()) {
13552
- const neighbor = pos.clone().add(new import_three35.Vector3(...offset));
14028
+ const neighbor = pos.clone().add(new import_three36.Vector3(...offset));
13553
14029
  if (this.getChunkAt(neighbor)?.isOccludingAt(neighbor)) {
13554
14030
  mask |= 1 << face;
13555
14031
  }
@@ -13583,14 +14059,14 @@ var MineRenderWorld = class {
13583
14059
  return this._chunks.get(this.worldPosToChunkKey(pos));
13584
14060
  }
13585
14061
  static worldToScenePosition(pos) {
13586
- return new import_three35.Vector3(
14062
+ return new import_three36.Vector3(
13587
14063
  pos.x * 16,
13588
14064
  pos.y * 16,
13589
14065
  pos.z * 16
13590
14066
  );
13591
14067
  }
13592
14068
  static sceneToWorldPosition(pos) {
13593
- return new import_three35.Vector3(
14069
+ return new import_three36.Vector3(
13594
14070
  pos.x / 16,
13595
14071
  pos.y / 16,
13596
14072
  pos.z / 16
@@ -13610,10 +14086,10 @@ var MineRenderWorld = class {
13610
14086
  };
13611
14087
 
13612
14088
  // src/world/SectionMesh.ts
13613
- var import_three36 = require("three");
14089
+ var import_three37 = require("three");
13614
14090
  init_CanvasCompat();
13615
14091
  init_Materials();
13616
- var SectionMesh = class _SectionMesh extends import_three36.Group {
14092
+ var SectionMesh = class _SectionMesh extends import_three37.Group {
13617
14093
  constructor() {
13618
14094
  super(...arguments);
13619
14095
  this.ownedMeshes = [];
@@ -13686,18 +14162,18 @@ var SectionMesh = class _SectionMesh extends import_three36.Group {
13686
14162
  for (let corner = 0; corner < 6; corner++) indices.push(start + sourceIndices.getX(face * 6 + corner) - face * 4);
13687
14163
  }
13688
14164
  }
13689
- const geometry = new import_three36.BufferGeometry();
13690
- geometry.setAttribute("position", new import_three36.Float32BufferAttribute(positions, 3));
13691
- geometry.setAttribute("normal", new import_three36.Float32BufferAttribute(normals, 3));
13692
- geometry.setAttribute("uv", new import_three36.Float32BufferAttribute(uvs, 2));
13693
- geometry.setAttribute("color", new import_three36.Float32BufferAttribute(colors, 3));
14165
+ const geometry = new import_three37.BufferGeometry();
14166
+ geometry.setAttribute("position", new import_three37.Float32BufferAttribute(positions, 3));
14167
+ geometry.setAttribute("normal", new import_three37.Float32BufferAttribute(normals, 3));
14168
+ geometry.setAttribute("uv", new import_three37.Float32BufferAttribute(uvs, 2));
14169
+ geometry.setAttribute("color", new import_three37.Float32BufferAttribute(colors, 3));
13694
14170
  geometry.setIndex(indices);
13695
14171
  geometry.computeBoundingBox();
13696
14172
  geometry.computeBoundingSphere();
13697
14173
  const material = Materials.createShadedCanvasMaterial(canvas, false);
13698
14174
  material.vertexColors = true;
13699
14175
  const texture = material.uniforms?.map?.value ?? material.map;
13700
- const mesh = new import_three36.Mesh(geometry, material);
14176
+ const mesh = new import_three37.Mesh(geometry, material);
13701
14177
  section.add(mesh);
13702
14178
  section.ownedMeshes.push({ mesh, texture });
13703
14179
  }
@@ -13731,10 +14207,10 @@ var Chunk = class _Chunk {
13731
14207
  }
13732
14208
  getBlockAt(posOrX, y, z) {
13733
14209
  if (typeof posOrX == "number") {
13734
- return this.getBlockAt(new import_three37.Vector3(posOrX, y, z));
14210
+ return this.getBlockAt(new import_three38.Vector3(posOrX, y, z));
13735
14211
  }
13736
14212
  if (isTripleArray(posOrX)) {
13737
- return this.getBlockAt(new import_three37.Vector3(posOrX[0], posOrX[1], posOrX[2]));
14213
+ return this.getBlockAt(new import_three38.Vector3(posOrX[0], posOrX[1], posOrX[2]));
13738
14214
  }
13739
14215
  const pos = this.worldPosToChunkPos(posOrX);
13740
14216
  const index = _Chunk.chunkPosToBlockIndex(pos);
@@ -13742,10 +14218,10 @@ var Chunk = class _Chunk {
13742
14218
  }
13743
14219
  async setBlockAt(posOrX, yOrBlock, z, block) {
13744
14220
  if (typeof posOrX == "number") {
13745
- return this.setBlockAt(new import_three37.Vector3(posOrX, yOrBlock, z), block);
14221
+ return this.setBlockAt(new import_three38.Vector3(posOrX, yOrBlock, z), block);
13746
14222
  }
13747
14223
  if (isTripleArray(posOrX)) {
13748
- return this.setBlockAt(new import_three37.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
14224
+ return this.setBlockAt(new import_three38.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
13749
14225
  }
13750
14226
  const worldPos = posOrX;
13751
14227
  const pos = this.worldPosToChunkPos(worldPos);
@@ -13774,7 +14250,8 @@ var Chunk = class _Chunk {
13774
14250
  this.data.set(index, void 0);
13775
14251
  return void 0;
13776
14252
  }
13777
- const template = getFluidKind(blockState.key, stored.properties) ? void 0 : await this.sectionModels?.get(blockState, stored.properties);
14253
+ const perBlock = !this.sectionModels || getFluidKind(blockState.key, stored.properties) || blockState.key && BlockEntities.entry(await BlockEntities.getIndex(blockState.key.root), blockState.key.toNamespacedString());
14254
+ const template = perBlock ? void 0 : await this.sectionModels.get(blockState, stored.properties);
13778
14255
  if (template) {
13779
14256
  this.sectionBlocks.set(index, { index, template, cullMask: 0 });
13780
14257
  this.meshDirty = true;
@@ -13830,7 +14307,7 @@ var Chunk = class _Chunk {
13830
14307
  }
13831
14308
  async clear(onBlocksChanged = this.onBlocksChanged) {
13832
14309
  const positions = [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
13833
- new import_three37.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
14310
+ new import_three38.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
13834
14311
  ));
13835
14312
  for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
13836
14313
  this.sectionBlocks.clear();
@@ -13854,14 +14331,14 @@ var Chunk = class _Chunk {
13854
14331
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
13855
14332
  }
13856
14333
  worldPosToChunkPos(pos) {
13857
- return new import_three37.Vector3(
14334
+ return new import_three38.Vector3(
13858
14335
  pos.x - this.x * 16,
13859
14336
  pos.y - this.y * 16,
13860
14337
  pos.z - this.z * 16
13861
14338
  );
13862
14339
  }
13863
14340
  chunkPosToWorldPos(pos) {
13864
- return new import_three37.Vector3(
14341
+ return new import_three38.Vector3(
13865
14342
  this.x * 16 + pos.x,
13866
14343
  this.y * 16 + pos.y,
13867
14344
  this.z * 16 + pos.z
@@ -13884,6 +14361,7 @@ var Chunk = class _Chunk {
13884
14361
  BUILTIN_GENERATED,
13885
14362
  BasicAssetKey,
13886
14363
  BatchedExecutor,
14364
+ BlockEntities,
13887
14365
  BlockObject,
13888
14366
  BlockStateResolver,
13889
14367
  BlockStates,
@@ -13905,7 +14383,9 @@ var Chunk = class _Chunk {
13905
14383
  DefaultBlockStates,
13906
14384
  DisplayPosition,
13907
14385
  DisplayTransforms,
14386
+ ENTITY_ANIMATION_CHANNELS,
13908
14387
  Entities,
14388
+ EntityAnimationPlayer,
13909
14389
  EntityObject,
13910
14390
  Env,
13911
14391
  FluidModelObject,
@@ -13981,6 +14461,7 @@ var Chunk = class _Chunk {
13981
14461
  createCanvas,
13982
14462
  createFluidGeometry,
13983
14463
  createImage,
14464
+ entityAnimationTime,
13984
14465
  estimateBytesUsed,
13985
14466
  getBlockFluidState,
13986
14467
  getFluidKind,
@@ -14013,6 +14494,8 @@ var Chunk = class _Chunk {
14013
14494
  mergeVertices,
14014
14495
  prefix,
14015
14496
  registerNodeEnv,
14497
+ sampleEntityAnimation,
14498
+ sampleEntityKeyframes,
14016
14499
  sampleFluid,
14017
14500
  serializeBoxGeometryKey,
14018
14501
  serializeImageKey,