minerender 2.1.0-alpha.52 → 2.1.0-alpha.54

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.
@@ -843,7 +843,7 @@ var init_Textures = __esm({
843
843
  });
844
844
 
845
845
  // src/Materials.ts
846
- import { Color, DoubleSide, FrontSide, MeshBasicMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from "three";
846
+ import { Color, CustomBlending, DoubleSide, OneFactor, RepeatWrapping, FrontSide, MeshBasicMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial, ZeroFactor } from "three";
847
847
  var Materials;
848
848
  var init_Materials = __esm({
849
849
  "src/Materials.ts"() {
@@ -885,6 +885,71 @@ var init_Materials = __esm({
885
885
  alphaTest: 0.5
886
886
  });
887
887
  }
888
+ /** Whether vanilla's render type for the mode culls back faces. */
889
+ static entityModeCulls(mode = "cutout") {
890
+ return mode === "cutout_cull" || mode === "solid" || mode === "eyes" || mode === "water_mask";
891
+ }
892
+ /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */
893
+ static entityModeScroll(mode = "cutout") {
894
+ if (mode === "energy_swirl") return [0.01, 0.01];
895
+ if (mode === "breeze_wind") return [0.02, 0];
896
+ return void 0;
897
+ }
898
+ /**
899
+ * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes
900
+ * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides
901
+ * whether the geometry gets inward faces.
902
+ */
903
+ static createEntityCanvasMaterial(canvas, mode = "cutout", tint) {
904
+ const material = _Materials.createBasicCanvasMaterial(canvas);
905
+ switch (mode) {
906
+ case "cutout":
907
+ case "cutout_cull":
908
+ break;
909
+ case "cutout_z_offset":
910
+ material.polygonOffset = true;
911
+ material.polygonOffsetFactor = -1;
912
+ material.polygonOffsetUnits = -10;
913
+ break;
914
+ case "solid":
915
+ material.alphaTest = 0;
916
+ break;
917
+ case "translucent":
918
+ case "breeze_wind":
919
+ material.transparent = true;
920
+ material.alphaTest = 0.1;
921
+ break;
922
+ case "translucent_emissive":
923
+ material.transparent = true;
924
+ material.alphaTest = 0.1;
925
+ material.depthWrite = false;
926
+ break;
927
+ case "eyes":
928
+ material.transparent = true;
929
+ material.alphaTest = 0;
930
+ material.depthWrite = false;
931
+ break;
932
+ case "energy_swirl":
933
+ material.transparent = true;
934
+ material.alphaTest = 0.1;
935
+ material.blending = CustomBlending;
936
+ material.blendSrc = OneFactor;
937
+ material.blendDst = OneFactor;
938
+ material.blendSrcAlpha = ZeroFactor;
939
+ material.blendDstAlpha = OneFactor;
940
+ material.color.set(8421504);
941
+ break;
942
+ case "water_mask":
943
+ material.alphaTest = 0;
944
+ material.colorWrite = false;
945
+ break;
946
+ }
947
+ if (_Materials.entityModeScroll(mode)) {
948
+ material.map.wrapS = material.map.wrapT = RepeatWrapping;
949
+ }
950
+ if (tint !== void 0) material.color.multiply(new Color(tint));
951
+ return material;
952
+ }
888
953
  static createGuiCanvasMaterial(canvas) {
889
954
  const material = new MeshBasicMaterial({
890
955
  map: Textures.createCanvasTexture(canvas),
@@ -3533,48 +3598,6 @@ var init_SceneObject = __esm({
3533
3598
  }
3534
3599
  });
3535
3600
 
3536
- // src/model/ModelCulling.ts
3537
- import { Vector3 as Vector39 } from "three";
3538
- var ModelCulling;
3539
- var init_ModelCulling = __esm({
3540
- "src/model/ModelCulling.ts"() {
3541
- init_CubeFace();
3542
- ModelCulling = class {
3543
- static toLocalMask(worldMask, rotation) {
3544
- let localMask = 0;
3545
- for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
3546
- const normal = new Vector39(...offset).applyEuler(rotation);
3547
- const worldFace = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
3548
- if (worldFace < 0) return 0;
3549
- if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
3550
- }
3551
- return localMask;
3552
- }
3553
- static isOpaqueFullCube(atlas) {
3554
- if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
3555
- const element = atlas.model.elements[0];
3556
- if (element.from.length !== 3 || !element.from.every((value) => value === 0) || element.to.length !== 3 || !element.to.every((value) => value === 16) || element.rotation && element.rotation.angle !== 0 || element.mappedUv?.length !== 48 || !element.mappedUv.every(Number.isFinite)) return false;
3557
- if (!(atlas.image.width > 0 && atlas.image.height > 0)) return false;
3558
- return CUBE_FACES.every((face, faceIndex) => {
3559
- const texture = element.faces[face]?.texture;
3560
- if (!texture?.startsWith("#")) return false;
3561
- const key = texture.slice(1);
3562
- const position = atlas.positions[key];
3563
- const size = atlas.sizes[key];
3564
- if (position?.length !== 2 || !position.every(Number.isFinite) || size?.length !== 2 || !size.every((value) => value > 0 && Number.isFinite(value))) return false;
3565
- for (let vertex = 0; vertex < 4; vertex++) {
3566
- const uvIndex = (faceIndex * 4 + vertex) * 2;
3567
- const x = element.mappedUv[uvIndex] * atlas.image.width;
3568
- const y = (1 - element.mappedUv[uvIndex + 1]) * atlas.image.height;
3569
- if (x < position[0] - 1e-6 || x > position[0] + size[0] + 1e-6 || y < position[1] - 1e-6 || y > position[1] + size[1] + 1e-6) return false;
3570
- }
3571
- return true;
3572
- });
3573
- }
3574
- };
3575
- }
3576
- });
3577
-
3578
3601
  // src/three/BufferGeometryUtils.js
3579
3602
  import {
3580
3603
  BufferAttribute as BufferAttribute4,
@@ -3585,7 +3608,7 @@ import {
3585
3608
  TriangleFanDrawMode,
3586
3609
  TriangleStripDrawMode,
3587
3610
  TrianglesDrawMode,
3588
- Vector3 as Vector310
3611
+ Vector3 as Vector39
3589
3612
  } from "three";
3590
3613
  function computeTangents(geometry) {
3591
3614
  geometry.computeTangents();
@@ -3904,15 +3927,15 @@ function computeMorphedAttributes(object) {
3904
3927
  console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
3905
3928
  return null;
3906
3929
  }
3907
- const _vA = new Vector310();
3908
- const _vB = new Vector310();
3909
- const _vC = new Vector310();
3910
- const _tempA = new Vector310();
3911
- const _tempB = new Vector310();
3912
- const _tempC = new Vector310();
3913
- const _morphA = new Vector310();
3914
- const _morphB = new Vector310();
3915
- const _morphC = new Vector310();
3930
+ const _vA = new Vector39();
3931
+ const _vB = new Vector39();
3932
+ const _vC = new Vector39();
3933
+ const _tempA = new Vector39();
3934
+ const _tempB = new Vector39();
3935
+ const _tempC = new Vector39();
3936
+ const _morphA = new Vector39();
3937
+ const _morphB = new Vector39();
3938
+ const _morphC = new Vector39();
3916
3939
  function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
3917
3940
  _vA.fromBufferAttribute(attribute, a2);
3918
3941
  _vB.fromBufferAttribute(attribute, b2);
@@ -4121,12 +4144,54 @@ var init_BufferGeometryUtils = __esm({
4121
4144
  }
4122
4145
  });
4123
4146
 
4147
+ // src/model/ModelCulling.ts
4148
+ import { Vector3 as Vector310 } from "three";
4149
+ var ModelCulling;
4150
+ var init_ModelCulling = __esm({
4151
+ "src/model/ModelCulling.ts"() {
4152
+ init_CubeFace();
4153
+ ModelCulling = class {
4154
+ static toLocalMask(worldMask, rotation) {
4155
+ let localMask = 0;
4156
+ for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
4157
+ const normal = new Vector310(...offset).applyEuler(rotation);
4158
+ const worldFace = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
4159
+ if (worldFace < 0) return 0;
4160
+ if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
4161
+ }
4162
+ return localMask;
4163
+ }
4164
+ static isOpaqueFullCube(atlas) {
4165
+ if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
4166
+ const element = atlas.model.elements[0];
4167
+ if (element.from.length !== 3 || !element.from.every((value) => value === 0) || element.to.length !== 3 || !element.to.every((value) => value === 16) || element.rotation && element.rotation.angle !== 0 || element.mappedUv?.length !== 48 || !element.mappedUv.every(Number.isFinite)) return false;
4168
+ if (!(atlas.image.width > 0 && atlas.image.height > 0)) return false;
4169
+ return CUBE_FACES.every((face, faceIndex) => {
4170
+ const texture = element.faces[face]?.texture;
4171
+ if (!texture?.startsWith("#")) return false;
4172
+ const key = texture.slice(1);
4173
+ const position = atlas.positions[key];
4174
+ const size = atlas.sizes[key];
4175
+ if (position?.length !== 2 || !position.every(Number.isFinite) || size?.length !== 2 || !size.every((value) => value > 0 && Number.isFinite(value))) return false;
4176
+ for (let vertex = 0; vertex < 4; vertex++) {
4177
+ const uvIndex = (faceIndex * 4 + vertex) * 2;
4178
+ const x = element.mappedUv[uvIndex] * atlas.image.width;
4179
+ const y = (1 - element.mappedUv[uvIndex + 1]) * atlas.image.height;
4180
+ if (x < position[0] - 1e-6 || x > position[0] + size[0] + 1e-6 || y < position[1] - 1e-6 || y > position[1] + size[1] + 1e-6) return false;
4181
+ }
4182
+ return true;
4183
+ });
4184
+ }
4185
+ };
4186
+ }
4187
+ });
4188
+
4124
4189
  // src/model/scene/ModelObject.ts
4125
- import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color7, Euler as Euler6, Matrix4 as Matrix46 } from "three";
4190
+ import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as Matrix47 } from "three";
4126
4191
  function isModelObject(obj) {
4127
4192
  return obj.isModelObject;
4128
4193
  }
4129
- var import_ts_deepmerge5, p9, ModelObject;
4194
+ var import_ts_deepmerge5, p7, ModelObject;
4130
4195
  var init_ModelObject = __esm({
4131
4196
  "src/model/scene/ModelObject.ts"() {
4132
4197
  init_SceneObject();
@@ -4139,7 +4204,7 @@ var init_ModelObject = __esm({
4139
4204
  init_CubeFace();
4140
4205
  init_DisplayTransforms();
4141
4206
  init_ModelCulling();
4142
- p9 = prefix("ModelObject");
4207
+ p7 = prefix("ModelObject");
4143
4208
  ModelObject = class _ModelObject extends SceneObject {
4144
4209
  constructor(originalModel, options) {
4145
4210
  super(options);
@@ -4197,19 +4262,19 @@ var init_ModelObject = __esm({
4197
4262
  if (tintIndex === void 0 || tintIndex < 0) continue;
4198
4263
  const tint = this.options.tints[tintIndex];
4199
4264
  if (tint === void 0) continue;
4200
- const color = new Color7(tint);
4265
+ const color = new Color8(tint);
4201
4266
  for (let vertex = 0; vertex < 4; vertex++) {
4202
4267
  color.toArray(colors, (faceIndex * 4 + vertex) * 3);
4203
4268
  }
4204
4269
  }
4205
4270
  elGeo.setAttribute("color", new BufferAttribute5(colors, 3));
4206
4271
  }
4207
- elGeo.applyMatrix4(new Matrix46().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4208
- elGeo.applyMatrix4(new Matrix46().makeTranslation(el.from[0], el.from[1], el.from[2]));
4272
+ elGeo.applyMatrix4(new Matrix47().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4273
+ elGeo.applyMatrix4(new Matrix47().makeTranslation(el.from[0], el.from[1], el.from[2]));
4209
4274
  if (el.rotation) {
4210
4275
  applyElementRotation(el.rotation, elGeo);
4211
4276
  }
4212
- elGeo.applyMatrix4(new Matrix46().makeTranslation(-8, -8, -8));
4277
+ elGeo.applyMatrix4(new Matrix47().makeTranslation(-8, -8, -8));
4213
4278
  if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
4214
4279
  if (this.options.mergeMeshes) {
4215
4280
  allGeos.push(elGeo);
@@ -4221,10 +4286,10 @@ var init_ModelObject = __esm({
4221
4286
  }
4222
4287
  });
4223
4288
  } else {
4224
- console.debug(p9, this.atlas.model, "has no elements");
4289
+ console.debug(p7, this.atlas.model, "has no elements");
4225
4290
  }
4226
4291
  } else {
4227
- console.debug(p9, "Missing atlas for", this);
4292
+ console.debug(p7, "Missing atlas for", this);
4228
4293
  }
4229
4294
  if (this.options.mergeMeshes) {
4230
4295
  let combinedGeo;
@@ -4322,7 +4387,7 @@ var init_fluidBlocks = __esm({
4322
4387
  });
4323
4388
 
4324
4389
  // src/model/fluid/FluidGeometry.ts
4325
- import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute5 } from "three";
4390
+ import { BufferGeometry as BufferGeometry4, Float32BufferAttribute as Float32BufferAttribute5 } from "three";
4326
4391
  function getBlockFluidState(key, state) {
4327
4392
  const rule = key && fluidRules[key.toNamespacedString()];
4328
4393
  if (rule) return {
@@ -4340,7 +4405,7 @@ function ownHeight(sample) {
4340
4405
  return (level === 0 || level >= 8 ? 8 : 8 - level) / 9;
4341
4406
  }
4342
4407
  function createFluidGeometry(kind, sample) {
4343
- const geometry = new BufferGeometry3();
4408
+ const geometry = new BufferGeometry4();
4344
4409
  const positions = [], normals = [], uvs = [], indices = [];
4345
4410
  const self = sample(0, 0, 0);
4346
4411
  const height = (x, z) => {
@@ -4461,7 +4526,7 @@ __export(FluidModelObject_exports, {
4461
4526
  FluidModelObject: () => FluidModelObject,
4462
4527
  sampleFluid: () => sampleFluid
4463
4528
  });
4464
- import { BufferAttribute as BufferAttribute6, Color as Color8, DoubleSide as DoubleSide3 } from "three";
4529
+ import { BufferAttribute as BufferAttribute6, Color as Color9, DoubleSide as DoubleSide3 } from "three";
4465
4530
  function sampleFluid(kind, sample) {
4466
4531
  const cells = [];
4467
4532
  const key = [];
@@ -4512,7 +4577,7 @@ var init_FluidModelObject = __esm({
4512
4577
  }
4513
4578
  }
4514
4579
  geometry.clearGroups();
4515
- const color = new Color8(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4580
+ const color = new Color9(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4516
4581
  const colors = new Float32Array(geometry.getAttribute("position").count * 3);
4517
4582
  for (let i = 0; i < colors.length; i += 3) color.toArray(colors, i);
4518
4583
  geometry.setAttribute("color", new BufferAttribute6(colors, 3));
@@ -4809,32 +4874,44 @@ var Entities = class {
4809
4874
  static async getLayerList(modelKey) {
4810
4875
  return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
4811
4876
  }
4877
+ /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
4878
+ static async getPassList(modelKey) {
4879
+ return (await this.getModelFile(modelKey))?.passes ?? [];
4880
+ }
4812
4881
  static async getEntity(modelKey, textureKey, options) {
4813
4882
  const model = await this.getModelFile(modelKey);
4814
4883
  if (!model) return void 0;
4815
- const names = [...new Set(options?.layers ?? [options?.layer ?? "main"])];
4816
- if (names.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
4817
- const selected = names.map((name) => {
4818
- const layer = model.layers[name];
4884
+ const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
4885
+ const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
4886
+ if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
4887
+ draws.push(...passes);
4888
+ const names = [];
4889
+ const selected = draws.map((pass) => {
4890
+ const layer = model.layers[pass.layer];
4819
4891
  if (!layer) {
4820
- throw new MineRenderError(`Entity ${model.id} has no layer "${name}". Available layers: ${Object.keys(model.layers).join(", ")}`);
4892
+ throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
4821
4893
  }
4822
- return { name, layer };
4894
+ let name = pass.layer;
4895
+ for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
4896
+ names.push(name);
4897
+ return { name, layer, pass };
4823
4898
  });
4824
- const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer }, index) => {
4899
+ const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
4825
4900
  const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
4901
+ const textureLocation = pass.textureLocation ?? layer.textureLocation;
4826
4902
  let texture;
4827
4903
  if (override) {
4828
4904
  const path = isAssetKey(override) ? override.getFullPath() : override.path;
4829
4905
  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);
4830
- } else if (layer.textureLocation !== void 0) {
4831
- texture = AssetKey.parse("textures", layer.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
4906
+ } else if (textureLocation !== void 0) {
4907
+ texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
4832
4908
  } else {
4833
4909
  texture = await this.resolveTexture(modelKey);
4834
4910
  }
4835
- return [name, { key: override ?? modelKey, texture, layer }];
4911
+ const render = pass.render ?? layer.render;
4912
+ return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
4836
4913
  })));
4837
- return { ...layers[names[0]], id: model.id, layers };
4914
+ return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
4838
4915
  }
4839
4916
  static async resolveTexture(modelKey) {
4840
4917
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
@@ -4916,11 +4993,12 @@ function trimCanvas(source) {
4916
4993
  init_SceneObject();
4917
4994
  init_Caching();
4918
4995
  var import_ts_deepmerge4 = __toESM(require_dist());
4996
+ init_Ticker();
4919
4997
  init_model();
4920
4998
  init_ModelTextures();
4921
4999
  init_AssetKey();
4922
5000
  init_Materials();
4923
- import { Object3D as Object3D3 } from "three";
5001
+ import { Color as Color3, Euler as Euler4, Matrix4 as Matrix44, Object3D as Object3D3 } from "three";
4924
5002
  init_three();
4925
5003
  var EntityObject = class _EntityObject extends SceneObject {
4926
5004
  constructor(entity, options) {
@@ -4928,10 +5006,14 @@ var EntityObject = class _EntityObject extends SceneObject {
4928
5006
  this.entity = entity;
4929
5007
  this.isEntityObject = true;
4930
5008
  this.meshesCreated = false;
5009
+ /** Scrolling materials are owned: their texture offset follows this entity's age. */
5010
+ this.scrollMaterials = [];
5011
+ /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
5012
+ this.age = 0;
4931
5013
  this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
4932
5014
  }
4933
5015
  static {
4934
- this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, { flip: true });
5016
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
4935
5017
  }
4936
5018
  async init() {
4937
5019
  this.createMeshes();
@@ -4940,6 +5022,25 @@ var EntityObject = class _EntityObject extends SceneObject {
4940
5022
  dispose() {
4941
5023
  super.dispose();
4942
5024
  }
5025
+ disposeAndRemoveAllChildren() {
5026
+ this.clearScrollMaterials();
5027
+ super.disposeAndRemoveAllChildren();
5028
+ }
5029
+ clearScrollMaterials() {
5030
+ Ticker.remove(this.scrollTicker);
5031
+ this.scrollTicker = void 0;
5032
+ for (const { material } of this.scrollMaterials.splice(0)) {
5033
+ material.map?.dispose();
5034
+ material.dispose();
5035
+ }
5036
+ }
5037
+ /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
5038
+ updateScroll() {
5039
+ for (const { offset, speed } of this.scrollMaterials) {
5040
+ offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
5041
+ }
5042
+ this.notifyDirty();
5043
+ }
4943
5044
  getLayerGroup(name) {
4944
5045
  return super.getGroupByName(`layer:${name}`);
4945
5046
  }
@@ -4970,16 +5071,29 @@ var EntityObject = class _EntityObject extends SceneObject {
4970
5071
  createMeshes(force = false) {
4971
5072
  if (this.meshesCreated && !force) return;
4972
5073
  const modelRoot = new Object3D3();
4973
- if (this.options.flip) modelRoot.scale.set(-1, -1, 1);
5074
+ const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
5075
+ if (transform) {
5076
+ for (const op of transform) {
5077
+ const matrix = new Matrix44();
5078
+ if ("scale" in op) matrix.makeScale(...op.scale);
5079
+ else if ("translate" in op) matrix.makeTranslation(...op.translate);
5080
+ else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
5081
+ modelRoot.matrix.multiply(matrix);
5082
+ }
5083
+ modelRoot.matrixAutoUpdate = false;
5084
+ } else if (this.options.flip ?? true) {
5085
+ modelRoot.scale.set(-1, -1, 1);
5086
+ }
4974
5087
  this.add(modelRoot);
4975
5088
  Object.entries(this.entityLayers).forEach(([name, layer], index) => {
4976
5089
  const group = this.createGroup(`layer:${name}`);
4977
5090
  modelRoot.add(group);
4978
- this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index);
5091
+ const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
5092
+ this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
4979
5093
  });
4980
5094
  this.meshesCreated = true;
4981
5095
  }
4982
- createPart(name, part, parent, textureSize, material, renderOrder) {
5096
+ createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
4983
5097
  const anchor = this.createGroup(name);
4984
5098
  anchor.position.fromArray(part.pose.offset);
4985
5099
  anchor.rotation.set(...part.pose.rotation, "ZYX");
@@ -4998,7 +5112,7 @@ var EntityObject = class _EntityObject extends SceneObject {
4998
5112
  uv
4999
5113
  ).clone();
5000
5114
  geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
5001
- if (Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
5115
+ if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
5002
5116
  const index = Array.from(geometry.getIndex().array);
5003
5117
  geometry.setIndex(index.concat(index.slice().reverse()));
5004
5118
  }
@@ -5008,26 +5122,42 @@ var EntityObject = class _EntityObject extends SceneObject {
5008
5122
  if (this.options.wireframe) addWireframeToMesh(geometry, mesh);
5009
5123
  }
5010
5124
  for (const [childName, child] of Object.entries(part.children)) {
5011
- this.createPart(childName, child, anchor, size, material, renderOrder);
5125
+ this.createPart(childName, child, anchor, size, material, renderOrder, inward);
5012
5126
  }
5013
5127
  }
5014
5128
  async applyTextures() {
5129
+ this.clearScrollMaterials();
5015
5130
  await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
5131
+ const mode = layer.render ?? layer.layer.render ?? "cutout";
5132
+ const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
5133
+ const scroll = Materials.entityModeScroll(mode);
5016
5134
  const assetKeyStr = this.getTextureKey(layer).serialize();
5017
- const keyStr = `entity:${assetKeyStr}`;
5018
- let mat = Caching.materialCache.getIfPresent(keyStr);
5135
+ const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color3(tint).getHexString()}:${assetKeyStr}`;
5136
+ let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
5019
5137
  if (!mat) {
5020
5138
  const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
5021
5139
  const imageData = await this.loadTextures(layer);
5022
5140
  if (!imageData) return;
5023
5141
  const canvas = imageData.data.canvas;
5024
- const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
5025
- mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5142
+ const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
5143
+ mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5144
+ if (scroll) {
5145
+ this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
5146
+ }
5026
5147
  }
5027
5148
  this.getLayerGroup(name)?.traverse((object) => {
5028
5149
  if (isMesh(object)) object.material = mat;
5029
5150
  });
5030
5151
  }));
5152
+ if (!this.children.length) {
5153
+ this.clearScrollMaterials();
5154
+ } else if (this.scrollMaterials.length) {
5155
+ this.updateScroll();
5156
+ this.scrollTicker = Ticker.add(() => {
5157
+ this.age++;
5158
+ this.updateScroll();
5159
+ });
5160
+ }
5031
5161
  this.notifyDirty();
5032
5162
  }
5033
5163
  };
@@ -5039,11 +5169,11 @@ function isEntityObject(obj) {
5039
5169
  init_MineRenderError();
5040
5170
 
5041
5171
  // src/export/SceneExporter.ts
5042
- import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color6, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as Matrix45, Mesh as Mesh5, MeshBasicMaterial as MeshBasicMaterial2, NearestFilter as NearestFilter3, RGBAFormat as RGBAFormat3, Scene as Scene4, Source as Source2, Texture as Texture4, UnsignedByteType } from "three";
5172
+ import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color7, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as Matrix46, Mesh as Mesh5, MeshBasicMaterial as MeshBasicMaterial2, NearestFilter as NearestFilter3, RGBAFormat as RGBAFormat3, Scene as Scene4, Source as Source2, Texture as Texture4, UnsignedByteType } from "three";
5043
5173
 
5044
5174
  // ../../node_modules/three/examples/jsm/exporters/OBJExporter.js
5045
5175
  import {
5046
- Color as Color3,
5176
+ Color as Color4,
5047
5177
  Matrix3,
5048
5178
  Vector2 as Vector22,
5049
5179
  Vector3 as Vector36
@@ -5055,7 +5185,7 @@ var OBJExporter = class {
5055
5185
  let indexVertexUvs = 0;
5056
5186
  let indexNormals = 0;
5057
5187
  const vertex = new Vector36();
5058
- const color = new Color3();
5188
+ const color = new Color4();
5059
5189
  const normal = new Vector36();
5060
5190
  const uv = new Vector22();
5061
5191
  const face = [];
@@ -5186,7 +5316,7 @@ var OBJExporter = class {
5186
5316
  import {
5187
5317
  Matrix3 as Matrix32,
5188
5318
  Vector3 as Vector37,
5189
- Color as Color4
5319
+ Color as Color5
5190
5320
  } from "three";
5191
5321
  var PLYExporter = class {
5192
5322
  parse(object, onDone, options = {}) {
@@ -5244,7 +5374,7 @@ var PLYExporter = class {
5244
5374
  includeIndices = false;
5245
5375
  }
5246
5376
  });
5247
- const tempColor = new Color4();
5377
+ const tempColor = new Color5();
5248
5378
  includeIndices = includeIndices && excludeAttributes.indexOf("index") === -1;
5249
5379
  includeNormals = includeNormals && excludeAttributes.indexOf("normal") === -1;
5250
5380
  includeColors = includeColors && excludeAttributes.indexOf("color") === -1;
@@ -5456,7 +5586,7 @@ property list uchar int vertex_index
5456
5586
  import {
5457
5587
  BufferAttribute as BufferAttribute3,
5458
5588
  ClampToEdgeWrapping,
5459
- Color as Color5,
5589
+ Color as Color6,
5460
5590
  DoubleSide as DoubleSide2,
5461
5591
  InterpolateDiscrete,
5462
5592
  InterpolateLinear,
@@ -5465,14 +5595,14 @@ import {
5465
5595
  LinearMipmapLinearFilter,
5466
5596
  LinearMipmapNearestFilter,
5467
5597
  MathUtils as MathUtils2,
5468
- Matrix4 as Matrix44,
5598
+ Matrix4 as Matrix45,
5469
5599
  MirroredRepeatWrapping,
5470
5600
  NearestFilter as NearestFilter2,
5471
5601
  NearestMipmapLinearFilter,
5472
5602
  NearestMipmapNearestFilter,
5473
5603
  PropertyBinding,
5474
5604
  RGBAFormat as RGBAFormat2,
5475
- RepeatWrapping,
5605
+ RepeatWrapping as RepeatWrapping2,
5476
5606
  Scene as Scene3,
5477
5607
  Source,
5478
5608
  SRGBColorSpace as SRGBColorSpace4,
@@ -5690,7 +5820,7 @@ THREE_TO_WEBGL[LinearFilter] = WEBGL_CONSTANTS.LINEAR;
5690
5820
  THREE_TO_WEBGL[LinearMipmapNearestFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST;
5691
5821
  THREE_TO_WEBGL[LinearMipmapLinearFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR;
5692
5822
  THREE_TO_WEBGL[ClampToEdgeWrapping] = WEBGL_CONSTANTS.CLAMP_TO_EDGE;
5693
- THREE_TO_WEBGL[RepeatWrapping] = WEBGL_CONSTANTS.REPEAT;
5823
+ THREE_TO_WEBGL[RepeatWrapping2] = WEBGL_CONSTANTS.REPEAT;
5694
5824
  THREE_TO_WEBGL[MirroredRepeatWrapping] = WEBGL_CONSTANTS.MIRRORED_REPEAT;
5695
5825
  var PATH_PROPERTIES = {
5696
5826
  scale: "scale",
@@ -5698,7 +5828,7 @@ var PATH_PROPERTIES = {
5698
5828
  quaternion: "rotation",
5699
5829
  morphTargetInfluences: "weights"
5700
5830
  };
5701
- var DEFAULT_SPECULAR_COLOR = new Color5();
5831
+ var DEFAULT_SPECULAR_COLOR = new Color6();
5702
5832
  var GLB_HEADER_BYTES = 12;
5703
5833
  var GLB_HEADER_MAGIC = 1179937895;
5704
5834
  var GLB_VERSION = 2;
@@ -6755,7 +6885,7 @@ var GLTFWriter = class {
6755
6885
  if (rootJoint === void 0) return null;
6756
6886
  const joints = [];
6757
6887
  const inverseBindMatrices = new Float32Array(skeleton.bones.length * 16);
6758
- const temporaryBoneInverse = new Matrix44();
6888
+ const temporaryBoneInverse = new Matrix45();
6759
6889
  for (let i = 0; i < skeleton.bones.length; ++i) {
6760
6890
  joints.push(nodeMap.get(skeleton.bones[i]));
6761
6891
  temporaryBoneInverse.copy(skeleton.boneInverses[i]);
@@ -7221,7 +7351,7 @@ var GLTFMeshGpuInstancing = class {
7221
7351
  const translationAttr = new Float32Array(mesh.count * 3);
7222
7352
  const rotationAttr = new Float32Array(mesh.count * 4);
7223
7353
  const scaleAttr = new Float32Array(mesh.count * 3);
7224
- const matrix = new Matrix44();
7354
+ const matrix = new Matrix45();
7225
7355
  const position = new Vector38();
7226
7356
  const quaternion = new Quaternion4();
7227
7357
  const scale = new Vector38();
@@ -7395,7 +7525,7 @@ var SceneExporter = class {
7395
7525
  }
7396
7526
  };
7397
7527
  function localMatrix(object) {
7398
- return object.matrixAutoUpdate ? new Matrix45().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7528
+ return object.matrixAutoUpdate ? new Matrix46().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7399
7529
  }
7400
7530
  function createSnapshot(root, gltf, bakeColors = false) {
7401
7531
  const scene = new Scene4();
@@ -7480,7 +7610,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7480
7610
  const material = copyMaterial(sourceMaterial, geometry);
7481
7611
  if (!sourceMaterial.vertexColors) geometry.deleteAttribute("color");
7482
7612
  if (bakeColors || instanceColor) {
7483
- const tint = (material.color ?? new Color6()).clone();
7613
+ const tint = (material.color ?? new Color7()).clone();
7484
7614
  if (instanceColor) tint.multiply(instanceColor);
7485
7615
  if (bakeColors) {
7486
7616
  const original = geometry.getAttribute("color");
@@ -7507,9 +7637,9 @@ function createSnapshot(root, gltf, bakeColors = false) {
7507
7637
  const instanced = mesh;
7508
7638
  if (instanced.isInstancedMesh) {
7509
7639
  for (let i = 0; i < instanced.count; i++) {
7510
- const matrix = new Matrix45();
7640
+ const matrix = new Matrix46();
7511
7641
  instanced.getMatrixAt(i, matrix);
7512
- const color = instanced.instanceColor ? new Color6().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7642
+ const color = instanced.instanceColor ? new Color7().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7513
7643
  addMesh(mesh, world.clone().multiply(matrix), color);
7514
7644
  }
7515
7645
  } else {
@@ -7521,7 +7651,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7521
7651
  try {
7522
7652
  const ancestors = [];
7523
7653
  for (let parent = root.parent; parent; parent = parent.parent) ancestors.unshift(parent);
7524
- const world = new Matrix45();
7654
+ const world = new Matrix46();
7525
7655
  for (const ancestor of ancestors) {
7526
7656
  if (!ancestor.visible) return { scene, dispose };
7527
7657
  world.multiply(localMatrix(ancestor));
@@ -7588,20 +7718,90 @@ function copyDataTexture(source) {
7588
7718
  }
7589
7719
 
7590
7720
  // src/gui/GuiHelper.ts
7721
+ init_AssetKey();
7591
7722
  var GuiHelper = class {
7592
7723
  static inventorySlot(slot, origin = [0, 0], offset = [18, 18], rowSize = 9) {
7593
7724
  const [column, row] = typeof slot === "number" ? [slot % rowSize, Math.floor(slot / rowSize)] : slot;
7594
7725
  return [origin[0] + column * offset[0], origin[1] + row * offset[1]];
7595
7726
  }
7727
+ /** Creates crafting-table layers for ingredients and the result; stack counts are not drawn. */
7728
+ static recipe(recipe, options = {}) {
7729
+ const layers = [
7730
+ { name: "background", texture: "minecraft:gui/container/crafting_table", crop: [0, 0, 176, 166] }
7731
+ ];
7732
+ const itemKey = (ingredient) => {
7733
+ const item = typeof ingredient === "string" && !ingredient.startsWith("#") ? ingredient : typeof ingredient === "object" && "item" in ingredient ? ingredient.item : options.resolveIngredient?.(ingredient);
7734
+ if (isAssetKey(item)) return item;
7735
+ if (!item || item.startsWith("#")) {
7736
+ throw new Error(`Select a concrete item for recipe ingredient ${JSON.stringify(ingredient)}`);
7737
+ }
7738
+ const key = AssetKey.parse("models", item);
7739
+ return new AssetKey(key.namespace, key.getFullPath(), "models", "item");
7740
+ };
7741
+ const addIngredient = (ingredient, slot) => {
7742
+ layers.push({
7743
+ name: `ingredient-${slot}`,
7744
+ item: itemKey(ingredient),
7745
+ position: this.inventorySlot(slot, [30, 17], [18, 18], 3)
7746
+ });
7747
+ };
7748
+ switch (recipe.type) {
7749
+ case "minecraft:crafting_shaped":
7750
+ case "crafting_shaped": {
7751
+ const pattern = recipe.pattern;
7752
+ if (!pattern.length || pattern.length > 3 || !pattern[0].length || pattern[0].length > 3 || pattern.some((row) => row.length !== pattern[0].length)) {
7753
+ throw new Error("Crafting patterns must be rectangular, with 1\u20133 rows and columns");
7754
+ }
7755
+ const cells = pattern.flatMap((row, y) => row.split("").map((symbol, x) => ({ symbol, x, y }))).filter((cell) => cell.symbol !== " ");
7756
+ if (!cells.length) throw new Error("Crafting patterns must contain an ingredient");
7757
+ const minX = Math.min(...cells.map((cell) => cell.x)), maxX = Math.max(...cells.map((cell) => cell.x));
7758
+ const minY = Math.min(...cells.map((cell) => cell.y)), maxY = Math.max(...cells.map((cell) => cell.y));
7759
+ const offsetX = minX === maxX ? 1 : 0, offsetY = minY === maxY ? 1 : 0;
7760
+ for (const { symbol, x, y } of cells) {
7761
+ const ingredient = recipe.key[symbol];
7762
+ if (!ingredient) throw new Error(`Missing recipe ingredient for symbol ${JSON.stringify(symbol)}`);
7763
+ addIngredient(ingredient, (y - minY + offsetY) * 3 + x - minX + offsetX);
7764
+ }
7765
+ break;
7766
+ }
7767
+ case "minecraft:crafting_shapeless":
7768
+ case "crafting_shapeless":
7769
+ if (!recipe.ingredients.length || recipe.ingredients.length > 9) {
7770
+ throw new Error("Shapeless crafting recipes require 1\u20139 ingredients");
7771
+ }
7772
+ recipe.ingredients.forEach(addIngredient);
7773
+ break;
7774
+ default:
7775
+ throw new Error(`Unsupported crafting recipe type: ${recipe.type}`);
7776
+ }
7777
+ layers.push({
7778
+ name: "result",
7779
+ item: itemKey("id" in recipe.result ? recipe.result.id : recipe.result.item),
7780
+ position: [124, 35]
7781
+ });
7782
+ return layers;
7783
+ }
7596
7784
  };
7597
7785
 
7598
7786
  // src/gui/scene/GuiObject.ts
7599
7787
  init_AssetKey();
7600
7788
  init_ModelTextures();
7789
+ init_Models();
7601
7790
  init_Caching();
7602
7791
  init_SceneObject();
7603
7792
  init_Materials();
7604
- import { Box2, Mesh as Mesh6, PlaneGeometry as PlaneGeometry2, Vector2 as Vector23 } from "three";
7793
+ init_ModelObject();
7794
+ init_DisplayPosition();
7795
+ import { Box2, Box3 as Box32, Mesh as Mesh7, PlaneGeometry as PlaneGeometry2, Vector2 as Vector23 } from "three";
7796
+
7797
+ // src/model/GuiLight.ts
7798
+ var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
7799
+ GuiLight2["FRONT"] = "front";
7800
+ GuiLight2["SIDE"] = "side";
7801
+ return GuiLight2;
7802
+ })(GuiLight || {});
7803
+
7804
+ // src/gui/scene/GuiObject.ts
7605
7805
  var GuiObject = class extends SceneObject {
7606
7806
  constructor(textureLayers, options) {
7607
7807
  super({ ...options, instanceMeshes: false, mergeMeshes: false });
@@ -7616,13 +7816,34 @@ var GuiObject = class extends SceneObject {
7616
7816
  async init() {
7617
7817
  if (this.initialized) return;
7618
7818
  try {
7819
+ let depth = 0;
7619
7820
  for (const [index, layer] of this.textureLayers.entries()) {
7821
+ const [x, y] = layer.position ?? [0, 0];
7822
+ if ("item" in layer) {
7823
+ const [width2, height2] = layer.size ?? [16, 16];
7824
+ const item = await this.createItem(layer, index);
7825
+ item.position.set(x + width2 / 2, -y - height2 / 2, 0);
7826
+ item.scale.set(width2 / 16, height2 / 16, width2 / 16);
7827
+ item.updateMatrix();
7828
+ const bounds = new Box32();
7829
+ item.iterateAllMeshes((mesh2) => {
7830
+ mesh2.geometry.computeBoundingBox();
7831
+ bounds.union(mesh2.geometry.boundingBox);
7832
+ });
7833
+ bounds.applyMatrix4(item.matrix);
7834
+ item.position.z = depth - bounds.min.z;
7835
+ depth += bounds.max.z - bounds.min.z + 0.01;
7836
+ this.bounds.expandByPoint(new Vector23(x, y));
7837
+ this.bounds.expandByPoint(new Vector23(x + width2, y + height2));
7838
+ this.bounds.expandByPoint(new Vector23(bounds.min.x, -bounds.max.y));
7839
+ this.bounds.expandByPoint(new Vector23(bounds.max.x, -bounds.min.y));
7840
+ continue;
7841
+ }
7620
7842
  const key = typeof layer.texture === "string" ? AssetKey.parse("textures", layer.texture) : layer.texture;
7621
7843
  const material = await this.loadMaterial(key);
7622
7844
  const image = material.map.image;
7623
7845
  const [cropX, cropY, cropWidth, cropHeight] = layer.crop ?? [0, 0, image.width, image.height];
7624
7846
  const [width, height] = layer.size ?? [cropWidth, cropHeight];
7625
- const [x, y] = layer.position ?? [0, 0];
7626
7847
  const geometry = new PlaneGeometry2(width, height);
7627
7848
  this.geometries.add(geometry);
7628
7849
  const uv = geometry.getAttribute("uv");
@@ -7633,14 +7854,16 @@ var GuiObject = class extends SceneObject {
7633
7854
  1 - (cropY + (1 - uv.getY(i)) * cropHeight) / image.height
7634
7855
  );
7635
7856
  }
7636
- const mesh = new Mesh6(geometry, material);
7857
+ const mesh = new Mesh7(geometry, material);
7637
7858
  mesh.name = `mesh:${layer.name ?? index}`;
7638
- mesh.position.set(x + width / 2, -y - height / 2, 0);
7859
+ mesh.position.set(x + width / 2, -y - height / 2, depth);
7639
7860
  mesh.renderOrder = index;
7640
7861
  this.add(mesh);
7641
7862
  this.bounds.expandByPoint(new Vector23(x, y));
7642
7863
  this.bounds.expandByPoint(new Vector23(x + width, y + height));
7864
+ depth += 0.01;
7643
7865
  }
7866
+ for (const child of this.children) child.position.z -= depth - 0.01;
7644
7867
  this.initialized = true;
7645
7868
  this.notifyDirty();
7646
7869
  } catch (error) {
@@ -7648,6 +7871,32 @@ var GuiObject = class extends SceneObject {
7648
7871
  throw error;
7649
7872
  }
7650
7873
  }
7874
+ async createItem(layer, index) {
7875
+ const key = typeof layer.item === "string" ? AssetKey.parse("models", layer.item) : layer.item;
7876
+ const model = await Models.getMerged(key);
7877
+ if (!model) throw new Error(`Could not load GUI item ${key.toNamespacedString()}`);
7878
+ const item = new ModelObject(model, {
7879
+ displayPosition: "gui" /* GUI */,
7880
+ tints: layer.tints,
7881
+ instanceMeshes: false,
7882
+ mergeMeshes: true
7883
+ });
7884
+ item.name = `group:${layer.name ?? index}`;
7885
+ this.add(item);
7886
+ await item.init();
7887
+ item.iterateAllMeshes((mesh) => {
7888
+ this.geometries.add(mesh.geometry);
7889
+ mesh.name = `mesh:${layer.name ?? index}`;
7890
+ mesh.renderOrder = index;
7891
+ for (const material of Array.isArray(mesh.material) ? mesh.material : [mesh.material]) {
7892
+ material.transparent = true;
7893
+ if (model.gui_light === "front" /* FRONT */ && material.uniforms?.SHADE) {
7894
+ material.uniforms.SHADE.value = false;
7895
+ }
7896
+ }
7897
+ });
7898
+ return item;
7899
+ }
7651
7900
  async loadMaterial(key) {
7652
7901
  const assetKey = key.serialize();
7653
7902
  const materialKey = `gui:${assetKey}`;
@@ -7691,7 +7940,7 @@ init_util();
7691
7940
  import { Raycaster, Vector2 as Vector24 } from "three";
7692
7941
  init_log();
7693
7942
  init_three();
7694
- var p7 = prefix("SceneInspector");
7943
+ var p8 = prefix("SceneInspector");
7695
7944
  var help = "<span>Ctrl/Cmd+Click to Select<br/></span><br/>";
7696
7945
  var SceneInspector = class {
7697
7946
  constructor(renderer) {
@@ -7785,7 +8034,7 @@ var SceneInspector = class {
7785
8034
  }
7786
8035
  selectObject(targetObject, targetIntersection, instance = this.getIntersectionInstance(targetIntersection)) {
7787
8036
  this.selectedObject = targetObject;
7788
- console.log(p7, "selected", targetObject);
8037
+ console.log(p8, "selected", targetObject);
7789
8038
  this.redraw(targetObject, targetIntersection, instance);
7790
8039
  }
7791
8040
  redraw(targetObject, targetIntersection, instance) {
@@ -8044,7 +8293,7 @@ var SceneStatsDisplay = class {
8044
8293
 
8045
8294
  // src/instance/InstanceManager.ts
8046
8295
  init_log();
8047
- var p8 = prefix("InstanceManager");
8296
+ var p9 = prefix("InstanceManager");
8048
8297
  var InstanceManager = class {
8049
8298
  constructor() {
8050
8299
  this.isInstanceManager = true;
@@ -8052,7 +8301,7 @@ var InstanceManager = class {
8052
8301
  }
8053
8302
  async get(key) {
8054
8303
  if (key in this.instanceCache) {
8055
- console.debug(p8, "key in cache", key);
8304
+ console.debug(p9, "key in cache", key);
8056
8305
  return (await this.instanceCache[key]).nextInstance();
8057
8306
  }
8058
8307
  return void 0;
@@ -8061,7 +8310,7 @@ var InstanceManager = class {
8061
8310
  if (key in this.instanceCache) {
8062
8311
  return await this.get(key);
8063
8312
  }
8064
- console.debug(p8, "key not in cache", key);
8313
+ console.debug(p9, "key not in cache", key);
8065
8314
  const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
8066
8315
  this.instanceCache[key] = pending;
8067
8316
  try {
@@ -8095,13 +8344,6 @@ function isInstanceable(obj) {
8095
8344
  init_DisplayPosition();
8096
8345
  init_DisplayTransforms();
8097
8346
 
8098
- // src/model/GuiLight.ts
8099
- var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
8100
- GuiLight2["FRONT"] = "front";
8101
- GuiLight2["SIDE"] = "side";
8102
- return GuiLight2;
8103
- })(GuiLight || {});
8104
-
8105
8347
  // src/model/Model.ts
8106
8348
  var ITEM_GENERATED = "item/generated";
8107
8349
  var BUILTIN_GENERATED = "builtin/generated";
@@ -8126,7 +8368,7 @@ init_ModelMerger();
8126
8368
  init_BlockStates();
8127
8369
  init_MineRenderError();
8128
8370
  init_util();
8129
- import { Euler as Euler5 } from "three";
8371
+ import { Euler as Euler7 } from "three";
8130
8372
  function matchesCondition(condition, state) {
8131
8373
  return Object.entries(condition).every(([key, value]) => {
8132
8374
  if (Array.isArray(value)) {
@@ -8201,7 +8443,7 @@ var BlockStateResolver = class {
8201
8443
  return variants[variants.length - 1];
8202
8444
  }
8203
8445
  static rotation(variant) {
8204
- const rotation = new Euler5();
8446
+ const rotation = new Euler7();
8205
8447
  if (typeof variant.x !== "undefined") {
8206
8448
  rotation.x = toRadians(clampRotationDegrees(variant.x));
8207
8449
  }
@@ -8311,7 +8553,7 @@ var import_ts_deepmerge6 = __toESM(require_dist());
8311
8553
  init_MineRenderError();
8312
8554
  init_InstanceReference();
8313
8555
  init_AssetKey();
8314
- import { Euler as Euler7, Matrix4 as Matrix47, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
8556
+ import { Euler as Euler8, Matrix4 as Matrix48, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
8315
8557
  init_ModelCulling();
8316
8558
  init_FluidGeometry();
8317
8559
  var BlockObject = class _BlockObject extends SceneObject {
@@ -8382,7 +8624,7 @@ var BlockObject = class _BlockObject extends SceneObject {
8382
8624
  const scale = new Vector311();
8383
8625
  this.getModelMatrix(model).decompose(position, rotation, scale);
8384
8626
  if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new Vector311(1, 1, 1)) > 1e-10) return 0;
8385
- return ModelCulling.toLocalMask(worldMask, new Euler7().setFromQuaternion(rotation));
8627
+ return ModelCulling.toLocalMask(worldMask, new Euler8().setFromQuaternion(rotation));
8386
8628
  }
8387
8629
  async setCullMask(worldMask) {
8388
8630
  worldMask &= 63;
@@ -8444,7 +8686,7 @@ var BlockObject = class _BlockObject extends SceneObject {
8444
8686
  () => new FluidModelObject2(kind, surface.sample, this.blockState.key, this.options)
8445
8687
  );
8446
8688
  const previous = this._fluidModel;
8447
- const matrix = previous ? this.getModelMatrix(previous) : new Matrix47().makeTranslation(...this.position.toArray());
8689
+ const matrix = previous ? this.getModelMatrix(previous) : new Matrix48().makeTranslation(...this.position.toArray());
8448
8690
  if (isInstanceReference(replacement)) replacement.setMatrix(matrix);
8449
8691
  else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
8450
8692
  this._models = this._models.filter((model) => model !== previous);
@@ -8575,7 +8817,7 @@ var BlockObject = class _BlockObject extends SceneObject {
8575
8817
  setPositionRotationScaleAt(index, position, rotation, scale) {
8576
8818
  super.setPositionRotationScaleAt(index, position, rotation, scale);
8577
8819
  }
8578
- getMatrixAt(index, matrix = new Matrix47()) {
8820
+ getMatrixAt(index, matrix = new Matrix48()) {
8579
8821
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
8580
8822
  const child = this._models[0];
8581
8823
  if (child && isModelObject(child)) {
@@ -13137,7 +13379,7 @@ init_CubeFace();
13137
13379
  init_AssetKey();
13138
13380
  init_Models();
13139
13381
  init_CubeFace();
13140
- import { Matrix4 as Matrix48, Vector3 as Vector314 } from "three";
13382
+ import { Matrix4 as Matrix49, Vector3 as Vector314 } from "three";
13141
13383
  init_ModelCulling();
13142
13384
  init_ModelObject();
13143
13385
  init_UVMapper();
@@ -13200,7 +13442,7 @@ var SectionModels = class {
13200
13442
  });
13201
13443
  await object.init();
13202
13444
  const geometry = object.children[0].geometry;
13203
- geometry.applyMatrix4(new Matrix48().makeRotationFromEuler(rotation));
13445
+ geometry.applyMatrix4(new Matrix49().makeRotationFromEuler(rotation));
13204
13446
  object.clear();
13205
13447
  const cullFaces = CUBE_FACES.map((face) => {
13206
13448
  const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
@@ -13450,7 +13692,7 @@ var MineRenderWorld = class {
13450
13692
  // src/world/SectionMesh.ts
13451
13693
  init_CanvasCompat();
13452
13694
  init_Materials();
13453
- import { BufferGeometry as BufferGeometry5, Float32BufferAttribute as Float32BufferAttribute6, Group, Mesh as Mesh10 } from "three";
13695
+ import { BufferGeometry as BufferGeometry6, Float32BufferAttribute as Float32BufferAttribute6, Group, Mesh as Mesh10 } from "three";
13454
13696
  var SectionMesh = class _SectionMesh extends Group {
13455
13697
  constructor() {
13456
13698
  super(...arguments);
@@ -13524,7 +13766,7 @@ var SectionMesh = class _SectionMesh extends Group {
13524
13766
  for (let corner = 0; corner < 6; corner++) indices.push(start + sourceIndices.getX(face * 6 + corner) - face * 4);
13525
13767
  }
13526
13768
  }
13527
- const geometry = new BufferGeometry5();
13769
+ const geometry = new BufferGeometry6();
13528
13770
  geometry.setAttribute("position", new Float32BufferAttribute6(positions, 3));
13529
13771
  geometry.setAttribute("normal", new Float32BufferAttribute6(normals, 3));
13530
13772
  geometry.setAttribute("uv", new Float32BufferAttribute6(uvs, 2));