minerender 2.1.0-beta.7 → 2.1.0-beta.8

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.
Files changed (73) hide show
  1. package/README.md +10 -1
  2. package/dist/browser/esm/armor/Armor.mjs +84 -0
  3. package/dist/browser/esm/armor/Armor.mjs.map +1 -0
  4. package/dist/browser/esm/armor/index.mjs +3 -0
  5. package/dist/browser/esm/armor/index.mjs.map +1 -0
  6. package/dist/browser/esm/assets/BlockEntities.mjs +2 -0
  7. package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
  8. package/dist/browser/esm/assets/Entities.mjs +39 -11
  9. package/dist/browser/esm/assets/Entities.mjs.map +1 -1
  10. package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
  11. package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
  12. package/dist/browser/esm/assets/ModelTextures.mjs +13 -7
  13. package/dist/browser/esm/assets/ModelTextures.mjs.map +1 -1
  14. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
  15. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
  16. package/dist/browser/esm/cache/Caching.mjs +8 -0
  17. package/dist/browser/esm/cache/Caching.mjs.map +1 -1
  18. package/dist/browser/esm/entity/scene/EntityObject.mjs +31 -5
  19. package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
  20. package/dist/browser/esm/env/browser/BrowserEnv.mjs +11 -4
  21. package/dist/browser/esm/env/browser/BrowserEnv.mjs.map +1 -1
  22. package/dist/browser/esm/index.browser.d.mts +129 -13
  23. package/dist/browser/esm/index.browser.mjs.map +1 -1
  24. package/dist/browser/esm/index.mjs +1 -0
  25. package/dist/browser/esm/index.mjs.map +1 -1
  26. package/dist/browser/esm/model/ItemGlint.mjs +7 -6
  27. package/dist/browser/esm/model/ItemGlint.mjs.map +1 -1
  28. package/dist/browser/esm/model/block/scene/BlockObject.mjs +16 -5
  29. package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
  30. package/dist/browser/esm/scene/SceneDocument.mjs +35 -5
  31. package/dist/browser/esm/scene/SceneDocument.mjs.map +1 -1
  32. package/dist/browser/esm/scene/SceneDocumentLoader.mjs +14 -3
  33. package/dist/browser/esm/scene/SceneDocumentLoader.mjs.map +1 -1
  34. package/dist/browser/esm/skin/SkinGeometries.mjs +4 -1
  35. package/dist/browser/esm/skin/SkinGeometries.mjs.map +1 -1
  36. package/dist/browser/esm/skin/SkinPart.mjs +2 -0
  37. package/dist/browser/esm/skin/SkinPart.mjs.map +1 -1
  38. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs +11 -1
  39. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs.map +1 -1
  40. package/dist/browser/esm/skin/SkinTextures.mjs +1 -1
  41. package/dist/browser/esm/skin/SkinTextures.mjs.map +1 -1
  42. package/dist/browser/esm/skin/scene/SkinObject.mjs +119 -7
  43. package/dist/browser/esm/skin/scene/SkinObject.mjs.map +1 -1
  44. package/dist/browser/esm/texture/PalettedTextures.mjs +46 -0
  45. package/dist/browser/esm/texture/PalettedTextures.mjs.map +1 -0
  46. package/dist/browser/esm/texture/index.mjs +1 -0
  47. package/dist/browser/esm/texture/index.mjs.map +1 -1
  48. package/dist/browser/esm/util/util.mjs +0 -2
  49. package/dist/browser/esm/util/util.mjs.map +1 -1
  50. package/dist/browser/esm/world/Chunk.mjs +62 -33
  51. package/dist/browser/esm/world/Chunk.mjs.map +1 -1
  52. package/dist/browser/esm/world/MineRenderWorld.mjs +98 -13
  53. package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
  54. package/dist/browser/esm/world/SectionMesh.mjs +65 -9
  55. package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
  56. package/dist/browser/esm/world/SectionModels.mjs +21 -15
  57. package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
  58. package/dist/browser/esm/world/SectionWorker.mjs +8 -2
  59. package/dist/browser/esm/world/SectionWorker.mjs.map +1 -1
  60. package/dist/browser/esm/world/WorldStreamer.mjs +109 -15
  61. package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
  62. package/dist/browser/index.d.ts +129 -13
  63. package/dist/browser/index.js +1592 -894
  64. package/dist/browser/index.js.map +1 -1
  65. package/dist/bundle.js +1330 -619
  66. package/dist/bundle.js.map +1 -1
  67. package/dist/node/index.d.mts +117 -12
  68. package/dist/node/index.d.ts +117 -12
  69. package/dist/node/index.js +1505 -793
  70. package/dist/node/index.js.map +1 -1
  71. package/dist/node/index.mjs +1303 -593
  72. package/dist/node/index.mjs.map +1 -1
  73. package/package.json +2 -1
package/dist/bundle.js CHANGED
@@ -1896,40 +1896,6 @@ var MineRender = (() => {
1896
1896
  }
1897
1897
  });
1898
1898
 
1899
- // src/cache/PersistentCache.ts
1900
- var _PersistentCache, PersistentCache;
1901
- var init_PersistentCache = __esm({
1902
- "src/cache/PersistentCache.ts"() {
1903
- init_dirname();
1904
- init_buffer2();
1905
- init_process2();
1906
- init_Env();
1907
- _PersistentCache = class _PersistentCache {
1908
- constructor(backing) {
1909
- this.backing = backing;
1910
- }
1911
- /** Opens a named store in the active environment using the current cache schema version. */
1912
- static open(name2) {
1913
- return Env.provider.openCache(name2, _PersistentCache.VERSION);
1914
- }
1915
- /** Loads a missing entry and stores only non-nullish results. */
1916
- async getOrLoad(key, loader) {
1917
- let v5 = await this.get(key);
1918
- if (typeof v5 === "undefined" || v5 === null) {
1919
- v5 = await loader(key);
1920
- if (typeof v5 !== "undefined" && v5 !== null) {
1921
- await this.put(key, v5);
1922
- }
1923
- }
1924
- return v5;
1925
- }
1926
- };
1927
- /** Bump to invalidate every persisted entry. */
1928
- _PersistentCache.VERSION = 2;
1929
- PersistentCache = _PersistentCache;
1930
- }
1931
- });
1932
-
1933
1899
  // src/util/log.ts
1934
1900
  function readSwitch() {
1935
1901
  switchRead = true;
@@ -2014,6 +1980,40 @@ var MineRender = (() => {
2014
1980
  }
2015
1981
  });
2016
1982
 
1983
+ // src/cache/PersistentCache.ts
1984
+ var _PersistentCache, PersistentCache;
1985
+ var init_PersistentCache = __esm({
1986
+ "src/cache/PersistentCache.ts"() {
1987
+ init_dirname();
1988
+ init_buffer2();
1989
+ init_process2();
1990
+ init_Env();
1991
+ _PersistentCache = class _PersistentCache {
1992
+ constructor(backing) {
1993
+ this.backing = backing;
1994
+ }
1995
+ /** Opens a named store in the active environment using the current cache schema version. */
1996
+ static open(name2) {
1997
+ return Env.provider.openCache(name2, _PersistentCache.VERSION);
1998
+ }
1999
+ /** Loads a missing entry and stores only non-nullish results. */
2000
+ async getOrLoad(key, loader) {
2001
+ let v5 = await this.get(key);
2002
+ if (typeof v5 === "undefined" || v5 === null) {
2003
+ v5 = await loader(key);
2004
+ if (typeof v5 !== "undefined" && v5 !== null) {
2005
+ await this.put(key, v5);
2006
+ }
2007
+ }
2008
+ return v5;
2009
+ }
2010
+ };
2011
+ /** Bump to invalidate every persisted entry. */
2012
+ _PersistentCache.VERSION = 2;
2013
+ PersistentCache = _PersistentCache;
2014
+ }
2015
+ });
2016
+
2017
2017
  // ../../node_modules/localforage/dist/localforage.js
2018
2018
  var require_localforage = __commonJS({
2019
2019
  "../../node_modules/localforage/dist/localforage.js"(exports13, module2) {
@@ -4180,7 +4180,7 @@ var MineRender = (() => {
4180
4180
  canvas.style.display = "block";
4181
4181
  return canvas;
4182
4182
  }
4183
- function log2(...params) {
4183
+ function log3(...params) {
4184
4184
  const message = "THREE." + params.shift();
4185
4185
  if (_setConsoleFunction) {
4186
4186
  _setConsoleFunction("log", message, ...params);
@@ -4852,7 +4852,7 @@ var MineRender = (() => {
4852
4852
  }
4853
4853
  throw new Error(`THREE.TextureUtils: Unknown texture type ${type}.`);
4854
4854
  }
4855
- var REVISION, MOUSE, TOUCH, CullFaceNone, CullFaceBack, CullFaceFront, PCFShadowMap, PCFSoftShadowMap, VSMShadowMap, FrontSide, BackSide, DoubleSide, NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstAlphaFactor, OneMinusDstAlphaFactor, DstColorFactor, OneMinusDstColorFactor, SrcAlphaSaturateFactor, ConstantColorFactor, OneMinusConstantColorFactor, ConstantAlphaFactor, OneMinusConstantAlphaFactor, NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth, MultiplyOperation, MixOperation, AddOperation, NoToneMapping, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, CustomToneMapping, AgXToneMapping, NeutralToneMapping, UVMapping, CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping, CubeUVReflectionMapping, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearFilter, LinearMipmapNearestFilter, LinearMipmapLinearFilter, UnsignedByteType, ByteType, ShortType, UnsignedShortType, IntType, UnsignedIntType, FloatType, HalfFloatType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedInt101111Type, AlphaFormat, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, RedFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, RG11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolateBezier, ZeroCurvatureEnding, ZeroSlopeEnding, WrapAroundEnding, TrianglesDrawMode, TriangleStripDrawMode, TriangleFanDrawMode, BasicDepthPacking, TangentSpaceNormalMap, ObjectSpaceNormalMap, NoColorSpace, SRGBColorSpace, LinearSRGBColorSpace, LinearTransfer, SRGBTransfer, KeepStencilOp, AlwaysStencilFunc, NeverCompare, LessCompare, EqualCompare, LessEqualCompare, GreaterCompare, NotEqualCompare, GreaterEqualCompare, AlwaysCompare, StaticDrawUsage, GLSL3, WebGLCoordinateSystem, WebGPUCoordinateSystem, _cache, _setConsoleFunction, ReversedDepthFuncs, EventDispatcher, _lut, _seed, DEG2RAD, RAD2DEG, MathUtils, _Vector2, Vector2, Quaternion, _Vector3, Vector3, _vector$c, _quaternion$5, _Matrix3, Matrix3, _m3, LINEAR_REC709_TO_XYZ, XYZ_TO_LINEAR_REC709, ColorManagement, _canvas, ImageUtils, _sourceId, TextureSource, _textureId, _tempVec3, Texture, _Vector4, Vector4, RenderTarget, WebGLRenderTarget, DataArrayTexture, Data3DTexture, _Matrix4, Matrix4, _v1$7, _m1$2, _zero, _one, _x, _y, _z, _matrix$2, _quaternion$4, Euler, Layers, _object3DId, _v1$6, _q1, _m1$1, _target, _position$4, _scale$3, _quaternion$3, _xAxis, _yAxis, _zAxis, _addedEvent, _removedEvent, _childaddedEvent, _childremovedEvent, Object3D, Group, _moveEvent, WebXRController, _colorKeywords, _hslA, _hslB, Color, _color, Scene, _v0$2, _v1$5, _v2$4, _v3$2, _vab, _vac, _vbc, _vap, _vbp, _vcp, _v40, _v41, _v42, Triangle, Box3, _points, _vector$b, _box$4, _v0$1, _v1$4, _v2$3, _f0, _f1, _f2, _center, _extents, _triangleNormal, _testAxis, _vector$a, _vector2$1, _id$2, BufferAttribute, Uint16BufferAttribute, Uint32BufferAttribute, Float32BufferAttribute, _box$3, _v1$3, _v2$2, Sphere, _id$1, _m1, _obj, _offset, _box$2, _boxMorphTargets, _vector$9, BufferGeometry, InterleavedBuffer, _vector$8, InterleavedBufferAttribute, _vector1, _vector2, _normalMatrix, Plane, _materialId, Material, _vector$7, _segCenter, _segDir, _diff, Ray, MeshBasicMaterial, _inverseMatrix$3, _ray$3, _sphere$6, _sphereHitAt, _vA, _vB, _vC, _tempA, _morphA, _intersectionPoint, _intersectionPointWorld, Mesh, DataTexture, InstancedBufferAttribute, _instanceLocalMatrix, _instanceWorldMatrix, _instanceIntersects, _box3, _identity, _mesh$1, _sphere$4, InstancedMesh, _sphere$3, _defaultSpriteCenter, _vector$6, Frustum, LineBasicMaterial, _vStart, _vEnd, _inverseMatrix$1, _ray$1, _sphere$1, _intersectPointOnRay, _intersectPointOnSegment, Line, _start, _end, LineSegments, CompressedTexture, CubeTexture, CanvasTexture, DepthTexture, CubeDepthTexture, ExternalTexture, BoxGeometry, _v0, _v1$1, _normal, _triangle, EdgesGeometry, PlaneGeometry, UniformsUtils, default_vertex, default_fragment, ShaderMaterial, RawShaderMaterial, MeshStandardMaterial, MeshDepthMaterial, MeshDistanceMaterial, Interpolant, CubicInterpolant, LinearInterpolant, DiscreteInterpolant, BezierInterpolant, KeyframeTrack, BooleanKeyframeTrack, ColorKeyframeTrack, NumberKeyframeTrack, QuaternionLinearInterpolant, QuaternionKeyframeTrack, StringKeyframeTrack, VectorKeyframeTrack, LoadingManager, DefaultLoadingManager, Loader, _position$2, _quaternion$2, _scale$2, Camera, _v3$1, _minTarget, _maxTarget, PerspectiveCamera, OrthographicCamera, fov, aspect, CubeCamera, ArrayCamera, _RESERVED_CHARS_RE, _reservedRe, _wordChar, _wordCharOrDot, _directoryRe, _nodeRe, _objectRe, _propertyRe, _trackRe, _supportedObjectNames, Composite, PropertyBinding, _controlInterpolantsResultBuffer, Uniform, _matrix, Raycaster, Spherical, _Matrix2, Matrix2, _vector$4, Box2, GridHelper, AxesHelper, Controls;
4855
+ var REVISION, MOUSE, TOUCH, CullFaceNone, CullFaceBack, CullFaceFront, PCFShadowMap, PCFSoftShadowMap, VSMShadowMap, FrontSide, BackSide, DoubleSide, NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstAlphaFactor, OneMinusDstAlphaFactor, DstColorFactor, OneMinusDstColorFactor, SrcAlphaSaturateFactor, ConstantColorFactor, OneMinusConstantColorFactor, ConstantAlphaFactor, OneMinusConstantAlphaFactor, NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth, MultiplyOperation, MixOperation, AddOperation, NoToneMapping, LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, CustomToneMapping, AgXToneMapping, NeutralToneMapping, UVMapping, CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping, CubeUVReflectionMapping, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearFilter, LinearMipmapNearestFilter, LinearMipmapLinearFilter, UnsignedByteType, ByteType, ShortType, UnsignedShortType, IntType, UnsignedIntType, FloatType, HalfFloatType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedInt101111Type, AlphaFormat, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, RedFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, R11_EAC_Format, SIGNED_R11_EAC_Format, RG11_EAC_Format, SIGNED_RG11_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolateBezier, ZeroCurvatureEnding, ZeroSlopeEnding, WrapAroundEnding, TrianglesDrawMode, TriangleStripDrawMode, TriangleFanDrawMode, BasicDepthPacking, TangentSpaceNormalMap, ObjectSpaceNormalMap, NoColorSpace, SRGBColorSpace, LinearSRGBColorSpace, LinearTransfer, SRGBTransfer, KeepStencilOp, AlwaysStencilFunc, NeverCompare, LessCompare, EqualCompare, LessEqualCompare, GreaterCompare, NotEqualCompare, GreaterEqualCompare, AlwaysCompare, StaticDrawUsage, DynamicDrawUsage, GLSL3, WebGLCoordinateSystem, WebGPUCoordinateSystem, _cache, _setConsoleFunction, ReversedDepthFuncs, EventDispatcher, _lut, _seed, DEG2RAD, RAD2DEG, MathUtils, _Vector2, Vector2, Quaternion, _Vector3, Vector3, _vector$c, _quaternion$5, _Matrix3, Matrix3, _m3, LINEAR_REC709_TO_XYZ, XYZ_TO_LINEAR_REC709, ColorManagement, _canvas, ImageUtils, _sourceId, TextureSource, _textureId, _tempVec3, Texture, _Vector4, Vector4, RenderTarget, WebGLRenderTarget, DataArrayTexture, Data3DTexture, _Matrix4, Matrix4, _v1$7, _m1$2, _zero, _one, _x, _y, _z, _matrix$2, _quaternion$4, Euler, Layers, _object3DId, _v1$6, _q1, _m1$1, _target, _position$4, _scale$3, _quaternion$3, _xAxis, _yAxis, _zAxis, _addedEvent, _removedEvent, _childaddedEvent, _childremovedEvent, Object3D, Group, _moveEvent, WebXRController, _colorKeywords, _hslA, _hslB, Color, _color, Scene, _v0$2, _v1$5, _v2$4, _v3$2, _vab, _vac, _vbc, _vap, _vbp, _vcp, _v40, _v41, _v42, Triangle, Box3, _points, _vector$b, _box$4, _v0$1, _v1$4, _v2$3, _f0, _f1, _f2, _center, _extents, _triangleNormal, _testAxis, _vector$a, _vector2$1, _id$2, BufferAttribute, Uint16BufferAttribute, Uint32BufferAttribute, Float32BufferAttribute, _box$3, _v1$3, _v2$2, Sphere, _id$1, _m1, _obj, _offset, _box$2, _boxMorphTargets, _vector$9, BufferGeometry, InterleavedBuffer, _vector$8, InterleavedBufferAttribute, _vector1, _vector2, _normalMatrix, Plane, _materialId, Material, _vector$7, _segCenter, _segDir, _diff, Ray, MeshBasicMaterial, _inverseMatrix$3, _ray$3, _sphere$6, _sphereHitAt, _vA, _vB, _vC, _tempA, _morphA, _intersectionPoint, _intersectionPointWorld, Mesh, DataTexture, InstancedBufferAttribute, _instanceLocalMatrix, _instanceWorldMatrix, _instanceIntersects, _box3, _identity, _mesh$1, _sphere$4, InstancedMesh, _sphere$3, _defaultSpriteCenter, _vector$6, Frustum, LineBasicMaterial, _vStart, _vEnd, _inverseMatrix$1, _ray$1, _sphere$1, _intersectPointOnRay, _intersectPointOnSegment, Line, _start, _end, LineSegments, CompressedTexture, CubeTexture, CanvasTexture, DepthTexture, CubeDepthTexture, ExternalTexture, BoxGeometry, _v0, _v1$1, _normal, _triangle, EdgesGeometry, PlaneGeometry, UniformsUtils, default_vertex, default_fragment, ShaderMaterial, RawShaderMaterial, MeshStandardMaterial, MeshDepthMaterial, MeshDistanceMaterial, Interpolant, CubicInterpolant, LinearInterpolant, DiscreteInterpolant, BezierInterpolant, KeyframeTrack, BooleanKeyframeTrack, ColorKeyframeTrack, NumberKeyframeTrack, QuaternionLinearInterpolant, QuaternionKeyframeTrack, StringKeyframeTrack, VectorKeyframeTrack, LoadingManager, DefaultLoadingManager, Loader, _position$2, _quaternion$2, _scale$2, Camera, _v3$1, _minTarget, _maxTarget, PerspectiveCamera, OrthographicCamera, fov, aspect, CubeCamera, ArrayCamera, _RESERVED_CHARS_RE, _reservedRe, _wordChar, _wordCharOrDot, _directoryRe, _nodeRe, _objectRe, _propertyRe, _trackRe, _supportedObjectNames, Composite, PropertyBinding, _controlInterpolantsResultBuffer, Uniform, _matrix, Raycaster, Spherical, _Matrix2, Matrix2, _vector$4, Box2, GridHelper, AxesHelper, Controls;
4856
4856
  var init_three_core = __esm({
4857
4857
  "../../node_modules/three/build/three.core.js"() {
4858
4858
  init_dirname();
@@ -5018,6 +5018,7 @@ var MineRender = (() => {
5018
5018
  GreaterEqualCompare = 518;
5019
5019
  AlwaysCompare = 519;
5020
5020
  StaticDrawUsage = 35044;
5021
+ DynamicDrawUsage = 35048;
5021
5022
  GLSL3 = "300 es";
5022
5023
  WebGLCoordinateSystem = 2e3;
5023
5024
  WebGPUCoordinateSystem = 2001;
@@ -15869,7 +15870,7 @@ var MineRender = (() => {
15869
15870
  */
15870
15871
  clone(data) {
15871
15872
  if (data === void 0) {
15872
- log2("InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.");
15873
+ log3("InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.");
15873
15874
  const array = [];
15874
15875
  for (let i4 = 0; i4 < this.count; i4++) {
15875
15876
  const index = i4 * this.data.stride + this.offset;
@@ -15898,7 +15899,7 @@ var MineRender = (() => {
15898
15899
  */
15899
15900
  toJSON(data) {
15900
15901
  if (data === void 0) {
15901
- log2("InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.");
15902
+ log3("InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.");
15902
15903
  const array = [];
15903
15904
  for (let i4 = 0; i4 < this.count; i4++) {
15904
15905
  const index = i4 * this.data.stride + this.offset;
@@ -31889,11 +31890,11 @@ void main() {
31889
31890
  };
31890
31891
  function onContextLost(event) {
31891
31892
  event.preventDefault();
31892
- log2("WebGLRenderer: Context Lost.");
31893
+ log3("WebGLRenderer: Context Lost.");
31893
31894
  _isContextLost = true;
31894
31895
  }
31895
31896
  function onContextRestore() {
31896
- log2("WebGLRenderer: Context Restored.");
31897
+ log3("WebGLRenderer: Context Restored.");
31897
31898
  _isContextLost = false;
31898
31899
  const infoAutoReset = info.autoReset;
31899
31900
  const shadowMapEnabled = shadowMap.enabled;
@@ -34067,8 +34068,6 @@ void main() {
34067
34068
  });
34068
34069
  }
34069
34070
  function yieldToEventLoop() {
34070
- const scheduler = globalThis.scheduler;
34071
- if (scheduler?.yield) return scheduler.yield();
34072
34071
  return new Promise((resolve) => {
34073
34072
  if (typeof MessageChannel !== "undefined") {
34074
34073
  const channel = new MessageChannel();
@@ -35699,9 +35698,12 @@ void main() {
35699
35698
  this.entityTextureCache,
35700
35699
  this.entityAnimationCache,
35701
35700
  this.blockEntityIndexCache,
35701
+ this.entityDatasetVersionCache,
35702
35702
  this.fontCache,
35703
35703
  this.unihexCache,
35704
35704
  this.bannerPatternCache,
35705
+ this.equipmentCache,
35706
+ this.trimCache,
35705
35707
  this.mineRenderDataCache,
35706
35708
  this.usernameUuidCache,
35707
35709
  this.biomeCache
@@ -35733,6 +35735,8 @@ void main() {
35733
35735
  };
35734
35736
  }
35735
35737
  };
35738
+ /** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */
35739
+ _Caching.MISSING = false;
35736
35740
  _Caching._generation = 0;
35737
35741
  _Caching.rawImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(5)).buildAsync();
35738
35742
  _Caching.imageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
@@ -35754,9 +35758,12 @@ void main() {
35754
35758
  _Caching.entityTextureCache = _Caching.createAssetCache();
35755
35759
  _Caching.entityAnimationCache = _Caching.createAssetCache();
35756
35760
  _Caching.blockEntityIndexCache = _Caching.createAssetCache();
35761
+ _Caching.entityDatasetVersionCache = _Caching.createAssetCache();
35757
35762
  _Caching.unihexCache = _Caching.createAssetCache();
35758
35763
  _Caching.fontCache = _Caching.createAssetCache();
35759
35764
  _Caching.bannerPatternCache = _Caching.createAssetCache();
35765
+ _Caching.equipmentCache = _Caching.createAssetCache();
35766
+ _Caching.trimCache = _Caching.createAssetCache();
35760
35767
  _Caching.mineRenderDataCache = _Caching.createAssetCache();
35761
35768
  _Caching.usernameUuidCache = Caches.builder().expireAfterWrite(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
35762
35769
  _Caching.biomeCache = _Caching.createAssetCache();
@@ -36231,7 +36238,7 @@ void main() {
36231
36238
  signal.removeEventListener("abort", abort2);
36232
36239
  }
36233
36240
  }
36234
- var import_jobqu, log3, RequestError, RequestQueue, Requests;
36241
+ var import_jobqu, log4, RequestError, RequestQueue, Requests;
36235
36242
  var init_Requests = __esm({
36236
36243
  "src/request/Requests.ts"() {
36237
36244
  init_dirname();
@@ -36239,7 +36246,7 @@ void main() {
36239
36246
  init_process2();
36240
36247
  import_jobqu = __toESM(require_src());
36241
36248
  init_log();
36242
- log3 = logger("Requests");
36249
+ log4 = logger("Requests");
36243
36250
  RequestError = class extends Error {
36244
36251
  constructor(message, response, cause) {
36245
36252
  super(message);
@@ -36266,7 +36273,7 @@ void main() {
36266
36273
  try {
36267
36274
  return await abortable(this.queue.add(request), signal);
36268
36275
  } catch (error2) {
36269
- log3.debug("Request failed", error2);
36276
+ log4.debug("Request failed", error2);
36270
36277
  const delay = this.retryDelay(error2, request, retries);
36271
36278
  if (delay === void 0) {
36272
36279
  throw error2;
@@ -36454,7 +36461,7 @@ void main() {
36454
36461
  });
36455
36462
 
36456
36463
  // src/image/ImageLoader.ts
36457
- var log4, ImageLoader2;
36464
+ var log5, ImageLoader2;
36458
36465
  var init_ImageLoader = __esm({
36459
36466
  "src/image/ImageLoader.ts"() {
36460
36467
  init_dirname();
@@ -36468,7 +36475,7 @@ void main() {
36468
36475
  init_WrappedImage();
36469
36476
  init_base64();
36470
36477
  init_log();
36471
- log4 = logger("ImageLoader");
36478
+ log5 = logger("ImageLoader");
36472
36479
  ImageLoader2 = class _ImageLoader {
36473
36480
  static _createImage() {
36474
36481
  return createImage();
@@ -36493,7 +36500,7 @@ void main() {
36493
36500
  return image;
36494
36501
  }
36495
36502
  static async loadData(src) {
36496
- log4.debug("loadData", src);
36503
+ log5.debug("loadData", src);
36497
36504
  const image = await this.loadCanvasData(src);
36498
36505
  return image.data.getImageData(0, 0, image.width, image.height);
36499
36506
  }
@@ -36600,7 +36607,7 @@ void main() {
36600
36607
  });
36601
36608
 
36602
36609
  // src/texture/TextureLoader.ts
36603
- var log5, TextureLoader2;
36610
+ var log6, TextureLoader2;
36604
36611
  var init_TextureLoader = __esm({
36605
36612
  "src/texture/TextureLoader.ts"() {
36606
36613
  init_dirname();
@@ -36611,7 +36618,7 @@ void main() {
36611
36618
  init_ImageLoader();
36612
36619
  init_Textures();
36613
36620
  init_log();
36614
- log5 = logger("TextureLoader");
36621
+ log6 = logger("TextureLoader");
36615
36622
  TextureLoader2 = class {
36616
36623
  /** Reports whether image loading failed, so cached textures can be retried. */
36617
36624
  static hasFailed(texture) {
@@ -36627,7 +36634,7 @@ void main() {
36627
36634
  texture.needsUpdate = true;
36628
36635
  }, (error2) => {
36629
36636
  this.failedTextures.add(texture);
36630
- log5.warn("Failed to load texture", src, error2);
36637
+ log6.warn("Failed to load texture", src, error2);
36631
36638
  });
36632
36639
  texture.image = image;
36633
36640
  texture.format = format3;
@@ -36643,7 +36650,7 @@ void main() {
36643
36650
  texture.needsUpdate = true;
36644
36651
  }).catch((error2) => {
36645
36652
  this.failedTextures.add(texture);
36646
- log5.warn("Failed to load texture", src, error2);
36653
+ log6.warn("Failed to load texture", src, error2);
36647
36654
  });
36648
36655
  texture.format = format3;
36649
36656
  texture.rotation = rotation;
@@ -36722,7 +36729,7 @@ void main() {
36722
36729
  });
36723
36730
 
36724
36731
  // src/Materials.ts
36725
- var log6, Materials;
36732
+ var log7, Materials;
36726
36733
  var init_Materials = __esm({
36727
36734
  "src/Materials.ts"() {
36728
36735
  init_dirname();
@@ -36734,7 +36741,7 @@ void main() {
36734
36741
  init_TextureLoader();
36735
36742
  init_Caching();
36736
36743
  init_log();
36737
- log6 = logger("Materials");
36744
+ log7 = logger("Materials");
36738
36745
  Materials = class _Materials {
36739
36746
  /** Shared checkerboard material, created on first access. */
36740
36747
  static get MISSING_TEXTURE() {
@@ -37005,7 +37012,7 @@ void main() {
37005
37012
  Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });
37006
37013
  return material;
37007
37014
  } catch (e6) {
37008
- log6.warn(e6);
37015
+ log7.warn(e6);
37009
37016
  }
37010
37017
  return this.createBasicCanvasMaterial(canvas, transparent, shade);
37011
37018
  }
@@ -58567,7 +58574,7 @@ void main() {
58567
58574
  exports$17.callbackify = callbackify2;
58568
58575
  return exports$17;
58569
58576
  }
58570
- var exports$c4, _dewExec$b4, exports$b4, _dewExec$a4, exports$a4, _dewExec$94, exports$94, _dewExec$84, exports$84, _dewExec$74, exports$74, _dewExec$64, exports$64, _dewExec$54, _global$22, exports$54, _dewExec$44, _global$12, exports$44, _dewExec$34, exports$34, _dewExec$25, exports$25, _dewExec$15, exports$17, _dewExec9, _global4, exports11, _extend, callbackify, debuglog, deprecate, format, inherits, inspect, isArray, isBoolean, isBuffer, isDate, isError, isFunction, isNull, isNullOrUndefined, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, log7, promisify3, types, TextEncoder2, TextDecoder2;
58577
+ var exports$c4, _dewExec$b4, exports$b4, _dewExec$a4, exports$a4, _dewExec$94, exports$94, _dewExec$84, exports$84, _dewExec$74, exports$74, _dewExec$64, exports$64, _dewExec$54, _global$22, exports$54, _dewExec$44, _global$12, exports$44, _dewExec$34, exports$34, _dewExec$25, exports$25, _dewExec$15, exports$17, _dewExec9, _global4, exports11, _extend, callbackify, debuglog, deprecate, format, inherits, inspect, isArray, isBoolean, isBuffer, isDate, isError, isFunction, isNull, isNullOrUndefined, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, log8, promisify3, types, TextEncoder2, TextDecoder2;
58571
58578
  var init_util3 = __esm({
58572
58579
  "../../node_modules/@jspm/core/nodelibs/browser/util.js"() {
58573
58580
  init_dirname();
@@ -58651,7 +58658,7 @@ void main() {
58651
58658
  isString = exports11.isString;
58652
58659
  isSymbol = exports11.isSymbol;
58653
58660
  isUndefined = exports11.isUndefined;
58654
- log7 = exports11.log;
58661
+ log8 = exports11.log;
58655
58662
  promisify3 = exports11.promisify;
58656
58663
  types = exports11.types;
58657
58664
  TextEncoder2 = exports11.TextEncoder = globalThis.TextEncoder;
@@ -71057,7 +71064,7 @@ return ${compiler2.callType("value", tagType)}
71057
71064
  });
71058
71065
 
71059
71066
  // src/assets/source/HostedAssetSource.ts
71060
- var BINARY_TIMEOUT, log8, DEFAULT_OPTIONS2, _HostedAssetSource, HostedAssetSource;
71067
+ var BINARY_TIMEOUT, log9, DEFAULT_OPTIONS2, _HostedAssetSource, HostedAssetSource;
71061
71068
  var init_HostedAssetSource = __esm({
71062
71069
  "src/assets/source/HostedAssetSource.ts"() {
71063
71070
  init_dirname();
@@ -71074,7 +71081,7 @@ return ${compiler2.callType("value", tagType)}
71074
71081
  init_parser();
71075
71082
  init_merge();
71076
71083
  BINARY_TIMEOUT = 6e4;
71077
- log8 = logger("HostedAssetSource");
71084
+ log9 = logger("HostedAssetSource");
71078
71085
  DEFAULT_OPTIONS2 = {
71079
71086
  retryDefaults: true
71080
71087
  };
@@ -71086,14 +71093,14 @@ return ${compiler2.callType("value", tagType)}
71086
71093
  return direct;
71087
71094
  }
71088
71095
  if (key.namespace !== DEFAULT_NAMESPACE) {
71089
- log8.debug("Retrying", key, "with default namespace");
71096
+ log9.debug("Retrying", key, "with default namespace");
71090
71097
  const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);
71091
71098
  const namespaced = await this.load(namespaceKey, parser);
71092
71099
  if (typeof namespaced !== "undefined") {
71093
71100
  return namespaced;
71094
71101
  }
71095
71102
  if (typeof key.root !== "undefined" && key.root !== AssetLoader.ROOT || typeof this.root !== "undefined" && this.root !== AssetLoader.ROOT) {
71096
- log8.debug("Retrying", key, "with default root+namespace");
71103
+ log9.debug("Retrying", key, "with default root+namespace");
71097
71104
  const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);
71098
71105
  const namespacedRooted = await this.load(namespacedRootedKey, parser);
71099
71106
  if (typeof namespacedRooted !== "undefined") {
@@ -71101,7 +71108,7 @@ return ${compiler2.callType("value", tagType)}
71101
71108
  }
71102
71109
  }
71103
71110
  } else if (typeof key.root !== "undefined" && key.root !== AssetLoader.ROOT || typeof this.root !== "undefined" && this.root !== AssetLoader.ROOT) {
71104
- log8.debug("Retrying", key, "with default root");
71111
+ log9.debug("Retrying", key, "with default root");
71105
71112
  const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);
71106
71113
  const rooted = await this.load(rootKey, parser);
71107
71114
  if (typeof rooted !== "undefined") {
@@ -71112,7 +71119,7 @@ return ${compiler2.callType("value", tagType)}
71112
71119
  }
71113
71120
  async load(key, parser) {
71114
71121
  const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
71115
- log8.debug("Loading", url);
71122
+ log9.debug("Loading", url);
71116
71123
  const request = { url };
71117
71124
  try {
71118
71125
  parser.config(request);
@@ -81238,7 +81245,7 @@ return ${compiler2.callType("value", tagType)}
81238
81245
  });
81239
81246
 
81240
81247
  // src/assets/AssetLoader.ts
81241
- var log9, AssetLoader;
81248
+ var log10, AssetLoader;
81242
81249
  var init_AssetLoader = __esm({
81243
81250
  "src/assets/AssetLoader.ts"() {
81244
81251
  init_dirname();
@@ -81249,7 +81256,7 @@ return ${compiler2.callType("value", tagType)}
81249
81256
  init_log();
81250
81257
  init_source();
81251
81258
  init_Caching();
81252
- log9 = logger("AssetLoader");
81259
+ log10 = logger("AssetLoader");
81253
81260
  AssetLoader = class {
81254
81261
  static get _SOURCES() {
81255
81262
  return this.sources ?? (this.sources = [{ key: "mcassets", source: new HostedAssetSource(this.ROOT, { retryDefaults: false }) }]);
@@ -81304,11 +81311,11 @@ ${key}` : key;
81304
81311
  if (override) {
81305
81312
  const existing = this.removeSource(key);
81306
81313
  if (existing) {
81307
- log9.info("Removed existing AssetSource", key);
81314
+ log10.info("Removed existing AssetSource", key);
81308
81315
  }
81309
81316
  }
81310
81317
  this._SOURCES.unshift({ key, source });
81311
- log9.info("Added AssetSource", key);
81318
+ log10.info("Added AssetSource", key);
81312
81319
  }
81313
81320
  /** Removes and returns the first source with this name. Call {@link Caching.clear} to reload assets. */
81314
81321
  static removeSource(key) {
@@ -81426,15 +81433,21 @@ ${key}` : key;
81426
81433
  key.extension += ".mcmeta";
81427
81434
  }
81428
81435
  const keyStr = key.serialize();
81429
- return Caching.textureMetaCache.get(keyStr, (k4) => {
81430
- return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
81431
- return AssetLoader.get(key, "meta" /* META */).then((asset2) => {
81432
- if (asset2)
81433
- asset2.key = key;
81434
- return asset2;
81435
- });
81436
+ const meta = await Caching.textureMetaCache.get(keyStr, (k4) => {
81437
+ return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), async (k1) => {
81438
+ if (AssetLoader.persistentScope === "") {
81439
+ const path = key.getFullPath();
81440
+ const slash = path.lastIndexOf("/");
81441
+ const listKey = new AssetKey(key.namespace, `${path.slice(0, slash + 1)}_list`, "textures", void 0, "assets", ".json", key.root);
81442
+ const list2 = await Caching.listAssetCache.get(listKey.serialize(), () => AssetLoader.get(listKey, "list" /* LIST */)).catch(() => void 0);
81443
+ if (list2 && !list2.files.includes(`${path.slice(slash + 1)}${key.extension}`)) return Caching.MISSING;
81444
+ }
81445
+ const asset2 = await AssetLoader.get(key, "meta" /* META */);
81446
+ if (asset2) asset2.key = key;
81447
+ return asset2 ?? Caching.MISSING;
81436
81448
  });
81437
81449
  });
81450
+ return meta === Caching.MISSING ? void 0 : meta;
81438
81451
  }
81439
81452
  /** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */
81440
81453
  static async clearCache() {
@@ -81494,14 +81507,14 @@ ${key}` : key;
81494
81507
  });
81495
81508
 
81496
81509
  // src/Ticker.ts
81497
- var log10, _Ticker, Ticker;
81510
+ var log11, _Ticker, Ticker;
81498
81511
  var init_Ticker = __esm({
81499
81512
  "src/Ticker.ts"() {
81500
81513
  init_dirname();
81501
81514
  init_buffer2();
81502
81515
  init_process2();
81503
81516
  init_log();
81504
- log10 = logger("Ticker");
81517
+ log11 = logger("Ticker");
81505
81518
  _Ticker = class _Ticker {
81506
81519
  static schedule(fn, ms) {
81507
81520
  const handle = setInterval(fn, ms);
@@ -81519,7 +81532,7 @@ ${key}` : key;
81519
81532
  try {
81520
81533
  t5();
81521
81534
  } catch (e6) {
81522
- log10.warn(e6);
81535
+ log11.warn(e6);
81523
81536
  }
81524
81537
  });
81525
81538
  _Ticker.oneSecondTicks++;
@@ -81773,7 +81786,7 @@ ${key}` : key;
81773
81786
  });
81774
81787
 
81775
81788
  // src/UVMapper.ts
81776
- var log11, X3, Y4, Z3, FACE_UV_AXES, UVMapper, MinecraftFaceUV;
81789
+ var log12, X3, Y4, Z3, FACE_UV_AXES, UVMapper, MinecraftFaceUV;
81777
81790
  var init_UVMapper = __esm({
81778
81791
  "src/UVMapper.ts"() {
81779
81792
  init_dirname();
@@ -81791,7 +81804,7 @@ ${key}` : key;
81791
81804
  init_ModelGenerator();
81792
81805
  init_log();
81793
81806
  init_cubeUv();
81794
- log11 = logger("UVMapper");
81807
+ log12 = logger("UVMapper");
81795
81808
  X3 = 0;
81796
81809
  Y4 = 1;
81797
81810
  Z3 = 2;
@@ -82024,7 +82037,7 @@ ${key}` : key;
82024
82037
  model.elements = originalModel.elements.map((element) => ({ ...element }));
82025
82038
  }
82026
82039
  const isItemModel = !("elements" in model);
82027
- log11.debug("Creating Atlas for", model.key);
82040
+ log12.debug("Creating Atlas for", model.key);
82028
82041
  if (model.textures) {
82029
82042
  const promises = [];
82030
82043
  const uniqueTextureNames = [];
@@ -82038,7 +82051,7 @@ ${key}` : key;
82038
82051
  const assetKey = AssetKey.parse("textures", textureValue, model.key);
82039
82052
  promises.push(ModelTextures.get(assetKey).then((asset2) => {
82040
82053
  if (!asset2) {
82041
- log11.warn("Missing texture", assetKey);
82054
+ log12.warn("Missing texture", assetKey);
82042
82055
  return;
82043
82056
  }
82044
82057
  textureMap[textureKey] = new WrappedImage(asset2);
@@ -82050,7 +82063,7 @@ ${key}` : key;
82050
82063
  }
82051
82064
  await Promise.all(promises);
82052
82065
  const textureCount = uniqueTextureNames.length;
82053
- log11.debug("Creating Atlas for", textureCount, "textures");
82066
+ log12.debug("Creating Atlas for", textureCount, "textures");
82054
82067
  this.fillMissingTextureKeys(model.textures, textureMap);
82055
82068
  this.fillMissingTextureKeys(model.textures, metaMap);
82056
82069
  const sizes = {};
@@ -82081,7 +82094,7 @@ ${key}` : key;
82081
82094
  this.fillMissingTextureKeys(model.textures, sizes);
82082
82095
  const s4 = Math.ceil(Math.sqrt(textureCount + 1));
82083
82096
  const size = Math.ceil(s4 * maxWidth);
82084
- log11.debug("Atlas size:", size);
82097
+ log12.debug("Atlas size:", size);
82085
82098
  const squaredSize = size * size;
82086
82099
  const image = new CanvasImage(size, size);
82087
82100
  const missing = Textures.getMissing().image;
@@ -82160,7 +82173,7 @@ ${key}` : key;
82160
82173
  }
82161
82174
  this.fillMissingTextureKeys(model.textures, positions);
82162
82175
  if (isItemModel) {
82163
- log11.debug("Generating item model for", model);
82176
+ log12.debug("Generating item model for", model);
82164
82177
  model.elements = [];
82165
82178
  for (let layerName of ModelGenerator.ITEM_LAYERS) {
82166
82179
  const textureImage = textureMap[layerName];
@@ -82176,7 +82189,7 @@ ${key}` : key;
82176
82189
  ), layerName));
82177
82190
  }
82178
82191
  }
82179
- log11.debug("Item model elements", model.elements);
82192
+ log12.debug("Item model elements", model.elements);
82180
82193
  }
82181
82194
  if (!model.elements) {
82182
82195
  }
@@ -82233,7 +82246,7 @@ ${key}` : key;
82233
82246
  hasTranslucency
82234
82247
  );
82235
82248
  } else {
82236
- log11.warn("Model does not have any textures", model);
82249
+ log12.warn("Model does not have any textures", model);
82237
82250
  }
82238
82251
  return void 0;
82239
82252
  }
@@ -82360,26 +82373,318 @@ ${key}` : key;
82360
82373
  }
82361
82374
  });
82362
82375
 
82376
+ // src/assets/_versions/DatasetVersions.ts
82377
+ var parseRelease, compare2, nearestRelease;
82378
+ var init_DatasetVersions = __esm({
82379
+ "src/assets/_versions/DatasetVersions.ts"() {
82380
+ init_dirname();
82381
+ init_buffer2();
82382
+ init_process2();
82383
+ parseRelease = (value) => /^\d+\.\d+(?:\.\d+)?$/.test(value) ? value.split(".").map(Number) : void 0;
82384
+ compare2 = (left, right) => {
82385
+ for (let i4 = 0; i4 < 3; i4++) {
82386
+ const difference = (left[i4] ?? 0) - (right[i4] ?? 0);
82387
+ if (difference) return difference;
82388
+ }
82389
+ return 0;
82390
+ };
82391
+ nearestRelease = (requestedVersion, published) => {
82392
+ const requested = parseRelease(requestedVersion);
82393
+ if (!requested) return void 0;
82394
+ const versions2 = published.map((name2) => ({ name: name2, number: parseRelease(name2) })).filter((entry) => !!entry.number).sort((left, right) => compare2(left.number, right.number));
82395
+ const sameLine = versions2.filter((entry) => entry.number[0] === requested[0] && entry.number[1] === requested[1]);
82396
+ const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0)) - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare2(left.number, right.number))[0] ?? versions2.filter((entry) => compare2(entry.number, requested) <= 0).pop() ?? versions2[0];
82397
+ return selected?.name;
82398
+ };
82399
+ }
82400
+ });
82401
+
82402
+ // src/error/MineRenderError.ts
82403
+ var MineRenderError;
82404
+ var init_MineRenderError = __esm({
82405
+ "src/error/MineRenderError.ts"() {
82406
+ init_dirname();
82407
+ init_buffer2();
82408
+ init_process2();
82409
+ MineRenderError = class _MineRenderError extends Error {
82410
+ constructor(msg) {
82411
+ super(msg);
82412
+ Object.setPrototypeOf(this, _MineRenderError.prototype);
82413
+ }
82414
+ get name() {
82415
+ return "MineRenderError";
82416
+ }
82417
+ };
82418
+ }
82419
+ });
82420
+
82421
+ // src/assets/Entities.ts
82422
+ var Entities;
82423
+ var init_Entities = __esm({
82424
+ "src/assets/Entities.ts"() {
82425
+ init_dirname();
82426
+ init_buffer2();
82427
+ init_process2();
82428
+ init_AssetKey();
82429
+ init_DatasetVersions();
82430
+ init_AssetLoader();
82431
+ init_source();
82432
+ init_Caching();
82433
+ init_AssetDefaults();
82434
+ init_MineRenderError();
82435
+ init_ModelTextures();
82436
+ Entities = class {
82437
+ /**
82438
+ * Resolves `root` (default: the active version). Uses the exact dataset when published or when the
82439
+ * version is not a release; otherwise selects the nearest published release, like {@link MineRenderData.resolve}.
82440
+ * Textures keep the requested root.
82441
+ */
82442
+ static async getDatasetRoot(root) {
82443
+ const requestRoot = (root ?? AssetLoader.ROOT).replace(/\/+$/, "");
82444
+ const requestedVersion = requestRoot.slice(requestRoot.lastIndexOf("/") + 1);
82445
+ const base = requestRoot.slice(0, requestRoot.lastIndexOf("/"));
82446
+ const selected = await Caching.entityDatasetVersionCache.get(root ?? `sources:${AssetLoader.ROOT}`, async () => {
82447
+ const key = new AssetKey("entity-models", "version", void 0, void 0, void 0, ".json", root);
82448
+ key.rootType = void 0;
82449
+ if (!parseRelease(requestedVersion) || await AssetLoader.get(key, "json" /* JSON */) !== void 0) return requestedVersion;
82450
+ const indexKey = new AssetKey("entity-models", "versions", void 0, void 0, void 0, ".json", base);
82451
+ indexKey.rootType = void 0;
82452
+ const index = await AssetLoader.get(indexKey, "json" /* JSON */);
82453
+ if (index === void 0) return requestedVersion;
82454
+ if (!index || typeof index !== "object" || Array.isArray(index) || !Array.isArray(index.versions) || !index.versions.every((entry) => entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.name === "string")) {
82455
+ throw new MineRenderError(`Invalid entity model version index at ${base}/entity-models/versions.json`);
82456
+ }
82457
+ return nearestRelease(requestedVersion, index.versions.map((entry) => entry.name)) ?? requestedVersion;
82458
+ });
82459
+ return selected === requestedVersion ? root : `${base}/${selected}`;
82460
+ }
82461
+ /** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */
82462
+ static async getEntityList() {
82463
+ const root = await this.getDatasetRoot();
82464
+ const collect = async (path) => {
82465
+ const prefix2 = path ? `${path}/` : "";
82466
+ const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json", root);
82467
+ const list2 = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
82468
+ if (!list2) return [];
82469
+ const files = list2.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
82470
+ const children = await Promise.all(list2.directories.map((directory) => collect(`${prefix2}${directory}`)));
82471
+ return [...files, ...children.flat()];
82472
+ };
82473
+ return collect("");
82474
+ }
82475
+ /** @internal */
82476
+ static async getModelFile(modelKey) {
82477
+ const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
82478
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : void 0));
82479
+ return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
82480
+ }
82481
+ /** Returns selectable geometry-layer names, or an empty list when the model is missing. */
82482
+ static async getLayerList(modelKey) {
82483
+ return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
82484
+ }
82485
+ /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
82486
+ static async getPassList(modelKey) {
82487
+ return (await this.getModelFile(modelKey))?.passes ?? [];
82488
+ }
82489
+ /**
82490
+ * Loads the layers and textures to pass to {@link MineRenderScene.addEntity}.
82491
+ * By default, selects `main`, unconditional passes, and passes enabled by `options.when`.
82492
+ *
82493
+ * @param modelKey - Dataset model, such as `new BasicAssetKey("minecraft", "zombie")`.
82494
+ * @param textureKey - Texture override for the first selected layer.
82495
+ * @param options - Layer selection, conditional passes, and per-layer texture overrides.
82496
+ * @returns The selected model, or `undefined` when its dataset file is missing.
82497
+ */
82498
+ static async getEntity(modelKey, textureKey, options) {
82499
+ const model = await this.getModelFile(modelKey);
82500
+ if (!model) return void 0;
82501
+ const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
82502
+ const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
82503
+ if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
82504
+ draws.push(...passes);
82505
+ const names = [];
82506
+ const selected = draws.map((pass) => {
82507
+ const layer = model.layers[pass.layer];
82508
+ if (!layer) {
82509
+ throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
82510
+ }
82511
+ let name2 = pass.layer;
82512
+ for (let n4 = 2; names.includes(name2); n4++) name2 = `${pass.layer}#${n4}`;
82513
+ names.push(name2);
82514
+ return { name: name2, layer, pass };
82515
+ });
82516
+ const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name: name2, layer, pass }, index) => {
82517
+ const override = options?.textures?.[name2] ?? (index === 0 ? textureKey : void 0);
82518
+ const textureLocation = pass.textureLocation ?? layer.textureLocation;
82519
+ let texture;
82520
+ if (override) {
82521
+ const path = isAssetKey(override) ? override.getFullPath() : override.path;
82522
+ 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);
82523
+ } else if (textureLocation !== void 0) {
82524
+ texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
82525
+ if (isAssetKey(modelKey)) texture.root = modelKey.root;
82526
+ } else {
82527
+ texture = await this.resolveTexture(modelKey);
82528
+ }
82529
+ const render = pass.render ?? layer.render;
82530
+ return [name2, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
82531
+ })));
82532
+ return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
82533
+ }
82534
+ /**
82535
+ * Native and sampled vanilla clips by name, or undefined when the model or selected version has none.
82536
+ */
82537
+ static async getAnimations(modelKey) {
82538
+ const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
82539
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : void 0));
82540
+ const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
82541
+ return file?.animations;
82542
+ }
82543
+ /** Finds a fallback texture using the model path, its directory, and vanilla variant data. */
82544
+ static async resolveTexture(modelKey) {
82545
+ const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
82546
+ const root = isAssetKey(modelKey) ? modelKey.root : void 0;
82547
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", root);
82548
+ const texture = await Caching.entityTextureCache.get(key.serialize(), async () => {
82549
+ const name2 = path.split("/").pop();
82550
+ for (const candidate of [path, `${path}/${name2}`]) {
82551
+ const texture3 = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png", root);
82552
+ if (await ModelTextures.get(texture3)) return texture3;
82553
+ }
82554
+ const listKey = new AssetKey(modelKey.namespace, "_list", `${name2}_variant`, void 0, "data", ".json", root);
82555
+ const list2 = await AssetLoader.get(listKey, "list" /* LIST */);
82556
+ const files = list2?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
82557
+ const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
82558
+ if (!file) return Caching.MISSING;
82559
+ const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name2}_variant`, void 0, "data", ".json", root);
82560
+ const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
82561
+ const assets = variant?.assets;
82562
+ const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
82563
+ if (typeof textureId !== "string") return Caching.MISSING;
82564
+ const texture2 = AssetKey.parse("textures", textureId);
82565
+ texture2.root = root;
82566
+ return texture2;
82567
+ });
82568
+ return texture === Caching.MISSING ? void 0 : texture;
82569
+ }
82570
+ /** @deprecated Use getEntityList(); block entities share the entity dataset. */
82571
+ static getBlockList() {
82572
+ return this.getEntityList();
82573
+ }
82574
+ /** @deprecated Use getEntity(); block entities share the entity dataset. */
82575
+ static getBlock(modelKey, textureKey, options) {
82576
+ return this.getEntity(modelKey, textureKey, options);
82577
+ }
82578
+ };
82579
+ }
82580
+ });
82581
+
82582
+ // src/armor/Armor.ts
82583
+ var Armor_exports = {};
82584
+ __export(Armor_exports, {
82585
+ Armor: () => Armor
82586
+ });
82587
+ var ARMOR_TRANSFORM, Armor;
82588
+ var init_Armor = __esm({
82589
+ "src/armor/Armor.ts"() {
82590
+ init_dirname();
82591
+ init_buffer2();
82592
+ init_process2();
82593
+ init_AssetKey();
82594
+ init_AssetLoader();
82595
+ init_Entities();
82596
+ init_AssetParsers();
82597
+ init_Caching();
82598
+ init_MineRenderError();
82599
+ ARMOR_TRANSFORM = [
82600
+ { rotate: [0, Math.PI, 0] },
82601
+ { scale: [-1, -1, 1] },
82602
+ { translate: [0, -24, 0] }
82603
+ ];
82604
+ Armor = class {
82605
+ /** Loads 1.21.4+ armor in SkinObject's frame, or returns undefined when no layer draws. */
82606
+ static async getEntity(armor) {
82607
+ const model = await Entities.getModelFile(new BasicAssetKey("minecraft", "player"));
82608
+ const layers = {};
82609
+ const slots = { chest: "chestplate", legs: "leggings", feet: "boots", head: "helmet" };
82610
+ for (const slot of Object.keys(slots)) {
82611
+ const value = armor[slot];
82612
+ if (value === void 0) continue;
82613
+ const piece = typeof value === "string" ? { asset: value } : value;
82614
+ const name2 = slots[slot], geometry = model?.layers[name2];
82615
+ if (!geometry) throw new MineRenderError(`Missing armor geometry ${name2}; armor needs Minecraft 1.21.4 or later`);
82616
+ const id = this.identifier(piece.asset);
82617
+ const key = new AssetKey(id.namespace, id.path, "equipment", void 0, "assets", ".json");
82618
+ const equipment = await Caching.equipmentCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
82619
+ if (!equipment) throw new MineRenderError(`Missing equipment asset ${piece.asset}; armor takes equipment asset IDs such as minecraft:diamond and needs Minecraft 1.21.4 or later`);
82620
+ const layerType = slot === "legs" ? "humanoid_leggings" : "humanoid";
82621
+ const equipmentLayers = equipment.layers[layerType];
82622
+ if (!equipmentLayers?.length) continue;
82623
+ let count = 0;
82624
+ const add = (texture, settings) => {
82625
+ layers[++count === 1 ? name2 : `${name2}#${count}`] = { key: texture, texture, layer: geometry, ...settings };
82626
+ };
82627
+ let glint = piece.glint;
82628
+ for (const layer of equipmentLayers) {
82629
+ let color3;
82630
+ if (layer.dyeable) {
82631
+ const undyed = layer.dyeable.color_when_undyed;
82632
+ color3 = piece.color || (Array.isArray(undyed) ? Math.floor(undyed[0] * 255) << 16 | Math.floor(undyed[1] * 255) << 8 | Math.floor(undyed[2] * 255) : undyed === void 0 ? void 0 : undyed & 16777215);
82633
+ if (color3 === void 0) continue;
82634
+ }
82635
+ const texture = this.identifier(layer.texture);
82636
+ add(
82637
+ new AssetKey(texture.namespace, `equipment/${layerType}/${texture.path}`, "textures", "entity", "assets", ".png"),
82638
+ { ...color3 !== void 0 && { color: color3 }, ...glint && { glint: true } }
82639
+ );
82640
+ glint = false;
82641
+ }
82642
+ if (piece.trim) {
82643
+ const patternId = this.identifier(piece.trim.pattern), materialId = this.identifier(piece.trim.material);
82644
+ const patternKey = new AssetKey(patternId.namespace, patternId.path, "trim_pattern", void 0, "data", ".json");
82645
+ const materialKey = new AssetKey(materialId.namespace, materialId.path, "trim_material", void 0, "data", ".json");
82646
+ const pattern2 = await Caching.trimCache.get(patternKey.serialize(), () => AssetLoader.get(patternKey, "json" /* JSON */));
82647
+ if (!pattern2) throw new MineRenderError(`Missing trim pattern ${piece.trim.pattern}`);
82648
+ const material = await Caching.trimCache.get(materialKey.serialize(), () => AssetLoader.get(materialKey, "json" /* JSON */));
82649
+ if (!material) throw new MineRenderError(`Missing trim material ${piece.trim.material}`);
82650
+ const patternAsset = this.identifier(pattern2.asset_id);
82651
+ const suffix = material.override_armor_assets?.[id.toNamespacedString()] ?? material.asset_name;
82652
+ add(new AssetKey(patternAsset.namespace, `entity/${layerType}/${patternAsset.path}`, "textures", "trims", "assets", ".png"), {
82653
+ palette: {
82654
+ key: new AssetKey("minecraft", "color_palettes/trim_palette", "textures", "trims", "assets", ".png"),
82655
+ permutation: new AssetKey("minecraft", `color_palettes/${suffix}`, "textures", "trims", "assets", ".png")
82656
+ },
82657
+ render: pattern2.decal ? "cutout_z_offset" : "cutout"
82658
+ });
82659
+ }
82660
+ }
82661
+ const first = Object.values(layers)[0];
82662
+ return first ? { ...first, id: "minecraft:player", layers, transform: ARMOR_TRANSFORM } : void 0;
82663
+ }
82664
+ static identifier(value) {
82665
+ if (!isResourceLocation(value) || value.split(/[:/]/).some((part) => !part || part === "." || part === "..")) {
82666
+ throw new MineRenderError(`Invalid armor identifier ${value}`);
82667
+ }
82668
+ const [namespace, path] = value.includes(":") ? value.split(":") : ["minecraft", value];
82669
+ return new BasicAssetKey(namespace, path);
82670
+ }
82671
+ };
82672
+ }
82673
+ });
82674
+
82363
82675
  // src/assets/MineRenderData.ts
82364
- var object2, release2, compare2, MineRenderData;
82676
+ var object2, MineRenderData;
82365
82677
  var init_MineRenderData = __esm({
82366
82678
  "src/assets/MineRenderData.ts"() {
82367
82679
  init_dirname();
82368
82680
  init_buffer2();
82369
82681
  init_process2();
82682
+ init_DatasetVersions();
82370
82683
  init_AssetKey();
82371
82684
  init_AssetLoader();
82372
82685
  init_AssetParsers();
82373
82686
  init_Caching();
82374
82687
  object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
82375
- release2 = (value) => /^\d+\.\d+(?:\.\d+)?$/.test(value) ? value.split(".").map(Number) : void 0;
82376
- compare2 = (left, right) => {
82377
- for (let i4 = 0; i4 < 3; i4++) {
82378
- const difference = (left[i4] ?? 0) - (right[i4] ?? 0);
82379
- if (difference) return difference;
82380
- }
82381
- return 0;
82382
- };
82383
82688
  MineRenderData = class {
82384
82689
  /** Loads one registry. Missing files and invalid data reject the request. */
82385
82690
  static async get(dataset, root) {
@@ -82409,9 +82714,9 @@ ${key}` : key;
82409
82714
  const scope = AssetLoader.persistentScope;
82410
82715
  return this.cached(`resolve:${requestRoot === void 0 ? "sources" : "explicit"}:${root}`, scope, defaultRoot, async () => {
82411
82716
  const requestedVersion = root.slice(root.lastIndexOf("/") + 1);
82412
- let manifest = await this.manifest(root, requestRoot !== void 0 && release2(requestedVersion) ? requestedVersion : void 0, requestRoot);
82717
+ let manifest = await this.manifest(root, requestRoot !== void 0 && parseRelease(requestedVersion) ? requestedVersion : void 0, requestRoot);
82413
82718
  if (manifest) return { requestedVersion, version: manifest.minecraftVersion, root, manifest };
82414
- const requested = release2(requestedVersion);
82719
+ const requested = parseRelease(requestedVersion);
82415
82720
  if (!requested) {
82416
82721
  throw new Error(`No MineRender data is published for ${requestedVersion}; automatic fallback requires a release`);
82417
82722
  }
@@ -82423,14 +82728,12 @@ ${key}` : key;
82423
82728
  }
82424
82729
  return value.versions;
82425
82730
  });
82426
- const versions2 = index.map((entry) => ({ name: entry.name, number: release2(entry.name) })).filter((entry) => !!entry.number).sort((left, right) => compare2(left.number, right.number));
82427
- const sameLine = versions2.filter((entry) => entry.number[0] === requested[0] && entry.number[1] === requested[1]);
82428
- const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0)) - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare2(left.number, right.number))[0] ?? versions2.filter((entry) => compare2(entry.number, requested) <= 0).pop() ?? versions2[0];
82731
+ const selected = nearestRelease(requestedVersion, index.map((entry) => entry.name));
82429
82732
  if (!selected) throw new Error(`No compatible MineRender data is published for ${requestedVersion}`);
82430
- const resolvedRoot = `${base}/${selected.name}`;
82431
- manifest = await this.manifest(resolvedRoot, selected.name, resolvedRoot);
82432
- if (!manifest) throw new Error(`Missing MineRender manifest for published version ${selected.name}`);
82433
- return { requestedVersion, version: selected.name, root: resolvedRoot, manifest };
82733
+ const resolvedRoot = `${base}/${selected}`;
82734
+ manifest = await this.manifest(resolvedRoot, selected, resolvedRoot);
82735
+ if (!manifest) throw new Error(`Missing MineRender manifest for published version ${selected}`);
82736
+ return { requestedVersion, version: selected, root: resolvedRoot, manifest };
82434
82737
  });
82435
82738
  }
82436
82739
  static async manifest(root, expectedVersion, requestRoot) {
@@ -82783,25 +83086,6 @@ ${key}` : key, async () => {
82783
83086
  }
82784
83087
  });
82785
83088
 
82786
- // src/error/MineRenderError.ts
82787
- var MineRenderError;
82788
- var init_MineRenderError = __esm({
82789
- "src/error/MineRenderError.ts"() {
82790
- init_dirname();
82791
- init_buffer2();
82792
- init_process2();
82793
- MineRenderError = class _MineRenderError extends Error {
82794
- constructor(msg) {
82795
- super(msg);
82796
- Object.setPrototypeOf(this, _MineRenderError.prototype);
82797
- }
82798
- get name() {
82799
- return "MineRenderError";
82800
- }
82801
- };
82802
- }
82803
- });
82804
-
82805
83089
  // src/texture/Colormaps.ts
82806
83090
  var Colormaps;
82807
83091
  var init_Colormaps = __esm({
@@ -83593,7 +83877,7 @@ ${key}` : key, async () => {
83593
83877
  });
83594
83878
 
83595
83879
  // src/assets/BlockEntities.ts
83596
- var log12, BlockEntities;
83880
+ var log13, BlockEntities;
83597
83881
  var init_BlockEntities = __esm({
83598
83882
  "src/assets/BlockEntities.ts"() {
83599
83883
  init_dirname();
@@ -83601,11 +83885,12 @@ ${key}` : key, async () => {
83601
83885
  init_process2();
83602
83886
  init_three_module();
83603
83887
  init_AssetKey();
83888
+ init_Entities();
83604
83889
  init_AssetLoader();
83605
83890
  init_source();
83606
83891
  init_Caching();
83607
83892
  init_log();
83608
- log12 = logger("BlockEntities");
83893
+ log13 = logger("BlockEntities");
83609
83894
  BlockEntities = class {
83610
83895
  /**
83611
83896
  * Loads the block index of a version. Versions and sources without one yield an empty index, and so does
@@ -83617,9 +83902,10 @@ ${key}` : key, async () => {
83617
83902
  key.rootType = void 0;
83618
83903
  const index = await Caching.blockEntityIndexCache.get(key.serialize(), async () => {
83619
83904
  try {
83905
+ key.root = await Entities.getDatasetRoot(root);
83620
83906
  return await AssetLoader.get(key, "json" /* JSON */) ?? {};
83621
83907
  } catch (error2) {
83622
- log12.warn("Could not load the block entity index; block entities are drawn as plain block models", error2);
83908
+ log13.warn("Could not load the block entity index; block entities are drawn as plain block models", error2);
83623
83909
  return {};
83624
83910
  }
83625
83911
  });
@@ -83705,139 +83991,6 @@ ${key}` : key, async () => {
83705
83991
  }
83706
83992
  });
83707
83993
 
83708
- // src/assets/Entities.ts
83709
- var Entities;
83710
- var init_Entities = __esm({
83711
- "src/assets/Entities.ts"() {
83712
- init_dirname();
83713
- init_buffer2();
83714
- init_process2();
83715
- init_AssetKey();
83716
- init_AssetLoader();
83717
- init_source();
83718
- init_Caching();
83719
- init_AssetDefaults();
83720
- init_MineRenderError();
83721
- init_ModelTextures();
83722
- Entities = class {
83723
- /** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */
83724
- static async getEntityList() {
83725
- const collect = async (path) => {
83726
- const prefix2 = path ? `${path}/` : "";
83727
- const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json");
83728
- const list2 = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
83729
- if (!list2) return [];
83730
- const files = list2.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
83731
- const children = await Promise.all(list2.directories.map((directory) => collect(`${prefix2}${directory}`)));
83732
- return [...files, ...children.flat()];
83733
- };
83734
- return collect("");
83735
- }
83736
- static async getModelFile(modelKey) {
83737
- const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
83738
- const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
83739
- return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
83740
- }
83741
- /** Returns selectable geometry-layer names, or an empty list when the model is missing. */
83742
- static async getLayerList(modelKey) {
83743
- return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
83744
- }
83745
- /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
83746
- static async getPassList(modelKey) {
83747
- return (await this.getModelFile(modelKey))?.passes ?? [];
83748
- }
83749
- /**
83750
- * Loads the layers and textures to pass to {@link MineRenderScene.addEntity}.
83751
- * By default, selects `main`, unconditional passes, and passes enabled by `options.when`.
83752
- *
83753
- * @param modelKey - Dataset model, such as `new BasicAssetKey("minecraft", "zombie")`.
83754
- * @param textureKey - Texture override for the first selected layer.
83755
- * @param options - Layer selection, conditional passes, and per-layer texture overrides.
83756
- * @returns The selected model, or `undefined` when its dataset file is missing.
83757
- */
83758
- static async getEntity(modelKey, textureKey, options) {
83759
- const model = await this.getModelFile(modelKey);
83760
- if (!model) return void 0;
83761
- const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
83762
- const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
83763
- if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
83764
- draws.push(...passes);
83765
- const names = [];
83766
- const selected = draws.map((pass) => {
83767
- const layer = model.layers[pass.layer];
83768
- if (!layer) {
83769
- throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
83770
- }
83771
- let name2 = pass.layer;
83772
- for (let n4 = 2; names.includes(name2); n4++) name2 = `${pass.layer}#${n4}`;
83773
- names.push(name2);
83774
- return { name: name2, layer, pass };
83775
- });
83776
- const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name: name2, layer, pass }, index) => {
83777
- const override = options?.textures?.[name2] ?? (index === 0 ? textureKey : void 0);
83778
- const textureLocation = pass.textureLocation ?? layer.textureLocation;
83779
- let texture;
83780
- if (override) {
83781
- const path = isAssetKey(override) ? override.getFullPath() : override.path;
83782
- 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);
83783
- } else if (textureLocation !== void 0) {
83784
- texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
83785
- if (isAssetKey(modelKey)) texture.root = modelKey.root;
83786
- } else {
83787
- texture = await this.resolveTexture(modelKey);
83788
- }
83789
- const render = pass.render ?? layer.render;
83790
- return [name2, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
83791
- })));
83792
- return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
83793
- }
83794
- /**
83795
- * Native and sampled vanilla clips by name, or undefined when the model or selected version has none.
83796
- */
83797
- static async getAnimations(modelKey) {
83798
- const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
83799
- const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
83800
- const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
83801
- return file?.animations;
83802
- }
83803
- /** Finds a fallback texture using the model path, its directory, and vanilla variant data. */
83804
- static async resolveTexture(modelKey) {
83805
- const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
83806
- const root = isAssetKey(modelKey) ? modelKey.root : void 0;
83807
- const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", root);
83808
- return Caching.entityTextureCache.get(key.serialize(), async () => {
83809
- const name2 = path.split("/").pop();
83810
- for (const candidate of [path, `${path}/${name2}`]) {
83811
- const texture2 = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png", root);
83812
- if (await ModelTextures.get(texture2)) return texture2;
83813
- }
83814
- const listKey = new AssetKey(modelKey.namespace, "_list", `${name2}_variant`, void 0, "data", ".json", root);
83815
- const list2 = await AssetLoader.get(listKey, "list" /* LIST */);
83816
- const files = list2?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
83817
- const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
83818
- if (!file) return void 0;
83819
- const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name2}_variant`, void 0, "data", ".json", root);
83820
- const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
83821
- const assets = variant?.assets;
83822
- const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
83823
- if (typeof textureId !== "string") return void 0;
83824
- const texture = AssetKey.parse("textures", textureId);
83825
- texture.root = root;
83826
- return texture;
83827
- });
83828
- }
83829
- /** @deprecated Use getEntityList(); block entities share the entity dataset. */
83830
- static getBlockList() {
83831
- return this.getEntityList();
83832
- }
83833
- /** @deprecated Use getEntity(); block entities share the entity dataset. */
83834
- static getBlock(modelKey, textureKey, options) {
83835
- return this.getEntity(modelKey, textureKey, options);
83836
- }
83837
- };
83838
- }
83839
- });
83840
-
83841
83994
  // src/assets/_fonts/Unihex.ts
83842
83995
  var Unihex_exports = {};
83843
83996
  __export(Unihex_exports, {
@@ -83896,7 +84049,7 @@ ${key}` : key, async () => {
83896
84049
  }
83897
84050
  return { indices, rows, metrics };
83898
84051
  } catch (error2) {
83899
- log13.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error2);
84052
+ log14.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error2);
83900
84053
  return void 0;
83901
84054
  }
83902
84055
  }
@@ -83915,7 +84068,7 @@ ${key}` : key, async () => {
83915
84068
  return { ...override, from, to };
83916
84069
  });
83917
84070
  } catch (error2) {
83918
- log13.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error2);
84071
+ log14.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error2);
83919
84072
  return glyphs;
83920
84073
  }
83921
84074
  const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
@@ -83963,7 +84116,7 @@ ${key}` : key, async () => {
83963
84116
  }
83964
84117
  return glyphs;
83965
84118
  }
83966
- var log13, ATLAS_SIZE, GLYPH_HEIGHT, UnihexAtlas, atlases;
84119
+ var log14, ATLAS_SIZE, GLYPH_HEIGHT, UnihexAtlas, atlases;
83967
84120
  var init_Unihex = __esm({
83968
84121
  "src/assets/_fonts/Unihex.ts"() {
83969
84122
  init_dirname();
@@ -83977,7 +84130,7 @@ ${key}` : key, async () => {
83977
84130
  init_AssetParsers();
83978
84131
  init_CanvasCompat();
83979
84132
  init_log();
83980
- log13 = logger("Unihex");
84133
+ log14 = logger("Unihex");
83981
84134
  ATLAS_SIZE = 512;
83982
84135
  GLYPH_HEIGHT = 16;
83983
84136
  UnihexAtlas = class {
@@ -85000,6 +85153,272 @@ ${key}` : key, async () => {
85000
85153
  }
85001
85154
  });
85002
85155
 
85156
+ // src/model/ItemGlint.ts
85157
+ var ItemGlint_exports = {};
85158
+ __export(ItemGlint_exports, {
85159
+ ItemGlint: () => ItemGlint
85160
+ });
85161
+ var ItemGlint;
85162
+ var init_ItemGlint = __esm({
85163
+ "src/model/ItemGlint.ts"() {
85164
+ init_dirname();
85165
+ init_buffer2();
85166
+ init_process2();
85167
+ init_three_module();
85168
+ init_AssetKey();
85169
+ init_Models();
85170
+ init_ModelTextures();
85171
+ init_Caching();
85172
+ init_Textures();
85173
+ init_Ticker();
85174
+ init_CubeFace();
85175
+ init_DisplayPosition();
85176
+ ItemGlint = class _ItemGlint {
85177
+ constructor(owner, material) {
85178
+ this.owner = owner;
85179
+ this.material = material;
85180
+ this.updateTime();
85181
+ }
85182
+ /** Enables glint for enchantments or a lodestone compass unless a boolean component overrides them. */
85183
+ static enabled(components = {}, itemId) {
85184
+ const override = Models.componentValue(components, "enchantment_glint_override");
85185
+ if (override !== void 0) {
85186
+ if (typeof override !== "boolean") throw new Error("Item enchantment_glint_override must be a boolean");
85187
+ return override;
85188
+ }
85189
+ if (itemId === "minecraft:compass") {
85190
+ Models.componentValue(components, "lodestone_tracker");
85191
+ if (Object.prototype.hasOwnProperty.call(components, "lodestone_tracker") || Object.prototype.hasOwnProperty.call(components, "minecraft:lodestone_tracker")) return true;
85192
+ }
85193
+ const enchantments = Models.componentValue(components, "enchantments");
85194
+ if (enchantments === void 0) return false;
85195
+ if (!enchantments || typeof enchantments !== "object" || Array.isArray(enchantments)) throw new Error("Item enchantments must be an object");
85196
+ return Object.keys(enchantments).length > 0;
85197
+ }
85198
+ /** @internal */
85199
+ static async create(owner, baseMap, root, entityMeshes, kind = "item") {
85200
+ const key = new AssetKey("minecraft", `enchanted_glint_${kind}`, "textures", "misc", "assets", ".png", root);
85201
+ const assetKey = key.serialize(), textureKey = `item-glint:${assetKey}`;
85202
+ let texture = Caching.textureCache.getIfPresent(textureKey);
85203
+ if (!texture) {
85204
+ const pending = ModelTextures.get(key);
85205
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKey);
85206
+ const [image, metadata] = await Promise.all([pending, ModelTextures.getMeta(key)]);
85207
+ if (!image) throw new Error(`Missing ${kind} glint texture ${key.toNamespacedString()}`);
85208
+ if (cachedAsset && Caching.textureAssetCache.getIfPresent(assetKey) !== cachedAsset) return this.create(owner, baseMap, root, entityMeshes, kind);
85209
+ texture = Caching.textureCache.get(textureKey, () => {
85210
+ const texture2 = Textures.createCanvasTexture(image.data.canvas);
85211
+ texture2.wrapS = texture2.wrapT = metadata?.texture?.clamp ? ClampToEdgeWrapping : RepeatWrapping;
85212
+ if (metadata?.texture?.blur) texture2.magFilter = texture2.minFilter = LinearFilter;
85213
+ return texture2;
85214
+ });
85215
+ }
85216
+ const material = new ShaderMaterial({
85217
+ name: "item-glint",
85218
+ transparent: true,
85219
+ depthWrite: false,
85220
+ depthFunc: EqualDepth,
85221
+ side: DoubleSide,
85222
+ forceSinglePass: true,
85223
+ blending: CustomBlending,
85224
+ blendSrc: SrcColorFactor,
85225
+ blendDst: OneFactor,
85226
+ blendSrcAlpha: ZeroFactor,
85227
+ blendDstAlpha: OneFactor,
85228
+ toneMapped: false,
85229
+ // TextureTransform.ARMOR_ENTITY_GLINT_TEXTURING uses a smaller UV scale than item glint.
85230
+ defines: entityMeshes ? { ENTITY_GLINT: true, ENTITY_GLINT_SCALE: kind === "armor" ? "0.16" : "0.5" } : {},
85231
+ uniforms: {
85232
+ ...!entityMeshes && { baseMap: { value: baseMap } },
85233
+ glintMap: { value: texture },
85234
+ glintOffset: { value: new Vector2() },
85235
+ glintAlpha: { value: 0.75 }
85236
+ },
85237
+ vertexShader: `
85238
+ uniform vec2 glintOffset;
85239
+ #ifndef ENTITY_GLINT
85240
+ attribute vec4 uvBounds;
85241
+ attribute vec2 glintUv;
85242
+ flat out vec4 vUvBounds;
85243
+ centroid out vec2 vUv;
85244
+ #endif
85245
+ varying vec2 vGlintUv;
85246
+ void main() {
85247
+ #ifdef ENTITY_GLINT
85248
+ vec2 p = vec2(uv.x, 1.0 - uv.y) * ENTITY_GLINT_SCALE;
85249
+ #else
85250
+ vUv = uv;
85251
+ vUvBounds = uvBounds;
85252
+ vec2 p = glintUv * 8.0;
85253
+ #endif
85254
+ float angle = radians(10.0);
85255
+ vGlintUv = vec2(cos(angle) * p.x - sin(angle) * p.y, sin(angle) * p.x + cos(angle) * p.y) + glintOffset;
85256
+ vec4 mvPosition = vec4(position, 1.0);
85257
+ mvPosition = modelViewMatrix * mvPosition;
85258
+ gl_Position = projectionMatrix * mvPosition;
85259
+ }
85260
+ `,
85261
+ fragmentShader: `
85262
+ #ifndef ENTITY_GLINT
85263
+ uniform sampler2D baseMap;
85264
+ flat in vec4 vUvBounds;
85265
+ centroid in vec2 vUv;
85266
+ #endif
85267
+ uniform sampler2D glintMap;
85268
+ uniform float glintAlpha;
85269
+ varying vec2 vGlintUv;
85270
+ void main() {
85271
+ #ifndef ENTITY_GLINT
85272
+ vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);
85273
+ if (texture2D(baseMap, mapUv).a < 0.01) discard;
85274
+ #endif
85275
+ vec4 color = texture2D(glintMap, vec2(vGlintUv.x, 1.0 - vGlintUv.y));
85276
+ if (color.a < 0.1) discard;
85277
+ gl_FragColor = color;
85278
+ #include <colorspace_fragment>
85279
+ gl_FragColor.rgb *= glintAlpha;
85280
+ }
85281
+ `
85282
+ });
85283
+ if (!entityMeshes) Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
85284
+ const targets = entityMeshes ? [...entityMeshes] : [];
85285
+ if (!entityMeshes) owner.iterateAllMeshes((mesh) => targets.push({ mesh }));
85286
+ for (const { mesh: base, parent = base } of targets) {
85287
+ const pass = new Mesh(base.geometry, material);
85288
+ pass.name = `${base.name}:glint`;
85289
+ pass.userData.minerenderItemGlint = true;
85290
+ pass.raycast = () => {
85291
+ };
85292
+ pass.renderOrder = parent.renderOrder + 0.5;
85293
+ parent.add(pass);
85294
+ }
85295
+ return new _ItemGlint(owner, material);
85296
+ }
85297
+ /**
85298
+ * Maps glint before model centering and display transforms. Ordinary sprites approximate Minecraft's shared atlas density.
85299
+ * @internal
85300
+ */
85301
+ static mapUvs(geometry, faces, atlas, itemId, display) {
85302
+ const uv = geometry.getAttribute("uv");
85303
+ const mapped = new Float32Array(uv.count * 2);
85304
+ if (itemId === "minecraft:compass" || itemId === "minecraft:recovery_compass" || itemId === "minecraft:clock") {
85305
+ const positions = geometry.getAttribute("position"), normals = geometry.getAttribute("normal");
85306
+ const scale = display === "gui" /* GUI */ ? 0.5 : display === "firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */ || display === "firstperson_righthand" /* FIRSTPERSON_RIGHTHAND */ ? 0.75 : 1;
85307
+ const factor = 1 / (16 * 128 * scale);
85308
+ for (let index = 0; index < positions.count; index++) {
85309
+ const x4 = positions.getX(index), y5 = positions.getY(index), z4 = positions.getZ(index);
85310
+ const nx = normals.getX(index), ny = normals.getY(index), nz = normals.getZ(index);
85311
+ const ax = Math.abs(nx), ay = Math.abs(ny), az = Math.abs(nz);
85312
+ let u4, v5;
85313
+ if (ay >= az && ay >= ax) {
85314
+ u4 = x4;
85315
+ v5 = ny < 0 ? -z4 : z4;
85316
+ } else if (az >= ax) {
85317
+ u4 = nz < 0 ? -x4 : x4;
85318
+ v5 = -y5;
85319
+ } else {
85320
+ u4 = nx < 0 ? -z4 : z4;
85321
+ v5 = -y5;
85322
+ }
85323
+ mapped[index * 2] = u4 * factor;
85324
+ mapped[index * 2 + 1] = v5 * factor;
85325
+ }
85326
+ geometry.setAttribute("glintUv", new Float32BufferAttribute(mapped, 2));
85327
+ return;
85328
+ }
85329
+ for (const [faceIndex, face] of CUBE_FACES.entries()) {
85330
+ const texture = faces[face]?.texture?.substring(1);
85331
+ const position = texture && atlas.positions[texture] || [0, 0];
85332
+ const size = texture && atlas.sizes[texture] || [atlas.image.width, atlas.image.height];
85333
+ for (let corner = 0; corner < 4; corner++) {
85334
+ const index = faceIndex * 4 + corner;
85335
+ mapped[index * 2] = (uv.getX(index) * atlas.image.width - position[0]) / size[0] / 32;
85336
+ mapped[index * 2 + 1] = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] / 32;
85337
+ }
85338
+ }
85339
+ geometry.setAttribute("glintUv", new Float32BufferAttribute(mapped, 2));
85340
+ }
85341
+ updateTime() {
85342
+ const time = Math.trunc(Date.now() * 4);
85343
+ this.material.uniforms.glintOffset.value.set(-(time % 11e4) / 11e4, time % 3e4 / 3e4);
85344
+ }
85345
+ /** @internal */
85346
+ updateSubscription(active) {
85347
+ if (active && this.ticker === void 0) {
85348
+ this.updateTime();
85349
+ this.ticker = Ticker.add(() => {
85350
+ this.updateTime();
85351
+ this.owner.notifyDirty();
85352
+ });
85353
+ } else if (!active) {
85354
+ Ticker.remove(this.ticker);
85355
+ this.ticker = void 0;
85356
+ }
85357
+ }
85358
+ dispose() {
85359
+ Ticker.remove(this.ticker);
85360
+ this.ticker = void 0;
85361
+ this.material.dispose();
85362
+ }
85363
+ };
85364
+ }
85365
+ });
85366
+
85367
+ // src/texture/PalettedTextures.ts
85368
+ var PalettedTextures_exports = {};
85369
+ __export(PalettedTextures_exports, {
85370
+ PalettedTextures: () => PalettedTextures
85371
+ });
85372
+ var PalettedTextures;
85373
+ var init_PalettedTextures = __esm({
85374
+ "src/texture/PalettedTextures.ts"() {
85375
+ init_dirname();
85376
+ init_buffer2();
85377
+ init_process2();
85378
+ init_ModelTextures();
85379
+ init_Caching();
85380
+ init_CanvasImage();
85381
+ init_MineRenderError();
85382
+ PalettedTextures = class {
85383
+ /** Loads a texture with a palette permutation, sharing the resulting canvas between callers. */
85384
+ static async get(texture, key, permutation2) {
85385
+ return Caching.canvasImageDataCache.get(`palette:${texture.serialize()}:${key.serialize()}:${permutation2.serialize()}`, async () => {
85386
+ const source = await ModelTextures.get(texture);
85387
+ if (!source) return void 0;
85388
+ const [palette, replacement] = await Promise.all([ModelTextures.get(key), ModelTextures.get(permutation2)]);
85389
+ if (!palette) throw new MineRenderError(`Missing palette ${key.toNamespacedString()}`);
85390
+ if (!replacement) throw new MineRenderError(`Missing palette ${permutation2.toNamespacedString()}`);
85391
+ const pixels = source.data.getImageData(0, 0, source.width, source.height);
85392
+ const colors2 = palette.data.getImageData(0, 0, palette.width, palette.height).data;
85393
+ const replacements = replacement.data.getImageData(0, 0, replacement.width, replacement.height).data;
85394
+ const image = new CanvasImage(source.width, source.height);
85395
+ const output = image.context.createImageData(source.width, source.height);
85396
+ output.data.set(this.permute(pixels.data, colors2, replacements));
85397
+ image.putData(output);
85398
+ return { data: image.context, width: image.width, height: image.height };
85399
+ });
85400
+ }
85401
+ /** @internal */
85402
+ static permute(pixels, key, permutation2) {
85403
+ if (key.length !== permutation2.length) throw new MineRenderError("Palette images must have the same pixel count");
85404
+ const mapping = /* @__PURE__ */ new Map();
85405
+ for (let i4 = 0; i4 < key.length; i4 += 4) {
85406
+ if (key[i4 + 3] !== 0) mapping.set(key[i4] << 16 | key[i4 + 1] << 8 | key[i4 + 2], i4);
85407
+ }
85408
+ const output = new Uint8ClampedArray(pixels);
85409
+ for (let i4 = 0; i4 < pixels.length; i4 += 4) {
85410
+ if (pixels[i4 + 3] === 0) continue;
85411
+ const mapped = mapping.get(pixels[i4] << 16 | pixels[i4 + 1] << 8 | pixels[i4 + 2]);
85412
+ if (mapped === void 0) continue;
85413
+ output.set(permutation2.subarray(mapped, mapped + 3), i4);
85414
+ output[i4 + 3] = Math.floor(pixels[i4 + 3] * permutation2[mapped + 3] / 255);
85415
+ }
85416
+ return output;
85417
+ }
85418
+ };
85419
+ }
85420
+ });
85421
+
85003
85422
  // src/entity/scene/EntityObject.ts
85004
85423
  var EntityObject_exports = {};
85005
85424
  __export(EntityObject_exports, {
@@ -85009,7 +85428,7 @@ ${key}` : key, async () => {
85009
85428
  function isEntityObject(obj) {
85010
85429
  return obj.isEntityObject;
85011
85430
  }
85012
- var _EntityObject, EntityObject;
85431
+ var ItemGlintClass, PalettedTexturesClass, _EntityObject, EntityObject;
85013
85432
  var init_EntityObject = __esm({
85014
85433
  "src/entity/scene/EntityObject.ts"() {
85015
85434
  init_dirname();
@@ -85043,8 +85462,14 @@ ${key}` : key, async () => {
85043
85462
  this.animationPlayers = [];
85044
85463
  this.partPoses = /* @__PURE__ */ new Map();
85045
85464
  this.options = (0, import_ts_deepmerge.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
85046
- this.addEventListener("added", () => this.updateScrollSubscription());
85047
- this.addEventListener("removed", () => this.updateScrollSubscription());
85465
+ this.addEventListener("added", () => {
85466
+ this.updateScrollSubscription();
85467
+ this.glint?.updateSubscription(!!this.parent);
85468
+ });
85469
+ this.addEventListener("removed", () => {
85470
+ this.updateScrollSubscription();
85471
+ this.glint?.updateSubscription(!!this.parent);
85472
+ });
85048
85473
  }
85049
85474
  /** An optional shared material replaces texture loading for every selected draw; its owner retains disposal. */
85050
85475
  async init(material) {
@@ -85055,12 +85480,26 @@ ${key}` : key, async () => {
85055
85480
  mesh.material = material;
85056
85481
  });
85057
85482
  this.notifyDirty();
85058
- } else await this.applyTextures();
85483
+ } else {
85484
+ await this.applyTextures();
85485
+ const layers = Object.entries(this.entityLayers).filter(([, layer]) => layer.glint);
85486
+ const meshes = [];
85487
+ for (const [name2] of layers) this.getLayerGroup(name2)?.traverse((object4) => {
85488
+ if (isMesh(object4)) meshes.push(object4);
85489
+ });
85490
+ if (meshes.length) {
85491
+ const ItemGlint2 = ItemGlintClass ?? (ItemGlintClass = (await Promise.resolve().then(() => (init_ItemGlint(), ItemGlint_exports))).ItemGlint);
85492
+ this.glint = await ItemGlint2.create(this, void 0, this.getTextureKey(layers[0][1]).root, meshes.map((mesh) => ({ mesh })), "armor");
85493
+ this.glint.updateSubscription(!!this.parent);
85494
+ }
85495
+ }
85059
85496
  }
85060
85497
  dispose() {
85061
85498
  super.dispose();
85062
85499
  }
85063
85500
  disposeAndRemoveAllChildren() {
85501
+ this.glint?.dispose();
85502
+ this.glint = void 0;
85064
85503
  this.clearScrollMaterials();
85065
85504
  for (const geometry of this.geometries) geometry.dispose();
85066
85505
  this.geometries.clear();
@@ -85219,6 +85658,10 @@ ${key}` : key, async () => {
85219
85658
  );
85220
85659
  }
85221
85660
  async loadTextures(layer = this.entity) {
85661
+ if (layer.palette) {
85662
+ const PalettedTextures2 = PalettedTexturesClass ?? (PalettedTexturesClass = (await Promise.resolve().then(() => (init_PalettedTextures(), PalettedTextures_exports))).PalettedTextures);
85663
+ return PalettedTextures2.get(this.getTextureKey(layer), layer.palette.key, layer.palette.permutation);
85664
+ }
85222
85665
  return ModelTextures.get(this.getTextureKey(layer));
85223
85666
  }
85224
85667
  createMeshes(force = false) {
@@ -85291,10 +85734,10 @@ ${key}` : key, async () => {
85291
85734
  this.clearScrollMaterials();
85292
85735
  const results = await Promise.allSettled(Object.entries(this.entityLayers).map(async ([name2, layer]) => {
85293
85736
  const mode2 = layer.render ?? layer.layer.render ?? "cutout";
85294
- const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
85737
+ const tint = (layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint]) ?? layer.color;
85295
85738
  const scroll = Materials.entityModeScroll(mode2);
85296
85739
  const assetKeyStr = this.getTextureKey(layer).serialize();
85297
- const keyStr = `entity:${mode2}:${tint === void 0 ? "" : new Color(tint).getHexString()}:${assetKeyStr}`;
85740
+ const keyStr = `entity:${mode2}:${tint === void 0 ? "" : new Color(tint).getHexString()}:${assetKeyStr}` + (layer.palette ? `:${layer.palette.key.serialize()}:${layer.palette.permutation.serialize()}` : "");
85298
85741
  let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
85299
85742
  if (!mat) {
85300
85743
  const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
@@ -88206,7 +88649,7 @@ ${key}` : key, async () => {
88206
88649
  });
88207
88650
 
88208
88651
  // src/skin/Skins.ts
88209
- var log14, Skins;
88652
+ var log15, Skins;
88210
88653
  var init_Skins = __esm({
88211
88654
  "src/skin/Skins.ts"() {
88212
88655
  init_dirname();
@@ -88215,7 +88658,7 @@ ${key}` : key, async () => {
88215
88658
  init_Requests();
88216
88659
  init_Caching();
88217
88660
  init_log();
88218
- log14 = logger("Skins");
88661
+ log15 = logger("Skins");
88219
88662
  Skins = class {
88220
88663
  //<editor-fold desc="Skins">
88221
88664
  /** Returns a skin URL for {@link MineRenderScene.addSkin}, or `undefined` if name lookup fails. */
@@ -88287,7 +88730,7 @@ ${key}` : key, async () => {
88287
88730
  }
88288
88731
  return void 0;
88289
88732
  }).catch((err2) => {
88290
- log14.warn(err2);
88733
+ log15.warn(err2);
88291
88734
  return void 0;
88292
88735
  });
88293
88736
  }
@@ -88302,7 +88745,7 @@ ${key}` : key, async () => {
88302
88745
  }
88303
88746
  return void 0;
88304
88747
  }).catch((err2) => {
88305
- log14.warn(err2);
88748
+ log15.warn(err2);
88306
88749
  return void 0;
88307
88750
  });
88308
88751
  }
@@ -88316,7 +88759,7 @@ ${key}` : key, async () => {
88316
88759
  }
88317
88760
  return void 0;
88318
88761
  }).catch((err2) => {
88319
- log14.warn(err2);
88762
+ log15.warn(err2);
88320
88763
  return void 0;
88321
88764
  });
88322
88765
  }
@@ -88340,7 +88783,7 @@ ${key}` : key, async () => {
88340
88783
  }
88341
88784
  return void 0;
88342
88785
  }).catch((err2) => {
88343
- log14.warn(err2);
88786
+ log15.warn(err2);
88344
88787
  return void 0;
88345
88788
  });
88346
88789
  }
@@ -91276,7 +91719,7 @@ ${key}` : key, async () => {
91276
91719
  return pixels;
91277
91720
  }
91278
91721
  static makeBaseOpaque(pixels, width, scale) {
91279
- for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64]]) {
91722
+ for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64], [32, 0, 38, 7]]) {
91280
91723
  for (let y5 = y0 * scale; y5 < y1 * scale; y5++) {
91281
91724
  for (let x4 = x0 * scale; x4 < x1 * scale; x4++) pixels[(y5 * width + x4) * 4 + 3] = 255;
91282
91725
  }
@@ -91287,6 +91730,10 @@ ${key}` : key, async () => {
91287
91730
  });
91288
91731
 
91289
91732
  // src/skin/PlayerHeadTextures.ts
91733
+ var PlayerHeadTextures_exports = {};
91734
+ __export(PlayerHeadTextures_exports, {
91735
+ PlayerHeadTextures: () => PlayerHeadTextures
91736
+ });
91290
91737
  var PlayerHeadTextures;
91291
91738
  var init_PlayerHeadTextures = __esm({
91292
91739
  "src/skin/PlayerHeadTextures.ts"() {
@@ -91679,212 +92126,6 @@ ${shader.fragmentShader}`.replace(
91679
92126
  }
91680
92127
  });
91681
92128
 
91682
- // src/model/ItemGlint.ts
91683
- var ItemGlint;
91684
- var init_ItemGlint = __esm({
91685
- "src/model/ItemGlint.ts"() {
91686
- init_dirname();
91687
- init_buffer2();
91688
- init_process2();
91689
- init_three_module();
91690
- init_AssetKey();
91691
- init_Models();
91692
- init_ModelTextures();
91693
- init_Caching();
91694
- init_Textures();
91695
- init_Ticker();
91696
- init_CubeFace();
91697
- init_DisplayPosition();
91698
- ItemGlint = class _ItemGlint {
91699
- constructor(owner, material) {
91700
- this.owner = owner;
91701
- this.material = material;
91702
- this.updateTime();
91703
- }
91704
- /** Enables glint for enchantments or a lodestone compass unless a boolean component overrides them. */
91705
- static enabled(components = {}, itemId) {
91706
- const override = Models.componentValue(components, "enchantment_glint_override");
91707
- if (override !== void 0) {
91708
- if (typeof override !== "boolean") throw new Error("Item enchantment_glint_override must be a boolean");
91709
- return override;
91710
- }
91711
- if (itemId === "minecraft:compass") {
91712
- Models.componentValue(components, "lodestone_tracker");
91713
- if (Object.prototype.hasOwnProperty.call(components, "lodestone_tracker") || Object.prototype.hasOwnProperty.call(components, "minecraft:lodestone_tracker")) return true;
91714
- }
91715
- const enchantments = Models.componentValue(components, "enchantments");
91716
- if (enchantments === void 0) return false;
91717
- if (!enchantments || typeof enchantments !== "object" || Array.isArray(enchantments)) throw new Error("Item enchantments must be an object");
91718
- return Object.keys(enchantments).length > 0;
91719
- }
91720
- /** @internal */
91721
- static async create(owner, baseMap, root, entityMeshes) {
91722
- const key = new AssetKey("minecraft", "enchanted_glint_item", "textures", "misc", "assets", ".png", root);
91723
- const assetKey = key.serialize(), textureKey = `item-glint:${assetKey}`;
91724
- let texture = Caching.textureCache.getIfPresent(textureKey);
91725
- if (!texture) {
91726
- const pending = ModelTextures.get(key);
91727
- const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKey);
91728
- const [image, metadata] = await Promise.all([pending, ModelTextures.getMeta(key)]);
91729
- if (!image) throw new Error(`Missing item glint texture ${key.toNamespacedString()}`);
91730
- if (cachedAsset && Caching.textureAssetCache.getIfPresent(assetKey) !== cachedAsset) return this.create(owner, baseMap, root, entityMeshes);
91731
- texture = Caching.textureCache.get(textureKey, () => {
91732
- const texture2 = Textures.createCanvasTexture(image.data.canvas);
91733
- texture2.wrapS = texture2.wrapT = metadata?.texture?.clamp ? ClampToEdgeWrapping : RepeatWrapping;
91734
- if (metadata?.texture?.blur) texture2.magFilter = texture2.minFilter = LinearFilter;
91735
- return texture2;
91736
- });
91737
- }
91738
- const material = new ShaderMaterial({
91739
- name: "item-glint",
91740
- transparent: true,
91741
- depthWrite: false,
91742
- depthFunc: EqualDepth,
91743
- side: DoubleSide,
91744
- forceSinglePass: true,
91745
- blending: CustomBlending,
91746
- blendSrc: SrcColorFactor,
91747
- blendDst: OneFactor,
91748
- blendSrcAlpha: ZeroFactor,
91749
- blendDstAlpha: OneFactor,
91750
- toneMapped: false,
91751
- defines: entityMeshes ? { ENTITY_GLINT: true } : {},
91752
- uniforms: {
91753
- ...!entityMeshes && { baseMap: { value: baseMap } },
91754
- glintMap: { value: texture },
91755
- glintOffset: { value: new Vector2() },
91756
- glintAlpha: { value: 0.75 }
91757
- },
91758
- vertexShader: `
91759
- uniform vec2 glintOffset;
91760
- #ifndef ENTITY_GLINT
91761
- attribute vec4 uvBounds;
91762
- attribute vec2 glintUv;
91763
- flat out vec4 vUvBounds;
91764
- centroid out vec2 vUv;
91765
- #endif
91766
- varying vec2 vGlintUv;
91767
- void main() {
91768
- #ifdef ENTITY_GLINT
91769
- vec2 p = vec2(uv.x, 1.0 - uv.y) * 0.5;
91770
- #else
91771
- vUv = uv;
91772
- vUvBounds = uvBounds;
91773
- vec2 p = glintUv * 8.0;
91774
- #endif
91775
- float angle = radians(10.0);
91776
- vGlintUv = vec2(cos(angle) * p.x - sin(angle) * p.y, sin(angle) * p.x + cos(angle) * p.y) + glintOffset;
91777
- vec4 mvPosition = vec4(position, 1.0);
91778
- mvPosition = modelViewMatrix * mvPosition;
91779
- gl_Position = projectionMatrix * mvPosition;
91780
- }
91781
- `,
91782
- fragmentShader: `
91783
- #ifndef ENTITY_GLINT
91784
- uniform sampler2D baseMap;
91785
- flat in vec4 vUvBounds;
91786
- centroid in vec2 vUv;
91787
- #endif
91788
- uniform sampler2D glintMap;
91789
- uniform float glintAlpha;
91790
- varying vec2 vGlintUv;
91791
- void main() {
91792
- #ifndef ENTITY_GLINT
91793
- vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);
91794
- if (texture2D(baseMap, mapUv).a < 0.01) discard;
91795
- #endif
91796
- vec4 color = texture2D(glintMap, vec2(vGlintUv.x, 1.0 - vGlintUv.y));
91797
- if (color.a < 0.1) discard;
91798
- gl_FragColor = color;
91799
- #include <colorspace_fragment>
91800
- gl_FragColor.rgb *= glintAlpha;
91801
- }
91802
- `
91803
- });
91804
- if (!entityMeshes) Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
91805
- const targets = entityMeshes ? [...entityMeshes] : [];
91806
- if (!entityMeshes) owner.iterateAllMeshes((mesh) => targets.push({ mesh }));
91807
- for (const { mesh: base, parent = base } of targets) {
91808
- const pass = new Mesh(base.geometry, material);
91809
- pass.name = `${base.name}:glint`;
91810
- pass.userData.minerenderItemGlint = true;
91811
- pass.raycast = () => {
91812
- };
91813
- pass.renderOrder = parent.renderOrder + 0.5;
91814
- parent.add(pass);
91815
- }
91816
- return new _ItemGlint(owner, material);
91817
- }
91818
- /**
91819
- * Maps glint before model centering and display transforms. Ordinary sprites approximate Minecraft's shared atlas density.
91820
- * @internal
91821
- */
91822
- static mapUvs(geometry, faces, atlas, itemId, display) {
91823
- const uv = geometry.getAttribute("uv");
91824
- const mapped = new Float32Array(uv.count * 2);
91825
- if (itemId === "minecraft:compass" || itemId === "minecraft:recovery_compass" || itemId === "minecraft:clock") {
91826
- const positions = geometry.getAttribute("position"), normals = geometry.getAttribute("normal");
91827
- const scale = display === "gui" /* GUI */ ? 0.5 : display === "firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */ || display === "firstperson_righthand" /* FIRSTPERSON_RIGHTHAND */ ? 0.75 : 1;
91828
- const factor = 1 / (16 * 128 * scale);
91829
- for (let index = 0; index < positions.count; index++) {
91830
- const x4 = positions.getX(index), y5 = positions.getY(index), z4 = positions.getZ(index);
91831
- const nx = normals.getX(index), ny = normals.getY(index), nz = normals.getZ(index);
91832
- const ax = Math.abs(nx), ay = Math.abs(ny), az = Math.abs(nz);
91833
- let u4, v5;
91834
- if (ay >= az && ay >= ax) {
91835
- u4 = x4;
91836
- v5 = ny < 0 ? -z4 : z4;
91837
- } else if (az >= ax) {
91838
- u4 = nz < 0 ? -x4 : x4;
91839
- v5 = -y5;
91840
- } else {
91841
- u4 = nx < 0 ? -z4 : z4;
91842
- v5 = -y5;
91843
- }
91844
- mapped[index * 2] = u4 * factor;
91845
- mapped[index * 2 + 1] = v5 * factor;
91846
- }
91847
- geometry.setAttribute("glintUv", new Float32BufferAttribute(mapped, 2));
91848
- return;
91849
- }
91850
- for (const [faceIndex, face] of CUBE_FACES.entries()) {
91851
- const texture = faces[face]?.texture?.substring(1);
91852
- const position = texture && atlas.positions[texture] || [0, 0];
91853
- const size = texture && atlas.sizes[texture] || [atlas.image.width, atlas.image.height];
91854
- for (let corner = 0; corner < 4; corner++) {
91855
- const index = faceIndex * 4 + corner;
91856
- mapped[index * 2] = (uv.getX(index) * atlas.image.width - position[0]) / size[0] / 32;
91857
- mapped[index * 2 + 1] = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] / 32;
91858
- }
91859
- }
91860
- geometry.setAttribute("glintUv", new Float32BufferAttribute(mapped, 2));
91861
- }
91862
- updateTime() {
91863
- const time = Math.trunc(Date.now() * 4);
91864
- this.material.uniforms.glintOffset.value.set(-(time % 11e4) / 11e4, time % 3e4 / 3e4);
91865
- }
91866
- /** @internal */
91867
- updateSubscription(active) {
91868
- if (active && this.ticker === void 0) {
91869
- this.updateTime();
91870
- this.ticker = Ticker.add(() => {
91871
- this.updateTime();
91872
- this.owner.notifyDirty();
91873
- });
91874
- } else if (!active) {
91875
- Ticker.remove(this.ticker);
91876
- this.ticker = void 0;
91877
- }
91878
- }
91879
- dispose() {
91880
- Ticker.remove(this.ticker);
91881
- this.ticker = void 0;
91882
- this.material.dispose();
91883
- }
91884
- };
91885
- }
91886
- });
91887
-
91888
92129
  // src/model/scene/ModelObject.ts
91889
92130
  var ModelObject_exports = {};
91890
92131
  __export(ModelObject_exports, {
@@ -91894,7 +92135,7 @@ ${shader.fragmentShader}`.replace(
91894
92135
  function isModelObject(obj) {
91895
92136
  return obj.isModelObject;
91896
92137
  }
91897
- var log15, _ModelObject, ModelObject;
92138
+ var log16, _ModelObject, ModelObject;
91898
92139
  var init_ModelObject = __esm({
91899
92140
  "src/model/scene/ModelObject.ts"() {
91900
92141
  init_dirname();
@@ -91917,7 +92158,7 @@ ${shader.fragmentShader}`.replace(
91917
92158
  init_GuiLight();
91918
92159
  init_ItemTints();
91919
92160
  init_ItemGlint();
91920
- log15 = logger("ModelObject");
92161
+ log16 = logger("ModelObject");
91921
92162
  _ModelObject = class _ModelObject extends SceneObject {
91922
92163
  constructor(originalModel, options) {
91923
92164
  super(options);
@@ -92099,10 +92340,10 @@ ${shader.fragmentShader}`.replace(
92099
92340
  }
92100
92341
  });
92101
92342
  } else {
92102
- log15.debug(this.atlas.model, "has no elements");
92343
+ log16.debug(this.atlas.model, "has no elements");
92103
92344
  }
92104
92345
  } else {
92105
- log15.debug("Missing atlas for", this);
92346
+ log16.debug("Missing atlas for", this);
92106
92347
  }
92107
92348
  if (this.options.mergeMeshes) {
92108
92349
  let combinedGeo;
@@ -92932,7 +93173,7 @@ ${shader.fragmentShader}`.replace(
92932
93173
  function isBlockObject(obj) {
92933
93174
  return obj.isBlockObject;
92934
93175
  }
92935
- var log18, _BlockObject, BlockObject;
93176
+ var log19, _BlockObject, BlockObject;
92936
93177
  var init_BlockObject = __esm({
92937
93178
  "src/model/block/scene/BlockObject.ts"() {
92938
93179
  init_dirname();
@@ -92955,7 +93196,7 @@ ${shader.fragmentShader}`.replace(
92955
93196
  init_Entities();
92956
93197
  init_Biomes();
92957
93198
  init_log();
92958
- log18 = logger("BlockObject");
93199
+ log19 = logger("BlockObject");
92959
93200
  _BlockObject = class _BlockObject extends SceneObject {
92960
93201
  constructor(blockState3, options) {
92961
93202
  super(options);
@@ -93047,20 +93288,28 @@ ${shader.fragmentShader}`.replace(
93047
93288
  if (!key || this.options.displayPosition) return false;
93048
93289
  const generation = this._entityGeneration;
93049
93290
  const created = [];
93291
+ const placement = new Matrix4();
93050
93292
  let resolved;
93051
93293
  try {
93052
93294
  resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);
93053
93295
  if (!resolved) return false;
93296
+ BlockEntities.matrix(resolved, placement);
93054
93297
  for (const part of resolved.parts) {
93055
93298
  const [namespace, path] = part.model.includes(":") ? part.model.split(":") : [key.namespace, part.model];
93056
- const texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
93299
+ let texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
93300
+ if (part.textureLocation === void 0 && namespace === "minecraft" && path === "player_head") {
93301
+ const { PlayerHeadTextures: PlayerHeadTextures2 } = await Promise.resolve().then(() => (init_PlayerHeadTextures(), PlayerHeadTextures_exports));
93302
+ texture = (await PlayerHeadTextures2.get(void 0, key.root)).texture;
93303
+ }
93057
93304
  if (texture) texture.root = key.root;
93058
93305
  const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });
93059
93306
  if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);
93060
- created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }));
93307
+ const object4 = await this.scene.addEntity(entity, { wireframe: this.options.wireframe });
93308
+ this.placeEntity(object4, placement);
93309
+ created.push(object4);
93061
93310
  }
93062
93311
  } catch (error2) {
93063
- log18.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error2);
93312
+ log19.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error2);
93064
93313
  this.removeEntities(created);
93065
93314
  return false;
93066
93315
  }
@@ -93068,18 +93317,21 @@ ${shader.fragmentShader}`.replace(
93068
93317
  this.removeEntities(created);
93069
93318
  return true;
93070
93319
  }
93071
- BlockEntities.matrix(resolved, this._entityPlacement);
93320
+ this._entityPlacement.copy(placement);
93072
93321
  this._entities = created;
93073
93322
  this.placeEntities();
93074
93323
  this.setVisible(this.visible);
93075
93324
  return true;
93076
93325
  }
93077
93326
  placeEntities() {
93078
- const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
93079
93327
  for (const entity of this._entities) {
93080
- matrix.decompose(entity.position, entity.quaternion, entity.scale);
93328
+ this.placeEntity(entity, this._entityPlacement);
93081
93329
  }
93082
93330
  }
93331
+ placeEntity(entity, placement) {
93332
+ const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(placement);
93333
+ matrix.decompose(entity.position, entity.quaternion, entity.scale);
93334
+ }
93083
93335
  get isOccluding() {
93084
93336
  if (!this.visible) {
93085
93337
  return false;
@@ -94214,6 +94466,7 @@ ${shader.fragmentShader}`.replace(
94214
94466
  AnvilParser: () => AnvilParser,
94215
94467
  AnvilWorldSource: () => AnvilWorldSource,
94216
94468
  ArchiveAssetSource: () => ArchiveAssetSource,
94469
+ Armor: () => Armor,
94217
94470
  AssetKey: () => AssetKey,
94218
94471
  AssetLoadError: () => AssetLoadError,
94219
94472
  AssetLoader: () => AssetLoader,
@@ -94296,6 +94549,7 @@ ${shader.fragmentShader}`.replace(
94296
94549
  OrbitControls: () => OrbitControls,
94297
94550
  PackFormats: () => PackFormats,
94298
94551
  PackMetadata: () => PackMetadata,
94552
+ PalettedTextures: () => PalettedTextures,
94299
94553
  PersistentCache: () => PersistentCache,
94300
94554
  PlayerHeadTextures: () => PlayerHeadTextures,
94301
94555
  Renames: () => Renames,
@@ -94440,6 +94694,7 @@ ${shader.fragmentShader}`.replace(
94440
94694
  init_buffer2();
94441
94695
  init_process2();
94442
94696
  init_Env();
94697
+ init_log();
94443
94698
 
94444
94699
  // src/env/browser/BrowserCache.ts
94445
94700
  init_dirname();
@@ -94546,6 +94801,7 @@ ${shader.fragmentShader}`.replace(
94546
94801
 
94547
94802
  // src/env/browser/BrowserEnv.ts
94548
94803
  var import_meta = {};
94804
+ var log2 = logger("BrowserEnv");
94549
94805
  function lazyLocalForage(options) {
94550
94806
  let instance;
94551
94807
  const store = () => instance ?? (instance = Promise.resolve().then(() => __toESM(require_localforage())).then((module2) => module2.default.createInstance(options)));
@@ -94561,7 +94817,8 @@ ${shader.fragmentShader}`.replace(
94561
94817
  };
94562
94818
  }
94563
94819
  var BrowserEnv = class {
94564
- constructor() {
94820
+ constructor(options = {}) {
94821
+ this.options = options;
94565
94822
  this.name = "browser";
94566
94823
  }
94567
94824
  createCanvas(width, height) {
@@ -94590,14 +94847,18 @@ ${shader.fragmentShader}`.replace(
94590
94847
  createWorker(name2) {
94591
94848
  if (name2 !== "section" || typeof Worker === "undefined") return void 0;
94592
94849
  try {
94850
+ const sectionWorker = this.options.sectionWorker;
94851
+ if (typeof sectionWorker === "function") return sectionWorker();
94852
+ if (sectionWorker !== void 0) return new Worker(sectionWorker, { type: "module" });
94593
94853
  return new Worker(new URL("./section.worker.mjs", import_meta.url), { type: "module" });
94594
- } catch {
94854
+ } catch (error2) {
94855
+ log2.warn("Could not start the section worker, so sections build on the main thread. Pass sectionWorker to registerBrowserEnv to load it from another URL.", error2);
94595
94856
  return void 0;
94596
94857
  }
94597
94858
  }
94598
94859
  };
94599
- function registerBrowserEnv() {
94600
- const env3 = new BrowserEnv();
94860
+ function registerBrowserEnv(options) {
94861
+ const env3 = new BrowserEnv(options);
94601
94862
  Env.register(env3);
94602
94863
  return env3;
94603
94864
  }
@@ -94723,6 +94984,12 @@ ${shader.fragmentShader}`.replace(
94723
94984
  Caching.end();
94724
94985
  }
94725
94986
 
94987
+ // src/armor/index.ts
94988
+ init_dirname();
94989
+ init_buffer2();
94990
+ init_process2();
94991
+ init_Armor();
94992
+
94726
94993
  // src/assets/index.ts
94727
94994
  init_dirname();
94728
94995
  init_buffer2();
@@ -96092,7 +96359,7 @@ property list uchar int vertex_index
96092
96359
  init_util();
96093
96360
  init_log();
96094
96361
  init_three();
96095
- var log16 = logger("SceneInspector");
96362
+ var log17 = logger("SceneInspector");
96096
96363
  var help = "<span>Ctrl/Cmd+Click to Select<br/></span><br/>";
96097
96364
  var SceneInspector = class {
96098
96365
  constructor(renderer) {
@@ -96186,7 +96453,7 @@ property list uchar int vertex_index
96186
96453
  }
96187
96454
  selectObject(targetObject, targetIntersection, instance = this.getIntersectionInstance(targetIntersection)) {
96188
96455
  this.selectedObject = targetObject;
96189
- log16.debug("selected", targetObject);
96456
+ log17.debug("selected", targetObject);
96190
96457
  this.redraw(targetObject, targetIntersection, instance);
96191
96458
  }
96192
96459
  redraw(targetObject, targetIntersection, instance) {
@@ -96457,7 +96724,7 @@ property list uchar int vertex_index
96457
96724
  init_buffer2();
96458
96725
  init_process2();
96459
96726
  init_log();
96460
- var log17 = logger("InstanceManager");
96727
+ var log18 = logger("InstanceManager");
96461
96728
  var InstanceManager = class {
96462
96729
  constructor() {
96463
96730
  this.isInstanceManager = true;
@@ -96466,7 +96733,7 @@ property list uchar int vertex_index
96466
96733
  /** Allocates a new placement of a cached model, or returns `undefined` if the key is unknown. */
96467
96734
  async get(key) {
96468
96735
  if (key in this.instanceCache) {
96469
- log17.debug("key in cache", key);
96736
+ log18.debug("key in cache", key);
96470
96737
  return (await this.instanceCache[key]).nextInstance();
96471
96738
  }
96472
96739
  return void 0;
@@ -96476,7 +96743,7 @@ property list uchar int vertex_index
96476
96743
  if (key in this.instanceCache) {
96477
96744
  return await this.get(key);
96478
96745
  }
96479
- log17.debug("key not in cache", key);
96746
+ log18.debug("key not in cache", key);
96480
96747
  const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
96481
96748
  this.instanceCache[key] = pending;
96482
96749
  try {
@@ -97444,6 +97711,7 @@ property list uchar int vertex_index
97444
97711
  init_buffer2();
97445
97712
  init_process2();
97446
97713
  init_SceneObject();
97714
+ init_three_module();
97447
97715
 
97448
97716
  // src/skin/SkinPart.ts
97449
97717
  init_dirname();
@@ -97463,6 +97731,8 @@ property list uchar int vertex_index
97463
97731
  SkinPart2["RIGHT_TROUSERS"] = "rightTrousers";
97464
97732
  SkinPart2["LEFT_TROUSERS"] = "leftTrousers";
97465
97733
  SkinPart2["CAPE"] = "cape";
97734
+ SkinPart2["LEFT_EAR"] = "leftEar";
97735
+ SkinPart2["RIGHT_EAR"] = "rightEar";
97466
97736
  return SkinPart2;
97467
97737
  })(SkinPart || {});
97468
97738
  var SKIN_PARTS = Object.values(SkinPart);
@@ -97471,6 +97741,14 @@ property list uchar int vertex_index
97471
97741
  init_dirname();
97472
97742
  init_buffer2();
97473
97743
  init_process2();
97744
+ var earCoordinates = {
97745
+ west: { uv: [24, 1, 25, 7] },
97746
+ east: { uv: [31, 1, 32, 7] },
97747
+ south: { uv: [25, 1, 31, 7] },
97748
+ north: { uv: [32, 1, 38, 7] },
97749
+ up: { uv: [25, 0, 31, 1] },
97750
+ down: { uv: [31, 1, 37, 0] }
97751
+ };
97474
97752
  var baseSkinCoordinates = {
97475
97753
  head: {
97476
97754
  west: {
@@ -98091,7 +98369,9 @@ property list uchar int vertex_index
98091
98369
  south: { uv: [12, 1, 22, 17] },
98092
98370
  up: { uv: [11, 1, 1, 0] },
98093
98371
  down: { uv: [21, 0, 11, 1] }
98094
- }
98372
+ },
98373
+ leftEar: earCoordinates,
98374
+ rightEar: earCoordinates
98095
98375
  };
98096
98376
  var classicSkinTextureCoordinates = {
98097
98377
  ...baseSkinCoordinates
@@ -98145,6 +98425,7 @@ property list uchar int vertex_index
98145
98425
  var box3_12_4inner = [3, 12, 4];
98146
98426
  var box3_12_4outer = [3.5, 12.5, 4.5];
98147
98427
  var box10_16_1 = [10, 16, 1];
98428
+ var box8_8_3ear = [8, 8, 3];
98148
98429
  var baseSkinGeometries = {
98149
98430
  head: box8inner,
98150
98431
  hat: box8outer,
@@ -98158,7 +98439,9 @@ property list uchar int vertex_index
98158
98439
  leftTrousers: box4_12_4outer,
98159
98440
  rightLeg: box4_12_4inner,
98160
98441
  rightTrousers: box4_12_4outer,
98161
- cape: box10_16_1
98442
+ cape: box10_16_1,
98443
+ leftEar: box8_8_3ear,
98444
+ rightEar: box8_8_3ear
98162
98445
  };
98163
98446
  var classicSkinGeometries = { ...{}, ...baseSkinGeometries };
98164
98447
  var slimSkinGeometries = {
@@ -98190,6 +98473,12 @@ property list uchar int vertex_index
98190
98473
  };
98191
98474
 
98192
98475
  // src/skin/scene/SkinObject.ts
98476
+ var ArmorClass;
98477
+ var EntityObjectClass;
98478
+ function hasCubes(part) {
98479
+ return part.cubes.length > 0 || Object.values(part.children).some(hasCubes);
98480
+ }
98481
+ var UPSIDE_DOWN_OFFSET = (1.8 + 0.1) * 16 / 0.9375;
98193
98482
  var SkinObject = class extends SceneObject {
98194
98483
  constructor(options) {
98195
98484
  super();
@@ -98197,27 +98486,42 @@ property list uchar int vertex_index
98197
98486
  this.detectedSlim = false;
98198
98487
  this.skinLoad = 0;
98199
98488
  this.capeLoad = 0;
98489
+ this.armorLoad = 0;
98490
+ this.armorObjects = [];
98200
98491
  this.options = (0, import_ts_deepmerge.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
98201
98492
  this.slim = this.options.slim ?? false;
98202
98493
  }
98203
98494
  async init() {
98204
98495
  const cape = this.getGroupByName("cape" /* CAPE */);
98496
+ const capeOnBody = cape?.parent === this.getGroupByName("body" /* BODY */);
98205
98497
  this.createMeshes();
98206
- if (cape) this.getGroupByName("body" /* BODY */).attach(cape);
98498
+ if (cape) {
98499
+ const body = this.getGroupByName("body" /* BODY */);
98500
+ if (capeOnBody) body.add(cape);
98501
+ else body.attach(cape);
98502
+ }
98503
+ for (const { part, object: object4 } of this.armorObjects) this.getGroupByName(part).add(object4);
98504
+ this.updateEars();
98505
+ this.updateUpsideDown();
98207
98506
  }
98208
98507
  removeMeshes() {
98209
98508
  }
98210
98509
  createMeshes() {
98211
98510
  const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;
98511
+ this.model?.removeFromParent();
98512
+ const model = this.model = new Object3D();
98513
+ this.add(model);
98212
98514
  {
98213
- const headGroup = this.createAndAddGroup("head", 0, 28, 0, "y" /* Y */, -4);
98515
+ const headGroup = this.createGroup("head", 0, 28, 0, "y" /* Y */, -4);
98516
+ model.add(headGroup);
98214
98517
  const headGeo = this.getBoxGeometry("head" /* HEAD */);
98215
98518
  const head = this.createAndAddMesh("head", headGroup, headGeo, mat, "y" /* Y */, 4);
98216
98519
  const hatGeo = this.getBoxGeometry("hat" /* HAT */);
98217
98520
  const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
98218
98521
  }
98219
98522
  {
98220
- const bodyGroup = this.createAndAddGroup("body", 0, 24, 0);
98523
+ const bodyGroup = this.createGroup("body", 0, 24, 0);
98524
+ model.add(bodyGroup);
98221
98525
  const bodyGeo = this.getBoxGeometry("body" /* BODY */);
98222
98526
  const body = this.createAndAddMesh("body", bodyGroup, bodyGeo, mat, "y" /* Y */, -6);
98223
98527
  const jacketGeo = this.getBoxGeometry("jacket" /* JACKET */);
@@ -98225,7 +98529,8 @@ property list uchar int vertex_index
98225
98529
  }
98226
98530
  {
98227
98531
  {
98228
- const leftArmGroup = this.createAndAddGroup("leftArm", 5, 22, 0);
98532
+ const leftArmGroup = this.createGroup("leftArm", 5, 22, 0);
98533
+ model.add(leftArmGroup);
98229
98534
  const leftArmGeo = this.getBoxGeometry("leftArm" /* LEFT_ARM */);
98230
98535
  const leftArm = this.createAndAddMesh("leftArm", leftArmGroup, leftArmGeo, mat, "y" /* Y */, -4);
98231
98536
  leftArm.position.x = this.slim ? 0.5 : 1;
@@ -98234,7 +98539,8 @@ property list uchar int vertex_index
98234
98539
  leftSleeve.position.x = this.slim ? 0.5 : 1;
98235
98540
  }
98236
98541
  {
98237
- const rightArmGroup = this.createAndAddGroup("rightArm", -5, 22, 0);
98542
+ const rightArmGroup = this.createGroup("rightArm", -5, 22, 0);
98543
+ model.add(rightArmGroup);
98238
98544
  const rightArmGeo = this.getBoxGeometry("rightArm" /* RIGHT_ARM */);
98239
98545
  const rightArm = this.createAndAddMesh("rightArm", rightArmGroup, rightArmGeo, mat, "y" /* Y */, -4);
98240
98546
  rightArm.position.x = this.slim ? -0.5 : -1;
@@ -98245,14 +98551,16 @@ property list uchar int vertex_index
98245
98551
  }
98246
98552
  {
98247
98553
  {
98248
- const leftLegGroup = this.createAndAddGroup("leftLeg", 1.9, 12, 0);
98554
+ const leftLegGroup = this.createGroup("leftLeg", 1.9, 12, 0);
98555
+ model.add(leftLegGroup);
98249
98556
  const leftLegGeo = this.getBoxGeometry("leftLeg" /* LEFT_LEG */);
98250
98557
  const leftLeg = this.createAndAddMesh("leftLeg", leftLegGroup, leftLegGeo, mat, "y" /* Y */, -6);
98251
98558
  const leftTrousersGeo = this.getBoxGeometry("leftTrousers" /* LEFT_TROUSERS */);
98252
98559
  const leftTrousers = this.createAndAddMesh("leftTrousers", leftLegGroup, leftTrousersGeo, mat, "y" /* Y */, -6);
98253
98560
  }
98254
98561
  {
98255
- const rightLegGroup = this.createAndAddGroup("rightLeg", -1.9, 12, 0);
98562
+ const rightLegGroup = this.createGroup("rightLeg", -1.9, 12, 0);
98563
+ model.add(rightLegGroup);
98256
98564
  const rightLegGeo = this.getBoxGeometry("rightLeg" /* RIGHT_LEG */);
98257
98565
  const rightLeg = this.createAndAddMesh("rightLeg", rightLegGroup, rightLegGeo, mat, "y" /* Y */, -6);
98258
98566
  const rightTrousersGeo = this.getBoxGeometry("rightTrousers" /* RIGHT_TROUSERS */);
@@ -98319,6 +98627,54 @@ property list uchar int vertex_index
98319
98627
  }
98320
98628
  this.notifyDirty();
98321
98629
  }
98630
+ /**
98631
+ * Loads armor from 1.21.4+ equipment assets, or pass undefined to remove it.
98632
+ * Each piece moves with the skin part it covers.
98633
+ */
98634
+ async setArmor(armor) {
98635
+ const load = ++this.armorLoad;
98636
+ const objects = [];
98637
+ if (armor) {
98638
+ const Armor2 = ArmorClass ?? (ArmorClass = (await Promise.resolve().then(() => (init_Armor(), Armor_exports))).Armor);
98639
+ const EntityObject2 = EntityObjectClass ?? (EntityObjectClass = (await Promise.resolve().then(() => (init_EntityObject(), EntityObject_exports))).EntityObject);
98640
+ const model = await Armor2.getEntity(armor);
98641
+ if (model) {
98642
+ const parts = { head: "head", body: "body", left_arm: "leftArm", right_arm: "rightArm", left_leg: "leftLeg", right_leg: "rightLeg" };
98643
+ for (const [name2, part] of Object.entries(parts)) {
98644
+ const layers = {};
98645
+ for (const [draw, layer] of Object.entries(model.layers)) {
98646
+ const child = layer.layer.root.children[name2];
98647
+ if (!child || !hasCubes(child)) continue;
98648
+ const pose = { offset: [0, 0, 0], rotation: [0, 0, 0] };
98649
+ layers[draw] = { ...layer, layer: { ...layer.layer, root: {
98650
+ pose,
98651
+ cubes: [],
98652
+ children: { [name2]: { ...child, pose } }
98653
+ } } };
98654
+ }
98655
+ const first = Object.values(layers)[0];
98656
+ if (!first) continue;
98657
+ const object4 = new EntityObject2({ ...first, id: model.id, layers }, { flip: false });
98658
+ object4.rotation.x = Math.PI;
98659
+ objects.push({ part, object: object4 });
98660
+ }
98661
+ }
98662
+ }
98663
+ const results = await Promise.allSettled(objects.map(({ object: object4 }) => object4.init()));
98664
+ const failure = results.find((result) => result.status === "rejected");
98665
+ if (load !== this.armorLoad || failure) {
98666
+ for (const { object: object4 } of objects) object4.dispose();
98667
+ if (load === this.armorLoad && failure?.status === "rejected") throw failure.reason;
98668
+ return;
98669
+ }
98670
+ for (const { object: object4 } of this.armorObjects) {
98671
+ object4.dispose();
98672
+ object4.removeFromParent();
98673
+ }
98674
+ this.armorObjects = objects;
98675
+ for (const { part, object: object4 } of objects) this.getGroupByName(part)?.add(object4);
98676
+ this.notifyDirty();
98677
+ }
98322
98678
  /** Select the arm model, or pass undefined to use texture detection. */
98323
98679
  setSlim(slim) {
98324
98680
  this.options.slim = slim;
@@ -98337,6 +98693,39 @@ property list uchar int vertex_index
98337
98693
  }
98338
98694
  this.notifyDirty();
98339
98695
  }
98696
+ /** Shows or hides deadmau5's ears, which vanilla draws from the skin texture at 24,0 for that player only. */
98697
+ setEars(ears) {
98698
+ if (ears === (this.options.ears ?? false)) return;
98699
+ this.options.ears = ears;
98700
+ this.updateEars();
98701
+ }
98702
+ updateEars() {
98703
+ const head = this.getGroupByName("head" /* HEAD */);
98704
+ if (!head) return;
98705
+ for (const [part, x4] of [["leftEar" /* LEFT_EAR */, 6], ["rightEar" /* RIGHT_EAR */, -6]]) {
98706
+ const ear = this.getMeshByName(part);
98707
+ if (!this.options.ears) {
98708
+ ear?.removeFromParent();
98709
+ } else if (!ear) {
98710
+ const mesh = this.createAndAddMesh(part, head, this.getBoxGeometry(part), this.skinMaterial ?? Materials.MISSING_TEXTURE);
98711
+ mesh.position.set(x4, 9, 0.5);
98712
+ }
98713
+ }
98714
+ this.notifyDirty();
98715
+ }
98716
+ /** Turns the player upside down, as vanilla does for players named Dinnerbone or Grumm. */
98717
+ setUpsideDown(upsideDown) {
98718
+ if (upsideDown === (this.options.upsideDown ?? false)) return;
98719
+ this.options.upsideDown = upsideDown;
98720
+ this.updateUpsideDown();
98721
+ }
98722
+ updateUpsideDown() {
98723
+ if (!this.model) return;
98724
+ const upsideDown = this.options.upsideDown ?? false;
98725
+ this.model.position.y = upsideDown ? UPSIDE_DOWN_OFFSET : 0;
98726
+ this.model.rotation.z = upsideDown ? Math.PI : 0;
98727
+ this.notifyDirty();
98728
+ }
98340
98729
  /** Select the texture layout, or pass undefined to detect it from image dimensions. */
98341
98730
  async setLegacy(legacy) {
98342
98731
  if (legacy === this.options.legacy) return;
@@ -98346,6 +98735,11 @@ property list uchar int vertex_index
98346
98735
  dispose() {
98347
98736
  this.skinLoad++;
98348
98737
  this.capeLoad++;
98738
+ this.armorLoad++;
98739
+ for (const { object: object4 } of this.armorObjects.splice(0)) {
98740
+ object4.dispose();
98741
+ object4.removeFromParent();
98742
+ }
98349
98743
  super.dispose();
98350
98744
  }
98351
98745
  //TODO: layer toggles
@@ -98365,7 +98759,7 @@ property list uchar int vertex_index
98365
98759
  }
98366
98760
  var ModelObjectClass;
98367
98761
  var BlockObjectClass;
98368
- var EntityObjectClass;
98762
+ var EntityObjectClass2;
98369
98763
  var GuiObjectClass;
98370
98764
  var ItemTintsClass;
98371
98765
  var _MineRenderScene = class _MineRenderScene extends Scene {
@@ -98506,7 +98900,7 @@ property list uchar int vertex_index
98506
98900
  }
98507
98901
  /** Adds an entity loaded with {@link Entities.getEntity}, using its selected layers and textures. */
98508
98902
  async addEntity(entity, options, parent = this) {
98509
- const EntityObject2 = EntityObjectClass ?? (EntityObjectClass = (await Promise.resolve().then(() => (init_EntityObject(), EntityObject_exports))).EntityObject);
98903
+ const EntityObject2 = EntityObjectClass2 ?? (EntityObjectClass2 = (await Promise.resolve().then(() => (init_EntityObject(), EntityObject_exports))).EntityObject);
98510
98904
  return this.addSceneObject(entity, () => new EntityObject2(entity, options), options, parent);
98511
98905
  }
98512
98906
  /**
@@ -101167,7 +101561,7 @@ gl_FragDepth=readDepth(vUv);
101167
101561
 
101168
101562
  // src/renderer/Renderer.ts
101169
101563
  init_log();
101170
- var log19 = logger("Renderer");
101564
+ var log20 = logger("Renderer");
101171
101565
  var _Renderer = class _Renderer {
101172
101566
  constructor(options, surface) {
101173
101567
  this._width = 0;
@@ -101412,10 +101806,10 @@ gl_FragDepth=readDepth(vUv);
101412
101806
  this._element = element;
101413
101807
  this._element.appendChild(this.renderer.domElement);
101414
101808
  if (this.viewWidth == 0) {
101415
- log19.warn("0 element width");
101809
+ log20.warn("0 element width");
101416
101810
  }
101417
101811
  if (this.viewHeight == 0) {
101418
- log19.warn("0 element height");
101812
+ log20.warn("0 element height");
101419
101813
  }
101420
101814
  this.resize(this.viewWidth, this.viewHeight);
101421
101815
  }
@@ -101852,6 +102246,23 @@ gl_FragDepth=readDepth(vUv);
101852
102246
  }
101853
102247
  });
101854
102248
  };
102249
+ function entityAnimation(value, path) {
102250
+ const animation = object3(value, path);
102251
+ if (["name", "clips"].filter((key) => animation[key] !== void 0).length !== 1) {
102252
+ fail2(path, "expected exactly one of name or clips");
102253
+ }
102254
+ fields(value, path, { name: text, clips: (value2, path2) => {
102255
+ list((value3, path3) => {
102256
+ fields(value3, path3, { name: text, weight: nonnegative }, ["name"]);
102257
+ })(value2, path2);
102258
+ if (!value2.length) fail2(path2, "expected at least one clip");
102259
+ const names = /* @__PURE__ */ new Set();
102260
+ for (const [index, clip] of value2.entries()) {
102261
+ if (names.has(clip.name)) fail2(`${path2}[${index}].name`, `duplicate clip "${clip.name}"`);
102262
+ names.add(clip.name);
102263
+ }
102264
+ }, loop: boolean, speed: nonnegative, time: nonnegative, paused: boolean });
102265
+ }
101855
102266
  function guiLayer(value, path) {
101856
102267
  const layer = object3(value, path);
101857
102268
  if (["texture", "item", "text"].filter((key) => layer[key] !== void 0).length !== 1) {
@@ -101892,13 +102303,27 @@ gl_FragDepth=readDepth(vUv);
101892
102303
  const required = ["id", "type"];
101893
102304
  const renderOptions = { wireframe: boolean };
101894
102305
  switch (input.type) {
101895
- case "skin":
102306
+ case "skin": {
102307
+ const piece = (value2, path2) => {
102308
+ if (typeof value2 === "string") asset(value2, path2);
102309
+ else fields(value2, path2, {
102310
+ asset,
102311
+ color: color2,
102312
+ glint: boolean,
102313
+ trim: (value3, path3) => {
102314
+ fields(value3, path3, { pattern: asset, material: asset }, ["pattern", "material"]);
102315
+ }
102316
+ }, ["asset"]);
102317
+ };
101896
102318
  fields(value, path, {
101897
102319
  ...common2,
101898
102320
  skin: text,
101899
102321
  cape: (value2, path2) => {
101900
102322
  fields(value2, path2, { texture: text, layout: enumeration(["minecraft", "optifine", "labymod"]) }, ["texture"]);
101901
102323
  },
102324
+ armor: (value2, path2) => {
102325
+ fields(value2, path2, { head: piece, chest: piece, legs: piece, feet: piece });
102326
+ },
101902
102327
  hiddenParts: list(enumeration(SKIN_PARTS)),
101903
102328
  pose: (value2, path2) => {
101904
102329
  fields(value2, path2, {
@@ -101912,10 +102337,11 @@ gl_FragDepth=readDepth(vUv);
101912
102337
  });
101913
102338
  },
101914
102339
  options: (value2, path2) => {
101915
- fields(value2, path2, { slim: boolean, legacy: boolean });
102340
+ fields(value2, path2, { slim: boolean, legacy: boolean, ears: boolean, upsideDown: boolean });
101916
102341
  }
101917
102342
  }, required);
101918
102343
  break;
102344
+ }
101919
102345
  case "block":
101920
102346
  fields(value, path, {
101921
102347
  ...common2,
@@ -101954,9 +102380,7 @@ gl_FragDepth=readDepth(vUv);
101954
102380
  })
101955
102381
  });
101956
102382
  },
101957
- animation: (value2, path2) => {
101958
- fields(value2, path2, { name: text, loop: boolean, speed: nonnegative, time: nonnegative, paused: boolean }, ["name"]);
101959
- }
102383
+ animation: entityAnimation
101960
102384
  }, [...required, "asset"]);
101961
102385
  if (Array.isArray(input.layers) && !input.layers.length) fail2(`${path}.layers`, "expected at least one layer");
101962
102386
  break;
@@ -102191,6 +102615,7 @@ gl_FragDepth=readDepth(vUv);
102191
102615
  await skin.setSkinTexture(texture);
102192
102616
  await content.initialize(skin);
102193
102617
  if (definition.cape) await skin.setCapeTexture(await skinTexture(definition.cape.texture, true), definition.cape.layout);
102618
+ if (definition.armor) await skin.setArmor(definition.armor);
102194
102619
  for (const [part, rotation] of Object.entries(definition.pose ?? {})) {
102195
102620
  skin.getGroupByName(part)?.rotation.set(...rotation, "XYZ");
102196
102621
  }
@@ -102229,10 +102654,20 @@ gl_FragDepth=readDepth(vUv);
102229
102654
  const entity = await content.addEntity(model, { ...definition.options, instanceMeshes: false });
102230
102655
  object4 = entity;
102231
102656
  if (definition.animation) {
102657
+ const animation = definition.animation;
102232
102658
  const animations = await Entities.getAnimations(key);
102233
- const clip = animations?.[definition.animation.name];
102234
- if (!clip) throw new Error(`Entity ${definition.asset} has no animation "${definition.animation.name}"`);
102235
- entity.playAnimation(clip, definition.animation);
102659
+ if (animation.name !== void 0) {
102660
+ const clip = animations && Object.prototype.hasOwnProperty.call(animations, animation.name) ? animations[animation.name] : void 0;
102661
+ if (!clip) throw new Error(`Entity ${definition.asset} has no animation "${animation.name}"`);
102662
+ entity.playAnimation(clip, animation);
102663
+ } else {
102664
+ const clips = animation.clips.map(({ name: name2 }) => {
102665
+ const clip = animations && Object.prototype.hasOwnProperty.call(animations, name2) ? animations[name2] : void 0;
102666
+ if (!clip) throw new Error(`Entity ${definition.asset} has no animation "${name2}"`);
102667
+ return clip;
102668
+ });
102669
+ entity.playAnimations(clips, { ...animation, weights: animation.clips.map((clip) => clip.weight ?? 1) });
102670
+ }
102236
102671
  }
102237
102672
  break;
102238
102673
  }
@@ -102292,6 +102727,7 @@ gl_FragDepth=readDepth(vUv);
102292
102727
  init_buffer2();
102293
102728
  init_process2();
102294
102729
  init_Colormaps();
102730
+ init_PalettedTextures();
102295
102731
  init_TextureAtlas();
102296
102732
  init_TextureLoader();
102297
102733
  init_Textures();
@@ -103115,7 +103551,7 @@ gl_FragDepth=readDepth(vUv);
103115
103551
  read.waiters++;
103116
103552
  return new Promise((resolve, reject) => {
103117
103553
  let finished = false;
103118
- const release3 = () => {
103554
+ const release2 = () => {
103119
103555
  if (finished) return false;
103120
103556
  finished = true;
103121
103557
  signal?.removeEventListener("abort", abort2);
@@ -103123,7 +103559,7 @@ gl_FragDepth=readDepth(vUv);
103123
103559
  return true;
103124
103560
  };
103125
103561
  const abort2 = () => {
103126
- if (!release3()) return;
103562
+ if (!release2()) return;
103127
103563
  if (!read.waiters && !read.settled) {
103128
103564
  if (this.pending.get(key) === read) this.pending.delete(key);
103129
103565
  read.controller.abort(signal.reason);
@@ -103133,10 +103569,10 @@ gl_FragDepth=readDepth(vUv);
103133
103569
  signal?.addEventListener("abort", abort2, { once: true });
103134
103570
  read.promise.then(
103135
103571
  (data) => {
103136
- if (release3()) resolve(data);
103572
+ if (release2()) resolve(data);
103137
103573
  },
103138
103574
  (error2) => {
103139
- if (release3()) reject(error2);
103575
+ if (release2()) reject(error2);
103140
103576
  }
103141
103577
  );
103142
103578
  if (signal?.aborted) abort2();
@@ -103166,6 +103602,7 @@ gl_FragDepth=readDepth(vUv);
103166
103602
  init_dirname();
103167
103603
  init_buffer2();
103168
103604
  init_process2();
103605
+ init_BlockObject();
103169
103606
  init_three_module();
103170
103607
  init_BlockStates();
103171
103608
  init_AssetKey();
@@ -103179,6 +103616,7 @@ gl_FragDepth=readDepth(vUv);
103179
103616
  init_util();
103180
103617
  init_AssetKey();
103181
103618
  init_BlockStates();
103619
+ init_BlockEntities();
103182
103620
  init_CubeFace();
103183
103621
 
103184
103622
  // src/world/SectionModels.ts
@@ -103279,6 +103717,10 @@ gl_FragDepth=readDepth(vUv);
103279
103717
  biomeTint: source ? [...templates.values()].some((template) => template.biomeTint?.some((value) => value === 1)) || void 0 : void 0
103280
103718
  };
103281
103719
  }
103720
+ /** Starts loading the state's models and atlases so a later `prepareState` with the same properties finds them loaded. */
103721
+ async preload(blockState3, properties = {}) {
103722
+ await this.state(blockState3, properties);
103723
+ }
103282
103724
  async state(blockState3, properties) {
103283
103725
  let states = this.states.get(blockState3);
103284
103726
  if (!states) this.states.set(blockState3, states = /* @__PURE__ */ new Map());
@@ -103301,22 +103743,24 @@ gl_FragDepth=readDepth(vUv);
103301
103743
  async prepare(blockState3, properties) {
103302
103744
  const state = { ...await BlockStateResolver.defaults(blockState3), ...properties };
103303
103745
  const groups = BlockStateResolver.matching(blockState3, state);
103304
- if (!groups.length) return void 0;
103746
+ if (!groups.length || groups.some((group) => Array.isArray(group) && !group.length)) return void 0;
103747
+ const variants = groups.flatMap((group) => Array.isArray(group) ? group : [group]);
103748
+ if (variants.some((variant) => !variant.model)) return void 0;
103749
+ const settled = await Promise.allSettled(variants.map(async (variant) => {
103750
+ const modelKey = AssetKey.parse("models", variant.model);
103751
+ modelKey.root = blockState3.key?.root;
103752
+ const model = await Models.getMerged(modelKey);
103753
+ if (!model?.elements?.length) return void 0;
103754
+ const atlas = await UVMapper.getAtlas(model);
103755
+ const rotation = BlockStateResolver.rotation(variant);
103756
+ if (!atlas || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize) return void 0;
103757
+ return { model, atlas, rotation };
103758
+ }));
103305
103759
  const prepared = /* @__PURE__ */ new Map();
103306
- for (const group of groups) {
103307
- const choices = Array.isArray(group) ? group : [group];
103308
- if (!choices.length) return void 0;
103309
- for (const variant of choices) {
103310
- if (!variant.model) return void 0;
103311
- const modelKey = AssetKey.parse("models", variant.model);
103312
- modelKey.root = blockState3.key?.root;
103313
- const model = await Models.getMerged(modelKey);
103314
- if (!model?.elements?.length) return void 0;
103315
- const atlas = await UVMapper.getAtlas(model);
103316
- const rotation = BlockStateResolver.rotation(variant);
103317
- if (!atlas || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize) return void 0;
103318
- prepared.set(variant, { model, atlas, rotation });
103319
- }
103760
+ for (const [i4, result] of settled.entries()) {
103761
+ if (result.status === "rejected") throw result.reason;
103762
+ if (!result.value) return void 0;
103763
+ prepared.set(variants[i4], result.value);
103320
103764
  }
103321
103765
  return { state, groups, choices: prepared };
103322
103766
  }
@@ -103502,7 +103946,7 @@ gl_FragDepth=readDepth(vUv);
103502
103946
 
103503
103947
  // src/world/_entities/WorldEntities.ts
103504
103948
  init_log();
103505
- var log20 = logger("WorldEntities");
103949
+ var log21 = logger("WorldEntities");
103506
103950
  var WorldEntities = class {
103507
103951
  constructor(scene) {
103508
103952
  this.scene = scene;
@@ -103571,7 +104015,7 @@ gl_FragDepth=readDepth(vUv);
103571
104015
  placement.owner.set(object4, { type: key.toNamespacedString(), position: placement.position });
103572
104016
  this.scene.add(object4);
103573
104017
  } catch (error2) {
103574
- log20.warn(`Could not draw saved entity ${placement.key.toNamespacedString()}, skipping it`, error2);
104018
+ log21.warn(`Could not draw saved entity ${placement.key.toNamespacedString()}, skipping it`, error2);
103575
104019
  } finally {
103576
104020
  if (object4 && !placement.owner.has(object4)) object4.dispose();
103577
104021
  }
@@ -103793,7 +104237,8 @@ gl_FragDepth=readDepth(vUv);
103793
104237
 
103794
104238
  // src/world/MineRenderWorld.ts
103795
104239
  init_log();
103796
- var log21 = logger("MineRenderWorld");
104240
+ var log22 = logger("MineRenderWorld");
104241
+ var YIELD_INTERVAL_MS = 8;
103797
104242
  var MineRenderWorld = class {
103798
104243
  constructor(scene, options = {}) {
103799
104244
  this._chunks = /* @__PURE__ */ new Map();
@@ -103907,7 +104352,7 @@ gl_FragDepth=readDepth(vUv);
103907
104352
  failures.set(chunk, error2);
103908
104353
  if (this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`) === chunk) this.pendingBiomes.set(chunk, void 0);
103909
104354
  }
103910
- if (performance.now() - sliceStart > 8) {
104355
+ if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
103911
104356
  await yieldToEventLoop();
103912
104357
  sliceStart = performance.now();
103913
104358
  }
@@ -104008,15 +104453,18 @@ gl_FragDepth=readDepth(vUv);
104008
104453
  const key = AssetKey.parse("blockstates", block.type);
104009
104454
  keys.set(key.serialize(), key);
104010
104455
  }
104011
- await BlockStates.getAll(keys.values());
104456
+ const loaded = await BlockStates.getAll(keys.values());
104457
+ const states = new Map([...keys.keys()].map((key, i4) => [key, loaded[i4]]));
104012
104458
  if (!useBatches) {
104013
104459
  for (const block of multiblock.blocks) await place(block);
104014
104460
  return;
104015
104461
  }
104016
104462
  if (!executor) {
104017
104463
  const groups2 = /* @__PURE__ */ new Map();
104464
+ const distinct = /* @__PURE__ */ new Map();
104018
104465
  const position = new Vector3();
104019
104466
  for (const block of multiblock.blocks) {
104467
+ if (this.sectionModels && !Chunk.isAir(block)) distinct.set(ChunkData.paletteKey(block), block);
104020
104468
  const [x4, y5, z4] = block.position;
104021
104469
  this.validatePosBounds(position.set(x4, y5, z4));
104022
104470
  const cx = Math.floor(x4 / 16), cy = Math.floor(y5 / 16), cz = Math.floor(z4 / 16);
@@ -104027,6 +104475,16 @@ gl_FragDepth=readDepth(vUv);
104027
104475
  if (!group) groups2.set(chunk, group = []);
104028
104476
  group.push({ index: (y5 - cy * 16) * 256 + (z4 - cz * 16) * 16 + x4 - cx * 16, block });
104029
104477
  }
104478
+ if (this.sectionModels) {
104479
+ for (const block of distinct.values()) {
104480
+ const state = states.get(AssetKey.parse("blockstates", block.type).serialize());
104481
+ if (!state) continue;
104482
+ void (async () => {
104483
+ if (state.key && BlockEntities.entry(await BlockEntities.getIndex(state.key.root), state.key.toNamespacedString())) return;
104484
+ await this.sectionModels.preload(state, block.properties);
104485
+ })().catch(() => void 0);
104486
+ }
104487
+ }
104030
104488
  await this.placeChunkGroups(groups2, changes);
104031
104489
  return;
104032
104490
  }
@@ -104062,7 +104520,7 @@ gl_FragDepth=readDepth(vUv);
104062
104520
  )));
104063
104521
  for (const pos of positions) changes.set(`${pos.x},${pos.y},${pos.z}`, pos);
104064
104522
  }
104065
- if (performance.now() - sliceStart > 8) {
104523
+ if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
104066
104524
  await yieldToEventLoop();
104067
104525
  sliceStart = performance.now();
104068
104526
  }
@@ -104070,6 +104528,62 @@ gl_FragDepth=readDepth(vUv);
104070
104528
  }
104071
104529
  /** Replaces a chunk column's blocks, biomes, and saved light and, with `renderEntities`, its supported saved mobs. */
104072
104530
  async placeChunk(chunk, executor) {
104531
+ return this.placeColumn(chunk, executor);
104532
+ }
104533
+ /**
104534
+ * Replaces parsed columns in input order, then refreshes neighboring geometry once.
104535
+ * Duplicate coordinates retain their order. A failed column stops placement; queued refreshes finish before rejection.
104536
+ */
104537
+ async placeChunks(chunks) {
104538
+ const columns = [];
104539
+ for (const chunk of chunks) {
104540
+ const { x: x4, z: z4 } = chunk ?? {};
104541
+ if (![x4, z4].every(Number.isSafeInteger)) {
104542
+ throw new RangeError("Chunk column coordinates must be safe integers");
104543
+ }
104544
+ const sections = Array.from(chunk.sections, (section) => {
104545
+ const { y: y5 } = section ?? {};
104546
+ if (!Number.isSafeInteger(y5)) throw new RangeError("Chunk section coordinates must be safe integers");
104547
+ return { ...section, y: y5 };
104548
+ });
104549
+ columns.push({ ...chunk, x: x4, z: z4, sections });
104550
+ }
104551
+ if (!columns.length) return;
104552
+ await this.culling;
104553
+ let failed = false, failure, sliceStart = performance.now();
104554
+ try {
104555
+ for (const column of columns) {
104556
+ await this.placeColumn(column, void 0, true);
104557
+ if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
104558
+ await yieldToEventLoop();
104559
+ sliceStart = performance.now();
104560
+ }
104561
+ }
104562
+ } catch (error2) {
104563
+ failed = true;
104564
+ failure = error2;
104565
+ } finally {
104566
+ try {
104567
+ const failures = await this.refreshBiomes(true);
104568
+ if (failures.size) log22.warn("Failed to refresh biome colors", failures.values().next().value);
104569
+ } catch (error2) {
104570
+ if (!failed) {
104571
+ failed = true;
104572
+ failure = error2;
104573
+ }
104574
+ }
104575
+ try {
104576
+ await this.updateCulling([]);
104577
+ } catch (error2) {
104578
+ if (!failed) {
104579
+ failed = true;
104580
+ failure = error2;
104581
+ }
104582
+ }
104583
+ }
104584
+ if (failed) throw failure;
104585
+ }
104586
+ async placeColumn(chunk, executor, deferCulling = false) {
104073
104587
  if (![chunk.x, chunk.z].every(Number.isSafeInteger)) {
104074
104588
  throw new RangeError("Chunk column coordinates must be safe integers");
104075
104589
  }
@@ -104131,7 +104645,7 @@ gl_FragDepth=readDepth(vUv);
104131
104645
  } finally {
104132
104646
  this.markSectionChanged(target);
104133
104647
  }
104134
- if (performance.now() - sliceStart > 8) {
104648
+ if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
104135
104649
  await yieldToEventLoop();
104136
104650
  sliceStart = performance.now();
104137
104651
  }
@@ -104154,9 +104668,12 @@ gl_FragDepth=readDepth(vUv);
104154
104668
  await placeEntities?.();
104155
104669
  } finally {
104156
104670
  this.markBiomesChanged(chunk.x, chunk.z, void 0, false);
104157
- const failures = await this.refreshBiomes();
104158
- if (failures.size) log21.warn("Failed to refresh biome colors", failures.values().next().value);
104159
- await this.updateCulling([...changes.values()]);
104671
+ if (deferCulling) await this.updateCulling([...changes.values()], true);
104672
+ else {
104673
+ const failures = await this.refreshBiomes();
104674
+ if (failures.size) log22.warn("Failed to refresh biome colors", failures.values().next().value);
104675
+ await this.updateCulling([...changes.values()]);
104676
+ }
104160
104677
  }
104161
104678
  }
104162
104679
  /**
@@ -104186,14 +104703,14 @@ gl_FragDepth=readDepth(vUv);
104186
104703
  for (const { x: x4, z: z4 } of columns.values()) {
104187
104704
  this.entities?.clearColumn(x4, z4);
104188
104705
  await this.clearChunkColumn(x4, z4);
104189
- if (performance.now() - sliceStart > 8) {
104706
+ if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
104190
104707
  await yieldToEventLoop();
104191
104708
  sliceStart = performance.now();
104192
104709
  }
104193
104710
  }
104194
104711
  } finally {
104195
104712
  const failures = await this.refreshBiomes(true);
104196
- if (failures.size) log21.warn("Failed to refresh biome colors", failures.values().next().value);
104713
+ if (failures.size) log22.warn("Failed to refresh biome colors", failures.values().next().value);
104197
104714
  await this.updateCulling([]);
104198
104715
  }
104199
104716
  }
@@ -104325,15 +104842,25 @@ gl_FragDepth=readDepth(vUv);
104325
104842
  for (const [index, mask] of masks) await chunk.setCullMaskIndex(index, mask);
104326
104843
  await chunk.refreshLight(indices === "all" ? void 0 : indices);
104327
104844
  chunk.refreshAmbientOcclusion(this._ambientOcclusion);
104328
- if ((this._ambientOcclusion || this.ambientOcclusionPending) && performance.now() - sliceStart > 8) {
104845
+ if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
104329
104846
  await yieldToEventLoop();
104330
104847
  sliceStart = performance.now();
104331
104848
  }
104332
104849
  }
104333
- const builds = await Promise.allSettled([...batch.keys()].map(async (chunk) => {
104334
- await chunk.rebuildSectionMesh();
104335
- batch.delete(chunk);
104336
- }));
104850
+ const pending = [];
104851
+ for (const chunk of [...batch.keys()]) {
104852
+ const build = (async () => {
104853
+ await chunk.rebuildSectionMesh();
104854
+ batch.delete(chunk);
104855
+ })();
104856
+ void build.catch(() => void 0);
104857
+ pending.push(build);
104858
+ if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
104859
+ await yieldToEventLoop();
104860
+ sliceStart = performance.now();
104861
+ }
104862
+ }
104863
+ const builds = await Promise.allSettled(pending);
104337
104864
  const failure = builds.find((result) => result.status === "rejected");
104338
104865
  if (failure?.status === "rejected") throw failure.reason;
104339
104866
  } catch (error2) {
@@ -104740,6 +105267,8 @@ gl_FragDepth=readDepth(vUv);
104740
105267
  init_buffer2();
104741
105268
  init_process2();
104742
105269
  init_Env();
105270
+ init_log();
105271
+ var log23 = logger("SectionWorker");
104743
105272
  var _SectionWorker = class _SectionWorker {
104744
105273
  constructor(worker) {
104745
105274
  this.worker = worker;
@@ -104753,8 +105282,12 @@ gl_FragDepth=readDepth(vUv);
104753
105282
  if (reply.type === "pages") pending.resolve(reply.pages);
104754
105283
  else pending.reject(new Error(reply.message));
104755
105284
  });
104756
- worker.addEventListener("error", (event) => this.fail(event.message || "Section worker failed"));
104757
- worker.addEventListener("messageerror", () => this.fail("Section worker message could not be deserialized"));
105285
+ const fallBack = (message) => {
105286
+ log23.warn(`${message}, so sections build on the main thread`);
105287
+ this.fail(message);
105288
+ };
105289
+ worker.addEventListener("error", (event) => fallBack(event.message || "Section worker failed"));
105290
+ worker.addEventListener("messageerror", () => fallBack("Section worker message could not be deserialized"));
104758
105291
  }
104759
105292
  /** The shared worker, or undefined when the environment has none or a previous worker failed. */
104760
105293
  static shared() {
@@ -104791,6 +105324,9 @@ gl_FragDepth=readDepth(vUv);
104791
105324
  var SectionWorker = _SectionWorker;
104792
105325
 
104793
105326
  // src/world/SectionMesh.ts
105327
+ var BLOCK_SIZE = 16;
105328
+ var QUAD_VERTICES = 4;
105329
+ var QUAD_INDICES = 6;
104794
105330
  var templateCache = /* @__PURE__ */ new WeakMap();
104795
105331
  var WATER_TINT = new Color(4159204).toArray();
104796
105332
  function toInput(entries, maxAtlasSize, fluids, lighting) {
@@ -104827,8 +105363,8 @@ gl_FragDepth=readDepth(vUv);
104827
105363
  if (!data) {
104828
105364
  const indices = template.geometry.getIndex();
104829
105365
  const position = template.geometry.getAttribute("position");
104830
- const quads = indices.count / 6;
104831
- if (indices.count % 6 !== 0 || position.count !== quads * 4) {
105366
+ const quads = indices.count / QUAD_INDICES;
105367
+ if (indices.count % QUAD_INDICES !== 0 || position.count !== quads * QUAD_VERTICES) {
104832
105368
  throw new RangeError("Section template geometry must hold four vertices and six indices per quad");
104833
105369
  }
104834
105370
  data = {
@@ -104838,8 +105374,8 @@ gl_FragDepth=readDepth(vUv);
104838
105374
  uvs: new Float32Array(quads * 8),
104839
105375
  uvBounds: new Float32Array(quads * 16),
104840
105376
  colors: new Float32Array(quads * 12),
104841
- shade: new Float32Array(quads * 4),
104842
- indices: new Uint16Array(quads * 6),
105377
+ shade: new Float32Array(quads * QUAD_VERTICES),
105378
+ indices: new Uint16Array(quads * QUAD_INDICES),
104843
105379
  cullFaces: new Uint8Array(template.cullFaces),
104844
105380
  biomeTint: template.biomeTint ? new Uint8Array(template.biomeTint) : void 0,
104845
105381
  atlas: 0,
@@ -104851,7 +105387,7 @@ gl_FragDepth=readDepth(vUv);
104851
105387
  const bounds = template.geometry.getAttribute("uvBounds");
104852
105388
  const color3 = template.geometry.getAttribute("color");
104853
105389
  const shade = template.geometry.getAttribute("shade");
104854
- for (let vertex2 = 0; vertex2 < quads * 4; vertex2++) {
105390
+ for (let vertex2 = 0; vertex2 < quads * QUAD_VERTICES; vertex2++) {
104855
105391
  data.positions.set([position.getX(vertex2), position.getY(vertex2), position.getZ(vertex2)], vertex2 * 3);
104856
105392
  data.normals.set([normal.getX(vertex2), normal.getY(vertex2), normal.getZ(vertex2)], vertex2 * 3);
104857
105393
  data.uvs.set([uv.getX(vertex2), uv.getY(vertex2)], vertex2 * 2);
@@ -104864,7 +105400,7 @@ gl_FragDepth=readDepth(vUv);
104864
105400
  data.colors.set([color3?.getX(vertex2) ?? 1, color3?.getY(vertex2) ?? 1, color3?.getZ(vertex2) ?? 1], vertex2 * 3);
104865
105401
  data.shade[vertex2] = shade?.getX(vertex2) ?? 1;
104866
105402
  }
104867
- for (let i5 = 0; i5 < data.indices.length; i5++) data.indices[i5] = indices.getX(i5) - 4 * Math.floor(i5 / 6);
105403
+ for (let i5 = 0; i5 < data.indices.length; i5++) data.indices[i5] = indices.getX(i5) - QUAD_VERTICES * Math.floor(i5 / QUAD_INDICES);
104868
105404
  templateCache.set(template, data);
104869
105405
  }
104870
105406
  id = input.templateData.length;
@@ -104897,6 +105433,54 @@ gl_FragDepth=readDepth(vUv);
104897
105433
  }
104898
105434
  return { input, atlases: atlases2 };
104899
105435
  }
105436
+ function sortTransparentQuads(mesh) {
105437
+ const index = mesh.geometry.getIndex();
105438
+ if (index.count <= QUAD_INDICES) return;
105439
+ index.setUsage(DynamicDrawUsage);
105440
+ const count = index.count / QUAD_INDICES;
105441
+ let source, centers, depths, order;
105442
+ const view = new Matrix4(), localCamera = new Vector3(), key = new Vector3(), previous = new Vector3();
105443
+ let previousOrthographic;
105444
+ mesh.onBeforeRender = (_renderer, _scene, camera) => {
105445
+ localCamera.setFromMatrixPosition(camera.matrixWorld).applyMatrix4(view.copy(mesh.matrixWorld).invert());
105446
+ const orthographic = !!camera.isOrthographicCamera;
105447
+ if (orthographic) {
105448
+ view.multiplyMatrices(camera.matrixWorldInverse, mesh.matrixWorld);
105449
+ key.set(view.elements[2], view.elements[6], view.elements[10]);
105450
+ } else {
105451
+ key.copy(localCamera).divideScalar(BLOCK_SIZE).floor();
105452
+ }
105453
+ if (orthographic === previousOrthographic && key.equals(previous)) return;
105454
+ previous.copy(key);
105455
+ previousOrthographic = orthographic;
105456
+ if (!centers) {
105457
+ source = new Uint32Array(index.array);
105458
+ centers = new Float32Array(count * 3);
105459
+ depths = new Float32Array(count);
105460
+ order = Uint32Array.from({ length: count }, (_4, quad) => quad);
105461
+ const positions = mesh.geometry.getAttribute("position");
105462
+ for (let quad = 0; quad < count; quad++) {
105463
+ for (let axis = 0; axis < 3; axis++) {
105464
+ let center = 0;
105465
+ for (let corner = 0; corner < QUAD_VERTICES; corner++) center += positions.getComponent(quad * QUAD_VERTICES + corner, axis);
105466
+ centers[quad * 3 + axis] = center / QUAD_VERTICES;
105467
+ }
105468
+ }
105469
+ }
105470
+ for (let quad = 0; quad < count; quad++) {
105471
+ const x4 = centers[quad * 3], y5 = centers[quad * 3 + 1], z4 = centers[quad * 3 + 2];
105472
+ depths[quad] = orthographic ? key.x * x4 + key.y * y5 + key.z * z4 : -((x4 - localCamera.x) ** 2 + (y5 - localCamera.y) ** 2 + (z4 - localCamera.z) ** 2);
105473
+ }
105474
+ order.sort((a4, b4) => depths[a4] - depths[b4] || a4 - b4);
105475
+ if (!order.some((quad, offset) => index.array[offset * QUAD_INDICES] !== source[quad * QUAD_INDICES])) return;
105476
+ for (let offset = 0; offset < count; offset++) {
105477
+ for (let indexOffset = 0; indexOffset < QUAD_INDICES; indexOffset++) {
105478
+ index.array[offset * QUAD_INDICES + indexOffset] = source[order[offset] * QUAD_INDICES + indexOffset];
105479
+ }
105480
+ }
105481
+ index.needsUpdate = true;
105482
+ };
105483
+ }
104900
105484
  var SectionMesh = class _SectionMesh extends Group {
104901
105485
  constructor() {
104902
105486
  super(...arguments);
@@ -104906,7 +105490,11 @@ gl_FragDepth=readDepth(vUv);
104906
105490
  /** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
104907
105491
  getBlockIndex(hit) {
104908
105492
  if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
104909
- return this.blockIndices.get(hit.object)?.[Math.floor(hit.faceIndex / 2)];
105493
+ const mesh = hit.object;
105494
+ const owners = this.blockIndices.get(mesh);
105495
+ if (!owners) return void 0;
105496
+ const vertex2 = mesh.geometry.getIndex().getX(hit.faceIndex * 3);
105497
+ return owners[Math.floor(vertex2 / QUAD_VERTICES)];
104910
105498
  }
104911
105499
  /** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
104912
105500
  static build(entries, maxAtlasSize = 2048, fluids, lighting) {
@@ -104942,13 +105530,14 @@ gl_FragDepth=readDepth(vUv);
104942
105530
  const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
104943
105531
  material.side = FrontSide;
104944
105532
  if (page.layer === 2) {
105533
+ material.depthWrite = !material.transparent;
104945
105534
  material.side = DoubleSide;
104946
105535
  material.forceSinglePass = true;
104947
- material.depthWrite = !material.transparent;
104948
105536
  }
104949
105537
  material.vertexColors = true;
104950
105538
  const texture = material.uniforms?.map?.value ?? material.map;
104951
105539
  const mesh = new Mesh(geometry, material);
105540
+ if (transparent) sortTransparentQuads(mesh);
104952
105541
  section.add(mesh);
104953
105542
  section.blockIndices.set(mesh, page.blockIndices);
104954
105543
  const unsubscribe = [];
@@ -105243,8 +105832,10 @@ gl_FragDepth=readDepth(vUv);
105243
105832
  if (rejected?.status === "rejected") throw rejected.reason;
105244
105833
  }
105245
105834
  const positions = [];
105246
- let failed = false, failure;
105247
- for (const { index, key, block } of placements) {
105835
+ const jobs = /* @__PURE__ */ new Map();
105836
+ let failureOrder = Infinity, failure;
105837
+ for (const [order, { index, key, block }] of placements.entries()) {
105838
+ jobs.delete(index);
105248
105839
  this.hiddenBlocks.delete(index);
105249
105840
  this.data.assign(index, this.data.intern(block), block?.nbt);
105250
105841
  const readBlock = this.data.snapshot(index);
@@ -105260,7 +105851,6 @@ gl_FragDepth=readDepth(vUv);
105260
105851
  this.z * 16 + Math.floor(index / 16) % 16
105261
105852
  );
105262
105853
  positions.push(worldPos);
105263
- let object4;
105264
105854
  try {
105265
105855
  if (!readBlock) continue;
105266
105856
  const resolved = resolutions.get(key);
@@ -105282,7 +105872,7 @@ gl_FragDepth=readDepth(vUv);
105282
105872
  this.sectionBlocks.set(index, templates.map((template) => ({ index, template, cullMask: 0, biomeTint: context?.tint })));
105283
105873
  this.meshDirty = true;
105284
105874
  } else {
105285
- object4 = await this.scene.addBlock(blockState3, {
105875
+ jobs.set(index, { order, readBlock, blockState: blockState3, position: MineRenderWorld.worldToScenePosition(worldPos), options: {
105286
105876
  mergeMeshes: true,
105287
105877
  instanceMeshes: true,
105288
105878
  maxInstanceCount: 2e3,
@@ -105290,13 +105880,12 @@ gl_FragDepth=readDepth(vUv);
105290
105880
  variantPosition,
105291
105881
  biome: context?.biome,
105292
105882
  biomePosition: this.biomePosition(index, blockState3, stored)
105293
- });
105294
- object4.setPosition(MineRenderWorld.worldToScenePosition(worldPos));
105883
+ } });
105884
+ continue;
105295
105885
  }
105296
105886
  this.renderedBlocks.set(index, { get block() {
105297
105887
  return readBlock();
105298
- }, object: object4 });
105299
- if (object4) this.objectBlocks.add(index);
105888
+ }, object: void 0 });
105300
105889
  } catch (error2) {
105301
105890
  if (preserveDataOnFailure && readBlock) {
105302
105891
  this.renderedBlocks.set(index, { get block() {
@@ -105304,12 +105893,35 @@ gl_FragDepth=readDepth(vUv);
105304
105893
  }, object: void 0 });
105305
105894
  } else this.data.assign(index, 0);
105306
105895
  this.fluidCells[index] = 0;
105307
- object4?.removeFromScene();
105308
- if (!failed) failure = error2;
105309
- failed = true;
105896
+ if (order < failureOrder) {
105897
+ failureOrder = order;
105898
+ failure = error2;
105899
+ }
105310
105900
  }
105311
105901
  }
105312
- if (failed) throw failure;
105902
+ const pending = [...jobs];
105903
+ const objects = await Promise.allSettled(pending.map(([, job]) => this.createBlockObject(job.blockState, job.position, job.options)));
105904
+ for (const [i4, [index, { order, readBlock }]] of pending.entries()) {
105905
+ const result = objects[i4];
105906
+ if (result.status === "fulfilled") {
105907
+ this.renderedBlocks.set(index, { get block() {
105908
+ return readBlock();
105909
+ }, object: result.value });
105910
+ this.objectBlocks.add(index);
105911
+ } else {
105912
+ if (preserveDataOnFailure) {
105913
+ this.renderedBlocks.set(index, { get block() {
105914
+ return readBlock();
105915
+ }, object: void 0 });
105916
+ } else this.data.assign(index, 0);
105917
+ this.fluidCells[index] = 0;
105918
+ if (order < failureOrder) {
105919
+ failureOrder = order;
105920
+ failure = result.reason;
105921
+ }
105922
+ }
105923
+ }
105924
+ if (failureOrder < Infinity) throw failure;
105313
105925
  return positions;
105314
105926
  }
105315
105927
  /** Replaces every cell from parsed section data. The caller refreshes neighbor culling. */
@@ -105380,37 +105992,42 @@ gl_FragDepth=readDepth(vUv);
105380
105992
  failed = true;
105381
105993
  }
105382
105994
  }
105383
- for (const { index, blockState: blockState3, biome } of perBlocks) {
105384
- let object4;
105385
- try {
105386
- object4 = await this.scene.addBlock(blockState3, {
105387
- mergeMeshes: true,
105388
- instanceMeshes: true,
105389
- maxInstanceCount: 2e3,
105390
- initialState: this.data.stateAt(this.data.idAt(index)).properties,
105391
- variantPosition: this.positionAt(index),
105392
- biome,
105393
- biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
105394
- });
105395
- object4.setPosition(new Vector3(
105396
- this.x * 256 + index % 16 * 16,
105397
- this.y * 256 + Math.floor(index / 256) * 16,
105398
- this.z * 256 + Math.floor(index / 16) % 16 * 16
105399
- ));
105400
- this.renderedBlocks.get(index).object = object4;
105995
+ const objects = await Promise.allSettled(perBlocks.map(({ index, blockState: blockState3, biome }) => this.createBlockObject(blockState3, new Vector3(
105996
+ this.x * 256 + index % 16 * 16,
105997
+ this.y * 256 + Math.floor(index / 256) * 16,
105998
+ this.z * 256 + Math.floor(index / 16) % 16 * 16
105999
+ ), {
106000
+ mergeMeshes: true,
106001
+ instanceMeshes: true,
106002
+ maxInstanceCount: 2e3,
106003
+ initialState: this.data.stateAt(this.data.idAt(index)).properties,
106004
+ variantPosition: this.positionAt(index),
106005
+ biome,
106006
+ biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
106007
+ })));
106008
+ for (const [i4, { index }] of perBlocks.entries()) {
106009
+ const result = objects[i4];
106010
+ if (result.status === "fulfilled") {
106011
+ this.renderedBlocks.get(index).object = result.value;
105401
106012
  this.objectBlocks.add(index);
105402
- } catch (error2) {
106013
+ } else {
105403
106014
  this.data.assign(index, 0);
105404
106015
  this.fluidCells[index] = 0;
105405
106016
  this.renderedBlocks.delete(index);
105406
106017
  this.objectBlocks.delete(index);
105407
- object4?.removeFromScene();
105408
- if (!failed) failure = error2;
106018
+ if (!failed) failure = result.reason;
105409
106019
  failed = true;
105410
106020
  }
105411
106021
  }
105412
106022
  if (failed) throw failure;
105413
106023
  }
106024
+ createBlockObject(blockState3, position, options) {
106025
+ return this.scene.addSceneObject(blockState3, () => {
106026
+ const object4 = new BlockObject(blockState3, options);
106027
+ object4.position.copy(position);
106028
+ return object4;
106029
+ }, options);
106030
+ }
105414
106031
  positionAt(index) {
105415
106032
  return [this.x * 16 + index % 16, this.y * 16 + Math.floor(index / 256), this.z * 16 + Math.floor(index / 16) % 16];
105416
106033
  }
@@ -105769,6 +106386,7 @@ gl_FragDepth=readDepth(vUv);
105769
106386
  init_dirname();
105770
106387
  init_buffer2();
105771
106388
  init_process2();
106389
+ var MAX_PREFETCHED_COLUMNS = 4;
105772
106390
  var WorldStreamer = class {
105773
106391
  constructor(world, source, options = {}) {
105774
106392
  this.world = world;
@@ -105778,6 +106396,7 @@ gl_FragDepth=readDepth(vUv);
105778
106396
  this.missing = /* @__PURE__ */ new Map();
105779
106397
  this.failed = /* @__PURE__ */ new Map();
105780
106398
  this.desired = [];
106399
+ this.reads = /* @__PURE__ */ new Map();
105781
106400
  this.disposed = false;
105782
106401
  this.loadRadius = options.loadRadius ?? 2;
105783
106402
  this.unloadRadius = options.unloadRadius ?? Math.min(32, this.loadRadius + 1);
@@ -105822,6 +106441,12 @@ gl_FragDepth=readDepth(vUv);
105822
106441
  if (this.loading && !this.within(this.loading.position, this.loadRadius)) {
105823
106442
  this.loading.controller.abort();
105824
106443
  }
106444
+ for (const [key, read] of this.reads) {
106445
+ if (!this.within(read.position, this.loadRadius)) {
106446
+ read.controller.abort();
106447
+ if (read.ready) this.reads.delete(key);
106448
+ }
106449
+ }
105825
106450
  }
105826
106451
  return this.running ?? (this.running = Promise.resolve().then(() => this.drain()));
105827
106452
  }
@@ -105842,8 +106467,11 @@ gl_FragDepth=readDepth(vUv);
105842
106467
  this.desired = [];
105843
106468
  this.center = void 0;
105844
106469
  this.loading?.controller.abort();
106470
+ for (const read of this.reads.values()) read.controller.abort();
105845
106471
  return this.disposal ?? (this.disposal = Promise.resolve().then(async () => {
105846
106472
  await this.running?.catch(() => void 0);
106473
+ await Promise.all([...this.reads.values()].map((read) => read.promise));
106474
+ this.reads.clear();
105847
106475
  try {
105848
106476
  await this.unloadMany([...this.owned.values()]);
105849
106477
  } finally {
@@ -105869,6 +106497,10 @@ gl_FragDepth=readDepth(vUv);
105869
106497
  await this.unloadMany(obsolete);
105870
106498
  continue;
105871
106499
  }
106500
+ if (this.world.placeChunks) {
106501
+ if (await this.placeReadyChunks()) continue;
106502
+ return;
106503
+ }
105872
106504
  const position = this.desired.find((position2) => this.needsLoad(position2));
105873
106505
  if (!position) return;
105874
106506
  let chunk;
@@ -105891,26 +106523,105 @@ gl_FragDepth=readDepth(vUv);
105891
106523
  continue;
105892
106524
  }
105893
106525
  this.owned.set(this.key(position), position);
106526
+ await this.placeOwnedColumns([position], () => this.world.placeChunk(chunk));
106527
+ }
106528
+ } finally {
106529
+ for (const [key, read] of this.reads) {
106530
+ read.controller.abort();
106531
+ if (read.ready) this.reads.delete(key);
106532
+ }
106533
+ this.running = void 0;
106534
+ }
106535
+ }
106536
+ fillReadSlots() {
106537
+ while (!this.disposed && this.reads.size < MAX_PREFETCHED_COLUMNS) {
106538
+ const position = this.desired.find((position2) => this.needsLoad(position2) && !this.reads.has(this.key(position2)));
106539
+ if (!position) return;
106540
+ const key = this.key(position);
106541
+ const read = {
106542
+ position,
106543
+ controller: new AbortController(),
106544
+ promise: Promise.resolve(),
106545
+ ready: false,
106546
+ failed: false
106547
+ };
106548
+ this.reads.set(key, read);
106549
+ read.promise = (async () => {
105894
106550
  try {
105895
- await this.world.placeChunk(chunk);
105896
- this.loaded.set(this.key(position), position);
106551
+ read.chunk = await this.source.getChunk(position.x, position.z, read.controller.signal);
106552
+ if (read.chunk) this.validateChunk(read.chunk, position);
105897
106553
  } catch (error2) {
105898
- try {
105899
- await this.unloadMany([position]);
105900
- } catch (cleanupError) {
105901
- const failure = error2 instanceof Error ? error2 : new Error(String(error2));
105902
- try {
105903
- Object.defineProperty(failure, "cause", { value: cleanupError, configurable: true });
105904
- } catch {
105905
- throw Object.assign(new Error(failure.message), { cause: cleanupError });
105906
- }
105907
- throw failure;
106554
+ read.failed = true;
106555
+ read.error = error2;
106556
+ } finally {
106557
+ read.ready = true;
106558
+ if (read.controller.signal.aborted || this.disposed || !this.within(position, this.loadRadius)) {
106559
+ this.reads.delete(key);
105908
106560
  }
105909
- throw error2;
106561
+ }
106562
+ })();
106563
+ }
106564
+ }
106565
+ /** Places only the ready prefix, so later source reads cannot delay the nearest ready column. */
106566
+ async placeReadyChunks() {
106567
+ this.fillReadSlots();
106568
+ const position = this.desired.find((position2) => this.needsLoad(position2));
106569
+ if (!position) {
106570
+ if (!this.reads.size) return false;
106571
+ await Promise.all([...this.reads.values()].map((read) => read.promise));
106572
+ return true;
106573
+ }
106574
+ const head = this.reads.get(this.key(position));
106575
+ if (!head) {
106576
+ for (let index = this.desired.length - 1; index >= 0; index--) {
106577
+ const key = this.key(this.desired[index]);
106578
+ if (this.reads.get(key)?.ready) {
106579
+ this.reads.delete(key);
106580
+ return true;
105910
106581
  }
105911
106582
  }
105912
- } finally {
105913
- this.running = void 0;
106583
+ await Promise.race([...this.reads.values()].map((read) => read.promise));
106584
+ return true;
106585
+ }
106586
+ if (!head.ready) {
106587
+ await head.promise;
106588
+ return true;
106589
+ }
106590
+ const chunks = [], positions = [];
106591
+ for (const desired of this.desired) {
106592
+ if (!this.needsLoad(desired)) continue;
106593
+ const key = this.key(desired), read = this.reads.get(key);
106594
+ if (!read?.ready) break;
106595
+ this.reads.delete(key);
106596
+ if (read.failed) this.failed.set(key, { ...desired, error: read.error });
106597
+ else if (!read.chunk) this.missing.set(key, desired);
106598
+ else {
106599
+ chunks.push(read.chunk);
106600
+ positions.push(desired);
106601
+ }
106602
+ }
106603
+ if (!chunks.length) return true;
106604
+ for (const position2 of positions) this.owned.set(this.key(position2), position2);
106605
+ await this.placeOwnedColumns(positions, () => this.world.placeChunks(chunks));
106606
+ return true;
106607
+ }
106608
+ async placeOwnedColumns(positions, place) {
106609
+ try {
106610
+ await place();
106611
+ for (const position of positions) this.loaded.set(this.key(position), position);
106612
+ } catch (error2) {
106613
+ try {
106614
+ await this.unloadMany(positions);
106615
+ } catch (cleanupError) {
106616
+ const failure = error2 instanceof Error ? error2 : new Error(String(error2));
106617
+ try {
106618
+ Object.defineProperty(failure, "cause", { value: cleanupError, configurable: true });
106619
+ } catch {
106620
+ throw Object.assign(new Error(failure.message), { cause: cleanupError });
106621
+ }
106622
+ throw failure;
106623
+ }
106624
+ throw error2;
105914
106625
  }
105915
106626
  }
105916
106627
  needsLoad(position) {