minerender 2.1.0-alpha.78 → 2.1.0-alpha.79

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.
@@ -524,6 +524,8 @@ interface ItemModel extends Model {
524
524
  gui_light?: GuiLight;
525
525
  special?: SpecialItemRenderer;
526
526
  tints?: ItemTintSource[];
527
+ /** Ordered composite children, each with its own textures, display pose, and tint sources. */
528
+ parts?: ItemModel[];
527
529
  }
528
530
  /** An sRGB packed `0xRRGGBB` value or an RGB triple with components from 0 to 1. */
529
531
  type ItemTintColor = number | TripleArray;
@@ -1187,26 +1189,46 @@ declare class Fonts {
1187
1189
  private static bitmap;
1188
1190
  }
1189
1191
 
1192
+ /** Caller-supplied item-preview state passed to {@link Models.getMerged}. */
1193
+ interface ItemModelContext {
1194
+ /** Context used by display-context selectors, overriding `properties`. Defaults to GUI. */
1195
+ displayContext?: DisplayPosition | "none";
1196
+ /** Explicit property overrides. Nodes with the same ID share one override, regardless of their parameters. */
1197
+ properties?: Record<string, boolean | string | number>;
1198
+ /** Supplied component JSON by ID. Item-registry defaults are not added; component selectors compare structural JSON values. */
1199
+ components?: Record<string, unknown>;
1200
+ /** Stack count, as a nonnegative integer. Defaults to 1; absent `max_stack_size` also defaults to 1. */
1201
+ count?: number;
1202
+ /** Item-model keys by reference-node ID, such as `minecraft:bundle/selected_item`. Unset references draw nothing. */
1203
+ itemReferences?: Record<string, AssetKey>;
1204
+ }
1190
1205
  /** Loads and caches Java block/item models, including inherited geometry and textures. */
1191
1206
  declare class Models {
1192
1207
  private static _persistentCache;
1193
1208
  private static get PERSISTENT_CACHE();
1194
1209
  /** Lists item filenames from the asset source's `_list.json`, with a legacy model-directory fallback. */
1195
1210
  static getItemList(): Promise<string[]>;
1196
- static loadAndMerge(key: AssetKey): Promise<Maybe<Model>>;
1211
+ static loadAndMerge(key: AssetKey, context?: ItemModelContext): Promise<Maybe<Model>>;
1197
1212
  private static getItemModel;
1198
- private static defaultItemModel;
1213
+ private static contextIdentifier;
1214
+ private static snapshotContext;
1215
+ private static contextKey;
1216
+ private static snapshotJson;
1217
+ private static propertyValue;
1218
+ private static selectItemModel;
1199
1219
  /** Loads one model file without resolving its parents. Returns `undefined` when the file is missing. */
1200
1220
  static getRaw(key: AssetKey): Promise<Maybe<Model>>;
1201
1221
  /**
1202
1222
  * Loads a model and resolves its parent chain. Returns `undefined` when the model is missing.
1203
- * Item keys use GUI context, false conditions, and zero numeric properties.
1223
+ * Item keys default to GUI context and a stack count of 1. Unresolved conditions are false and numeric properties are zero.
1224
+ * Pass `context` to supply component values, property overrides, and item references for a preview.
1225
+ * Composite items retain independently merged children in `ItemModel.parts`.
1204
1226
  *
1205
1227
  * @param key - Model key, for example `AssetKey.parse("models", "minecraft:item/diamond_sword")`.
1206
1228
  */
1207
- static getMerged(key: AssetKey): Promise<Maybe<Model>>;
1229
+ static getMerged(key: AssetKey, context?: ItemModelContext): Promise<Maybe<Model>>;
1208
1230
  /** Alias for {@link getMerged}. */
1209
- static get(key: AssetKey): Promise<Maybe<Model>>;
1231
+ static get(key: AssetKey, context?: ItemModelContext): Promise<Maybe<Model>>;
1210
1232
  /** Clears persisted models. Use {@link Caching.clear} to also discard in-memory assets. */
1211
1233
  static clearCache(): Promise<void>;
1212
1234
  }
@@ -1363,6 +1385,7 @@ declare class ModelObject extends SceneObject {
1363
1385
  private atlasTexture?;
1364
1386
  private unsubscribeAtlas?;
1365
1387
  private readonly specialMaterials;
1388
+ private readonly geometries;
1366
1389
  blockParent: Maybe<BlockObject>;
1367
1390
  private meshesCreated;
1368
1391
  constructor(originalModel: Model, options?: Partial<ModelObjectOptions>);
@@ -3213,4 +3236,4 @@ declare class NodeCache extends PersistentCache<LocalStorage> {
3213
3236
  forEach<T>(callback: (v: T, k: string) => void): Promise<void>;
3214
3237
  }
3215
3238
 
3216
- export { AXES, type AnimationFrame, type AnimationMeta, type AnimatorFunction, type AnvilChunk, AnvilParser, type AnvilRegion, ArchiveAssetSource, type ArchiveAssetSourceOptions, type ArchiveEntry, type ArchiveProxy, AssetKey, AssetLoadError, AssetLoader, AssetParser, AssetSource, type AssetType, Assets, Axis, BUILTIN_ENTITY, BUILTIN_GENERATED, BasicAssetKey, type BasicMinecraftAsset, BatchedExecutor, type BedrockBone, type BedrockCube, type BedrockEntityDescription, type BedrockEntityFile, type BedrockGeometry, type BedrockGeometryFile, type BitmapFont, type BitmapGlyph, type Block, BlockEntities, type BlockEntityEntry, type BlockEntityIndex, type BlockEntityPart, type BlockEntityRotation, type BlockFluidState, type BlockInfo, type BlockModel, type BlockModelTextures, BlockObject, type BlockObjectOptions, type BlockState, type BlockStateMultipart, type BlockStateProperties, type BlockStateProperty, type BlockStatePropertyDefaults, type BlockStatePropertyValue, BlockStateResolver, type BlockStateVariant, type BlockStateVariants, BlockStates, BlockTints, type BoxGeometryKey, BrowserArchiveProxy, CUBE_FACES, CUBE_FACE_OFFSETS, type CacheKey, Caching, type CameraOptions, CanvasImage, type CapeLayout, Chunk, ChunkData, Colormaps, type CompatCanvas, type CompatImage, type ComposerOptions, type ControlsOptions, CubeFace, CubeFaceIndex, DEFAULT_ELEMENTS, DEFAULT_NAMESPACE, DEFAULT_ROOT, DEFAULT_UV, DISPLAY_POSITIONS, type DebugOptions, type DeepPartial, DefaultBlockStates, DisplayPosition, DisplayTransforms, type Disposable, type DoubleArray, ENTITY_ANIMATION_CHANNELS, type ElementFace, type ElementRotation, Entities, type EntityAnimation, type EntityAnimationBone, type EntityAnimationChannel, type EntityAnimationFile, type EntityAnimationKeyframe, type EntityAnimationOptions, EntityAnimationPlayer, type EntityAnimationPose, type EntityLayer, type EntityModel, type EntityModelCube, type EntityModelFile, type EntityModelLayer, type EntityModelOptions, type EntityModelPart, type EntityModelPass, EntityObject, type EntityObjectOptions, type EntityRenderMode, type EntityTransformOp, Env, type EnvProvider, type ExtractableImageData, type FluidKind, FluidModelObject, type FluidSample, type FluidSampler, Fonts, type FrameCallback, type FromTo, GUI_CONTAINER_LAYOUTS, Geometries, type GuiBookButtonState, type GuiBookOptions, type GuiBossBarColor, type GuiBossBarOptions, type GuiContainerType, GuiHelper, type GuiItemLayer, type GuiLayer, GuiLight, GuiObject, type GuiObjectOptions, type GuiRecipe, type GuiRecipeIngredient, type GuiRecipeOptions, type GuiSpriteScaling, type GuiText, type GuiTextLayer, type GuiTextLayout, type GuiTextOptions, type GuiTextRun, type GuiTextStyle, type GuiTextureLayer, type GuiTooltipOptions, HostedAssetSource, type IModelTextures, ITEM_GENERATED, type ImageInfo, ImageLoader, type ImageSizeInfo, InstanceManager, InstanceReference, type Instanceable, type ItemModel, type ItemModelTextures, type ItemTintColor, type ItemTintSource, ItemTints, type ListAsset, type LoadedSceneDocument, type LoadedSceneObject, MapControls, type MaterialKey, Materials, type Maybe, type MeshKey, Meshes, MineRenderError, MineRenderScene, type MineRenderSceneOptions, MineRenderWorld, type MineRenderWorldOptions, type MinecraftAsset, MinecraftCubeTexture, MinecraftFaceUV, type MinecraftTextureMeta, type Model, ModelCulling, type ModelDisplay, type ModelElement, type ModelFaces, ModelGenerator, ModelMerger, ModelObject, type ModelObjectOptions, ModelTextures, Models, type MultiBlockBlock, type MultiBlockEntity, type MultiBlockStructure, type MultipartCondition, type NBTAsset, NBTHelper, NodeCache, NodeEnv, OrbitControls, type PackFormat, PackFormats, PackMetadata, PersistentCache, type PositionedGuiGlyph, type QuadArray, type RawImageKey, type RenderOptions, Renderer, type RendererFrame, type RendererOptions, type RequestConfig, RequestError, type RequestResponse, Requests, type ResolvedBlockEntity, type ResponseParser, SKIN_PARTS, type SceneBlockDefinition, type SceneDocument, SceneDocumentLoader, type SceneEntityDefinition, SceneExporter, type SceneGLTFExportOptions, type SceneGuiDefinition, type SceneGuiLayer, SceneInspector, type SceneModelDefinition, SceneObject, type SceneObjectDefinition, type SceneObjectDefinitionBase, type SceneObjectOptions, type SceneSkinDefinition, type SceneSkinPosePart, SceneStats, SceneStatsDisplay, SchematicParser, type SchematicParserOptions, SectionMesh, type SectionMeshEntry, type SectionMeshTemplate, SectionModels, type Serializable, type SkinGeometries, SkinImage, SkinObject, type SkinObjectOptions, SkinPart, type SkinTexture, type SkinTextureCoordinates, SkinTextures, Skins, type SpecialItemPart, type SpecialItemRenderer, SpecialItems, type StructureNBT, StructureParser, type TextureAsset, TextureAtlas, type TextureKey, TextureLoader, Textures, Ticker, type TickerFunction, TintColors, type Transformable, type TripleArray, UVMapper, WrappedImage, addBox3WireframeToObject, addWireframeToMesh, addWireframeToObject, applyElementRotation, applyGenericRotation, axisToVec3, base64decode, base64encode, capeTextureSizes, captureException, changeEvent, clampRotationDegrees, classicSkinGeometries, classicSkinTextureCoordinates, computeMorphedAttributes, createCanvas, createFluidGeometry, createGuiTextGeometry, createGuiTextureGeometry, createImage, entityAnimationTime, estimateBytesUsed, getBlockFluidState, getFluidKind, interleaveAttributes, isAssetKey, isBasicAssetKey, isBlockObject, isDisposable, isDoubleArray, isEntityObject, isGuiObject, isInstanceManager, isInstanceReference, isInstanceable, isInstancedMesh, isMesh, isMineRenderScene, isModelObject, isObject3D, isOrthographicCamera, isPerspectiveCamera, isQuadArray, isSceneObject, isTransformable, isTripleArray, isVector3, layoutGuiText, md5, mergeBufferAttributes, mergeBufferGeometries, mergeVertices, parseSceneDocument, prefix, registerNodeEnv, sampleEntityAnimation, sampleEntityKeyframes, sampleFluid, serializeBoxGeometryKey, serializeImageKey, serializeMaterialKey, serializeMeshKey, serializeTextureKey, sha1, sha256, sha512, shutdown, sleep, slimSkinGeometries, slimSkinTextureCoordinates, timingEnd, timingStart, toDegrees, toRadians, toTrianglesDrawMode, trimCanvas };
3239
+ export { AXES, type AnimationFrame, type AnimationMeta, type AnimatorFunction, type AnvilChunk, AnvilParser, type AnvilRegion, ArchiveAssetSource, type ArchiveAssetSourceOptions, type ArchiveEntry, type ArchiveProxy, AssetKey, AssetLoadError, AssetLoader, AssetParser, AssetSource, type AssetType, Assets, Axis, BUILTIN_ENTITY, BUILTIN_GENERATED, BasicAssetKey, type BasicMinecraftAsset, BatchedExecutor, type BedrockBone, type BedrockCube, type BedrockEntityDescription, type BedrockEntityFile, type BedrockGeometry, type BedrockGeometryFile, type BitmapFont, type BitmapGlyph, type Block, BlockEntities, type BlockEntityEntry, type BlockEntityIndex, type BlockEntityPart, type BlockEntityRotation, type BlockFluidState, type BlockInfo, type BlockModel, type BlockModelTextures, BlockObject, type BlockObjectOptions, type BlockState, type BlockStateMultipart, type BlockStateProperties, type BlockStateProperty, type BlockStatePropertyDefaults, type BlockStatePropertyValue, BlockStateResolver, type BlockStateVariant, type BlockStateVariants, BlockStates, BlockTints, type BoxGeometryKey, BrowserArchiveProxy, CUBE_FACES, CUBE_FACE_OFFSETS, type CacheKey, Caching, type CameraOptions, CanvasImage, type CapeLayout, Chunk, ChunkData, Colormaps, type CompatCanvas, type CompatImage, type ComposerOptions, type ControlsOptions, CubeFace, CubeFaceIndex, DEFAULT_ELEMENTS, DEFAULT_NAMESPACE, DEFAULT_ROOT, DEFAULT_UV, DISPLAY_POSITIONS, type DebugOptions, type DeepPartial, DefaultBlockStates, DisplayPosition, DisplayTransforms, type Disposable, type DoubleArray, ENTITY_ANIMATION_CHANNELS, type ElementFace, type ElementRotation, Entities, type EntityAnimation, type EntityAnimationBone, type EntityAnimationChannel, type EntityAnimationFile, type EntityAnimationKeyframe, type EntityAnimationOptions, EntityAnimationPlayer, type EntityAnimationPose, type EntityLayer, type EntityModel, type EntityModelCube, type EntityModelFile, type EntityModelLayer, type EntityModelOptions, type EntityModelPart, type EntityModelPass, EntityObject, type EntityObjectOptions, type EntityRenderMode, type EntityTransformOp, Env, type EnvProvider, type ExtractableImageData, type FluidKind, FluidModelObject, type FluidSample, type FluidSampler, Fonts, type FrameCallback, type FromTo, GUI_CONTAINER_LAYOUTS, Geometries, type GuiBookButtonState, type GuiBookOptions, type GuiBossBarColor, type GuiBossBarOptions, type GuiContainerType, GuiHelper, type GuiItemLayer, type GuiLayer, GuiLight, GuiObject, type GuiObjectOptions, type GuiRecipe, type GuiRecipeIngredient, type GuiRecipeOptions, type GuiSpriteScaling, type GuiText, type GuiTextLayer, type GuiTextLayout, type GuiTextOptions, type GuiTextRun, type GuiTextStyle, type GuiTextureLayer, type GuiTooltipOptions, HostedAssetSource, type IModelTextures, ITEM_GENERATED, type ImageInfo, ImageLoader, type ImageSizeInfo, InstanceManager, InstanceReference, type Instanceable, type ItemModel, type ItemModelContext, type ItemModelTextures, type ItemTintColor, type ItemTintSource, ItemTints, type ListAsset, type LoadedSceneDocument, type LoadedSceneObject, MapControls, type MaterialKey, Materials, type Maybe, type MeshKey, Meshes, MineRenderError, MineRenderScene, type MineRenderSceneOptions, MineRenderWorld, type MineRenderWorldOptions, type MinecraftAsset, MinecraftCubeTexture, MinecraftFaceUV, type MinecraftTextureMeta, type Model, ModelCulling, type ModelDisplay, type ModelElement, type ModelFaces, ModelGenerator, ModelMerger, ModelObject, type ModelObjectOptions, ModelTextures, Models, type MultiBlockBlock, type MultiBlockEntity, type MultiBlockStructure, type MultipartCondition, type NBTAsset, NBTHelper, NodeCache, NodeEnv, OrbitControls, type PackFormat, PackFormats, PackMetadata, PersistentCache, type PositionedGuiGlyph, type QuadArray, type RawImageKey, type RenderOptions, Renderer, type RendererFrame, type RendererOptions, type RequestConfig, RequestError, type RequestResponse, Requests, type ResolvedBlockEntity, type ResponseParser, SKIN_PARTS, type SceneBlockDefinition, type SceneDocument, SceneDocumentLoader, type SceneEntityDefinition, SceneExporter, type SceneGLTFExportOptions, type SceneGuiDefinition, type SceneGuiLayer, SceneInspector, type SceneModelDefinition, SceneObject, type SceneObjectDefinition, type SceneObjectDefinitionBase, type SceneObjectOptions, type SceneSkinDefinition, type SceneSkinPosePart, SceneStats, SceneStatsDisplay, SchematicParser, type SchematicParserOptions, SectionMesh, type SectionMeshEntry, type SectionMeshTemplate, SectionModels, type Serializable, type SkinGeometries, SkinImage, SkinObject, type SkinObjectOptions, SkinPart, type SkinTexture, type SkinTextureCoordinates, SkinTextures, Skins, type SpecialItemPart, type SpecialItemRenderer, SpecialItems, type StructureNBT, StructureParser, type TextureAsset, TextureAtlas, type TextureKey, TextureLoader, Textures, Ticker, type TickerFunction, TintColors, type Transformable, type TripleArray, UVMapper, WrappedImage, addBox3WireframeToObject, addWireframeToMesh, addWireframeToObject, applyElementRotation, applyGenericRotation, axisToVec3, base64decode, base64encode, capeTextureSizes, captureException, changeEvent, clampRotationDegrees, classicSkinGeometries, classicSkinTextureCoordinates, computeMorphedAttributes, createCanvas, createFluidGeometry, createGuiTextGeometry, createGuiTextureGeometry, createImage, entityAnimationTime, estimateBytesUsed, getBlockFluidState, getFluidKind, interleaveAttributes, isAssetKey, isBasicAssetKey, isBlockObject, isDisposable, isDoubleArray, isEntityObject, isGuiObject, isInstanceManager, isInstanceReference, isInstanceable, isInstancedMesh, isMesh, isMineRenderScene, isModelObject, isObject3D, isOrthographicCamera, isPerspectiveCamera, isQuadArray, isSceneObject, isTransformable, isTripleArray, isVector3, layoutGuiText, md5, mergeBufferAttributes, mergeBufferGeometries, mergeVertices, parseSceneDocument, prefix, registerNodeEnv, sampleEntityAnimation, sampleEntityKeyframes, sampleFluid, serializeBoxGeometryKey, serializeImageKey, serializeMaterialKey, serializeMeshKey, serializeTextureKey, sha1, sha256, sha512, shutdown, sleep, slimSkinGeometries, slimSkinTextureCoordinates, timingEnd, timingStart, toDegrees, toRadians, toTrianglesDrawMode, trimCanvas };
@@ -524,6 +524,8 @@ interface ItemModel extends Model {
524
524
  gui_light?: GuiLight;
525
525
  special?: SpecialItemRenderer;
526
526
  tints?: ItemTintSource[];
527
+ /** Ordered composite children, each with its own textures, display pose, and tint sources. */
528
+ parts?: ItemModel[];
527
529
  }
528
530
  /** An sRGB packed `0xRRGGBB` value or an RGB triple with components from 0 to 1. */
529
531
  type ItemTintColor = number | TripleArray;
@@ -1187,26 +1189,46 @@ declare class Fonts {
1187
1189
  private static bitmap;
1188
1190
  }
1189
1191
 
1192
+ /** Caller-supplied item-preview state passed to {@link Models.getMerged}. */
1193
+ interface ItemModelContext {
1194
+ /** Context used by display-context selectors, overriding `properties`. Defaults to GUI. */
1195
+ displayContext?: DisplayPosition | "none";
1196
+ /** Explicit property overrides. Nodes with the same ID share one override, regardless of their parameters. */
1197
+ properties?: Record<string, boolean | string | number>;
1198
+ /** Supplied component JSON by ID. Item-registry defaults are not added; component selectors compare structural JSON values. */
1199
+ components?: Record<string, unknown>;
1200
+ /** Stack count, as a nonnegative integer. Defaults to 1; absent `max_stack_size` also defaults to 1. */
1201
+ count?: number;
1202
+ /** Item-model keys by reference-node ID, such as `minecraft:bundle/selected_item`. Unset references draw nothing. */
1203
+ itemReferences?: Record<string, AssetKey>;
1204
+ }
1190
1205
  /** Loads and caches Java block/item models, including inherited geometry and textures. */
1191
1206
  declare class Models {
1192
1207
  private static _persistentCache;
1193
1208
  private static get PERSISTENT_CACHE();
1194
1209
  /** Lists item filenames from the asset source's `_list.json`, with a legacy model-directory fallback. */
1195
1210
  static getItemList(): Promise<string[]>;
1196
- static loadAndMerge(key: AssetKey): Promise<Maybe<Model>>;
1211
+ static loadAndMerge(key: AssetKey, context?: ItemModelContext): Promise<Maybe<Model>>;
1197
1212
  private static getItemModel;
1198
- private static defaultItemModel;
1213
+ private static contextIdentifier;
1214
+ private static snapshotContext;
1215
+ private static contextKey;
1216
+ private static snapshotJson;
1217
+ private static propertyValue;
1218
+ private static selectItemModel;
1199
1219
  /** Loads one model file without resolving its parents. Returns `undefined` when the file is missing. */
1200
1220
  static getRaw(key: AssetKey): Promise<Maybe<Model>>;
1201
1221
  /**
1202
1222
  * Loads a model and resolves its parent chain. Returns `undefined` when the model is missing.
1203
- * Item keys use GUI context, false conditions, and zero numeric properties.
1223
+ * Item keys default to GUI context and a stack count of 1. Unresolved conditions are false and numeric properties are zero.
1224
+ * Pass `context` to supply component values, property overrides, and item references for a preview.
1225
+ * Composite items retain independently merged children in `ItemModel.parts`.
1204
1226
  *
1205
1227
  * @param key - Model key, for example `AssetKey.parse("models", "minecraft:item/diamond_sword")`.
1206
1228
  */
1207
- static getMerged(key: AssetKey): Promise<Maybe<Model>>;
1229
+ static getMerged(key: AssetKey, context?: ItemModelContext): Promise<Maybe<Model>>;
1208
1230
  /** Alias for {@link getMerged}. */
1209
- static get(key: AssetKey): Promise<Maybe<Model>>;
1231
+ static get(key: AssetKey, context?: ItemModelContext): Promise<Maybe<Model>>;
1210
1232
  /** Clears persisted models. Use {@link Caching.clear} to also discard in-memory assets. */
1211
1233
  static clearCache(): Promise<void>;
1212
1234
  }
@@ -1363,6 +1385,7 @@ declare class ModelObject extends SceneObject {
1363
1385
  private atlasTexture?;
1364
1386
  private unsubscribeAtlas?;
1365
1387
  private readonly specialMaterials;
1388
+ private readonly geometries;
1366
1389
  blockParent: Maybe<BlockObject>;
1367
1390
  private meshesCreated;
1368
1391
  constructor(originalModel: Model, options?: Partial<ModelObjectOptions>);
@@ -3213,4 +3236,4 @@ declare class NodeCache extends PersistentCache<LocalStorage> {
3213
3236
  forEach<T>(callback: (v: T, k: string) => void): Promise<void>;
3214
3237
  }
3215
3238
 
3216
- export { AXES, type AnimationFrame, type AnimationMeta, type AnimatorFunction, type AnvilChunk, AnvilParser, type AnvilRegion, ArchiveAssetSource, type ArchiveAssetSourceOptions, type ArchiveEntry, type ArchiveProxy, AssetKey, AssetLoadError, AssetLoader, AssetParser, AssetSource, type AssetType, Assets, Axis, BUILTIN_ENTITY, BUILTIN_GENERATED, BasicAssetKey, type BasicMinecraftAsset, BatchedExecutor, type BedrockBone, type BedrockCube, type BedrockEntityDescription, type BedrockEntityFile, type BedrockGeometry, type BedrockGeometryFile, type BitmapFont, type BitmapGlyph, type Block, BlockEntities, type BlockEntityEntry, type BlockEntityIndex, type BlockEntityPart, type BlockEntityRotation, type BlockFluidState, type BlockInfo, type BlockModel, type BlockModelTextures, BlockObject, type BlockObjectOptions, type BlockState, type BlockStateMultipart, type BlockStateProperties, type BlockStateProperty, type BlockStatePropertyDefaults, type BlockStatePropertyValue, BlockStateResolver, type BlockStateVariant, type BlockStateVariants, BlockStates, BlockTints, type BoxGeometryKey, BrowserArchiveProxy, CUBE_FACES, CUBE_FACE_OFFSETS, type CacheKey, Caching, type CameraOptions, CanvasImage, type CapeLayout, Chunk, ChunkData, Colormaps, type CompatCanvas, type CompatImage, type ComposerOptions, type ControlsOptions, CubeFace, CubeFaceIndex, DEFAULT_ELEMENTS, DEFAULT_NAMESPACE, DEFAULT_ROOT, DEFAULT_UV, DISPLAY_POSITIONS, type DebugOptions, type DeepPartial, DefaultBlockStates, DisplayPosition, DisplayTransforms, type Disposable, type DoubleArray, ENTITY_ANIMATION_CHANNELS, type ElementFace, type ElementRotation, Entities, type EntityAnimation, type EntityAnimationBone, type EntityAnimationChannel, type EntityAnimationFile, type EntityAnimationKeyframe, type EntityAnimationOptions, EntityAnimationPlayer, type EntityAnimationPose, type EntityLayer, type EntityModel, type EntityModelCube, type EntityModelFile, type EntityModelLayer, type EntityModelOptions, type EntityModelPart, type EntityModelPass, EntityObject, type EntityObjectOptions, type EntityRenderMode, type EntityTransformOp, Env, type EnvProvider, type ExtractableImageData, type FluidKind, FluidModelObject, type FluidSample, type FluidSampler, Fonts, type FrameCallback, type FromTo, GUI_CONTAINER_LAYOUTS, Geometries, type GuiBookButtonState, type GuiBookOptions, type GuiBossBarColor, type GuiBossBarOptions, type GuiContainerType, GuiHelper, type GuiItemLayer, type GuiLayer, GuiLight, GuiObject, type GuiObjectOptions, type GuiRecipe, type GuiRecipeIngredient, type GuiRecipeOptions, type GuiSpriteScaling, type GuiText, type GuiTextLayer, type GuiTextLayout, type GuiTextOptions, type GuiTextRun, type GuiTextStyle, type GuiTextureLayer, type GuiTooltipOptions, HostedAssetSource, type IModelTextures, ITEM_GENERATED, type ImageInfo, ImageLoader, type ImageSizeInfo, InstanceManager, InstanceReference, type Instanceable, type ItemModel, type ItemModelTextures, type ItemTintColor, type ItemTintSource, ItemTints, type ListAsset, type LoadedSceneDocument, type LoadedSceneObject, MapControls, type MaterialKey, Materials, type Maybe, type MeshKey, Meshes, MineRenderError, MineRenderScene, type MineRenderSceneOptions, MineRenderWorld, type MineRenderWorldOptions, type MinecraftAsset, MinecraftCubeTexture, MinecraftFaceUV, type MinecraftTextureMeta, type Model, ModelCulling, type ModelDisplay, type ModelElement, type ModelFaces, ModelGenerator, ModelMerger, ModelObject, type ModelObjectOptions, ModelTextures, Models, type MultiBlockBlock, type MultiBlockEntity, type MultiBlockStructure, type MultipartCondition, type NBTAsset, NBTHelper, NodeCache, NodeEnv, OrbitControls, type PackFormat, PackFormats, PackMetadata, PersistentCache, type PositionedGuiGlyph, type QuadArray, type RawImageKey, type RenderOptions, Renderer, type RendererFrame, type RendererOptions, type RequestConfig, RequestError, type RequestResponse, Requests, type ResolvedBlockEntity, type ResponseParser, SKIN_PARTS, type SceneBlockDefinition, type SceneDocument, SceneDocumentLoader, type SceneEntityDefinition, SceneExporter, type SceneGLTFExportOptions, type SceneGuiDefinition, type SceneGuiLayer, SceneInspector, type SceneModelDefinition, SceneObject, type SceneObjectDefinition, type SceneObjectDefinitionBase, type SceneObjectOptions, type SceneSkinDefinition, type SceneSkinPosePart, SceneStats, SceneStatsDisplay, SchematicParser, type SchematicParserOptions, SectionMesh, type SectionMeshEntry, type SectionMeshTemplate, SectionModels, type Serializable, type SkinGeometries, SkinImage, SkinObject, type SkinObjectOptions, SkinPart, type SkinTexture, type SkinTextureCoordinates, SkinTextures, Skins, type SpecialItemPart, type SpecialItemRenderer, SpecialItems, type StructureNBT, StructureParser, type TextureAsset, TextureAtlas, type TextureKey, TextureLoader, Textures, Ticker, type TickerFunction, TintColors, type Transformable, type TripleArray, UVMapper, WrappedImage, addBox3WireframeToObject, addWireframeToMesh, addWireframeToObject, applyElementRotation, applyGenericRotation, axisToVec3, base64decode, base64encode, capeTextureSizes, captureException, changeEvent, clampRotationDegrees, classicSkinGeometries, classicSkinTextureCoordinates, computeMorphedAttributes, createCanvas, createFluidGeometry, createGuiTextGeometry, createGuiTextureGeometry, createImage, entityAnimationTime, estimateBytesUsed, getBlockFluidState, getFluidKind, interleaveAttributes, isAssetKey, isBasicAssetKey, isBlockObject, isDisposable, isDoubleArray, isEntityObject, isGuiObject, isInstanceManager, isInstanceReference, isInstanceable, isInstancedMesh, isMesh, isMineRenderScene, isModelObject, isObject3D, isOrthographicCamera, isPerspectiveCamera, isQuadArray, isSceneObject, isTransformable, isTripleArray, isVector3, layoutGuiText, md5, mergeBufferAttributes, mergeBufferGeometries, mergeVertices, parseSceneDocument, prefix, registerNodeEnv, sampleEntityAnimation, sampleEntityKeyframes, sampleFluid, serializeBoxGeometryKey, serializeImageKey, serializeMaterialKey, serializeMeshKey, serializeTextureKey, sha1, sha256, sha512, shutdown, sleep, slimSkinGeometries, slimSkinTextureCoordinates, timingEnd, timingStart, toDegrees, toRadians, toTrianglesDrawMode, trimCanvas };
3239
+ export { AXES, type AnimationFrame, type AnimationMeta, type AnimatorFunction, type AnvilChunk, AnvilParser, type AnvilRegion, ArchiveAssetSource, type ArchiveAssetSourceOptions, type ArchiveEntry, type ArchiveProxy, AssetKey, AssetLoadError, AssetLoader, AssetParser, AssetSource, type AssetType, Assets, Axis, BUILTIN_ENTITY, BUILTIN_GENERATED, BasicAssetKey, type BasicMinecraftAsset, BatchedExecutor, type BedrockBone, type BedrockCube, type BedrockEntityDescription, type BedrockEntityFile, type BedrockGeometry, type BedrockGeometryFile, type BitmapFont, type BitmapGlyph, type Block, BlockEntities, type BlockEntityEntry, type BlockEntityIndex, type BlockEntityPart, type BlockEntityRotation, type BlockFluidState, type BlockInfo, type BlockModel, type BlockModelTextures, BlockObject, type BlockObjectOptions, type BlockState, type BlockStateMultipart, type BlockStateProperties, type BlockStateProperty, type BlockStatePropertyDefaults, type BlockStatePropertyValue, BlockStateResolver, type BlockStateVariant, type BlockStateVariants, BlockStates, BlockTints, type BoxGeometryKey, BrowserArchiveProxy, CUBE_FACES, CUBE_FACE_OFFSETS, type CacheKey, Caching, type CameraOptions, CanvasImage, type CapeLayout, Chunk, ChunkData, Colormaps, type CompatCanvas, type CompatImage, type ComposerOptions, type ControlsOptions, CubeFace, CubeFaceIndex, DEFAULT_ELEMENTS, DEFAULT_NAMESPACE, DEFAULT_ROOT, DEFAULT_UV, DISPLAY_POSITIONS, type DebugOptions, type DeepPartial, DefaultBlockStates, DisplayPosition, DisplayTransforms, type Disposable, type DoubleArray, ENTITY_ANIMATION_CHANNELS, type ElementFace, type ElementRotation, Entities, type EntityAnimation, type EntityAnimationBone, type EntityAnimationChannel, type EntityAnimationFile, type EntityAnimationKeyframe, type EntityAnimationOptions, EntityAnimationPlayer, type EntityAnimationPose, type EntityLayer, type EntityModel, type EntityModelCube, type EntityModelFile, type EntityModelLayer, type EntityModelOptions, type EntityModelPart, type EntityModelPass, EntityObject, type EntityObjectOptions, type EntityRenderMode, type EntityTransformOp, Env, type EnvProvider, type ExtractableImageData, type FluidKind, FluidModelObject, type FluidSample, type FluidSampler, Fonts, type FrameCallback, type FromTo, GUI_CONTAINER_LAYOUTS, Geometries, type GuiBookButtonState, type GuiBookOptions, type GuiBossBarColor, type GuiBossBarOptions, type GuiContainerType, GuiHelper, type GuiItemLayer, type GuiLayer, GuiLight, GuiObject, type GuiObjectOptions, type GuiRecipe, type GuiRecipeIngredient, type GuiRecipeOptions, type GuiSpriteScaling, type GuiText, type GuiTextLayer, type GuiTextLayout, type GuiTextOptions, type GuiTextRun, type GuiTextStyle, type GuiTextureLayer, type GuiTooltipOptions, HostedAssetSource, type IModelTextures, ITEM_GENERATED, type ImageInfo, ImageLoader, type ImageSizeInfo, InstanceManager, InstanceReference, type Instanceable, type ItemModel, type ItemModelContext, type ItemModelTextures, type ItemTintColor, type ItemTintSource, ItemTints, type ListAsset, type LoadedSceneDocument, type LoadedSceneObject, MapControls, type MaterialKey, Materials, type Maybe, type MeshKey, Meshes, MineRenderError, MineRenderScene, type MineRenderSceneOptions, MineRenderWorld, type MineRenderWorldOptions, type MinecraftAsset, MinecraftCubeTexture, MinecraftFaceUV, type MinecraftTextureMeta, type Model, ModelCulling, type ModelDisplay, type ModelElement, type ModelFaces, ModelGenerator, ModelMerger, ModelObject, type ModelObjectOptions, ModelTextures, Models, type MultiBlockBlock, type MultiBlockEntity, type MultiBlockStructure, type MultipartCondition, type NBTAsset, NBTHelper, NodeCache, NodeEnv, OrbitControls, type PackFormat, PackFormats, PackMetadata, PersistentCache, type PositionedGuiGlyph, type QuadArray, type RawImageKey, type RenderOptions, Renderer, type RendererFrame, type RendererOptions, type RequestConfig, RequestError, type RequestResponse, Requests, type ResolvedBlockEntity, type ResponseParser, SKIN_PARTS, type SceneBlockDefinition, type SceneDocument, SceneDocumentLoader, type SceneEntityDefinition, SceneExporter, type SceneGLTFExportOptions, type SceneGuiDefinition, type SceneGuiLayer, SceneInspector, type SceneModelDefinition, SceneObject, type SceneObjectDefinition, type SceneObjectDefinitionBase, type SceneObjectOptions, type SceneSkinDefinition, type SceneSkinPosePart, SceneStats, SceneStatsDisplay, SchematicParser, type SchematicParserOptions, SectionMesh, type SectionMeshEntry, type SectionMeshTemplate, SectionModels, type Serializable, type SkinGeometries, SkinImage, SkinObject, type SkinObjectOptions, SkinPart, type SkinTexture, type SkinTextureCoordinates, SkinTextures, Skins, type SpecialItemPart, type SpecialItemRenderer, SpecialItems, type StructureNBT, StructureParser, type TextureAsset, TextureAtlas, type TextureKey, TextureLoader, Textures, Ticker, type TickerFunction, TintColors, type Transformable, type TripleArray, UVMapper, WrappedImage, addBox3WireframeToObject, addWireframeToMesh, addWireframeToObject, applyElementRotation, applyGenericRotation, axisToVec3, base64decode, base64encode, capeTextureSizes, captureException, changeEvent, clampRotationDegrees, classicSkinGeometries, classicSkinTextureCoordinates, computeMorphedAttributes, createCanvas, createFluidGeometry, createGuiTextGeometry, createGuiTextureGeometry, createImage, entityAnimationTime, estimateBytesUsed, getBlockFluidState, getFluidKind, interleaveAttributes, isAssetKey, isBasicAssetKey, isBlockObject, isDisposable, isDoubleArray, isEntityObject, isGuiObject, isInstanceManager, isInstanceReference, isInstanceable, isInstancedMesh, isMesh, isMineRenderScene, isModelObject, isObject3D, isOrthographicCamera, isPerspectiveCamera, isQuadArray, isSceneObject, isTransformable, isTripleArray, isVector3, layoutGuiText, md5, mergeBufferAttributes, mergeBufferGeometries, mergeVertices, parseSceneDocument, prefix, registerNodeEnv, sampleEntityAnimation, sampleEntityKeyframes, sampleFluid, serializeBoxGeometryKey, serializeImageKey, serializeMaterialKey, serializeMeshKey, serializeTextureKey, sha1, sha256, sha512, shutdown, sleep, slimSkinGeometries, slimSkinTextureCoordinates, timingEnd, timingStart, toDegrees, toRadians, toTrianglesDrawMode, trimCanvas };
@@ -1528,6 +1528,8 @@ var init_ModelMerger = __esm({
1528
1528
  ModelMerger = class {
1529
1529
  /** Loads the parent chain and returns a merged model without modifying the supplied definition. */
1530
1530
  static async mergeWithParents(model) {
1531
+ const parts = model.parts;
1532
+ if (parts) return { ...model, parts: await Promise.all(parts.map((part) => this.mergeWithParents(part))) };
1531
1533
  const models = await this.collectAllParents(model);
1532
1534
  let merged = {};
1533
1535
  for (const source of [...models, model]) {
@@ -1588,6 +1590,7 @@ var init_Models = __esm({
1588
1590
  init_PersistentCache();
1589
1591
  init_AssetKey();
1590
1592
  init_AssetParsers();
1593
+ init_DisplayPosition();
1591
1594
  Models = class _Models {
1592
1595
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1593
1596
  // the library, and would require an EnvProvider before any entry has had a chance to register
@@ -1602,34 +1605,174 @@ var init_Models = __esm({
1602
1605
  return (await AssetLoader.getFirst([key, legacyKey], "list" /* LIST */))?.asset;
1603
1606
  }).then((r) => r?.files ?? []);
1604
1607
  }
1605
- static async loadAndMerge(key) {
1606
- const model = key.type === "item" ? await this.getItemModel(key) : await this.getRaw(key);
1608
+ static async loadAndMerge(key, context = {}) {
1609
+ const model = key.type === "item" ? await this.getItemModel(key, context) : await this.getRaw(key);
1607
1610
  if (!model) {
1608
1611
  return void 0;
1609
1612
  }
1610
1613
  return ModelMerger.mergeWithParents(model);
1611
1614
  }
1612
- static async getItemModel(key) {
1615
+ static async getItemModel(key, context = {}) {
1616
+ const preview = this.snapshotContext(key, context);
1613
1617
  const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
1614
- const model = await this.PERSISTENT_CACHE.getOrLoad(`item-v2:${AssetLoader.persistentKey(itemKey.serialize())}`, async () => {
1618
+ const cacheKey = itemKey.serialize() + this.contextKey(preview);
1619
+ const model = await this.PERSISTENT_CACHE.getOrLoad(`item-v3:${AssetLoader.persistentKey(cacheKey)}`, async () => {
1615
1620
  const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
1616
1621
  if (!result) return void 0;
1617
1622
  if (result.key.assetType !== "items") return { ...result.asset, key };
1618
- const selected = this.defaultItemModel(result.asset.model, key);
1619
- const modelKey = AssetKey.parse("models", selected.model);
1620
- modelKey.root = key.root;
1621
- const model2 = await this.getRaw(modelKey);
1622
- if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);
1623
- return { ...model2, ...selected.special && { special: selected.special }, ...selected.tints && { tints: selected.tints } };
1623
+ const load = async (selected) => {
1624
+ if ("parts" in selected) {
1625
+ return { key, parts: await Promise.all(selected.parts.map(load)) };
1626
+ }
1627
+ if ("item" in selected) {
1628
+ const model3 = await this.getItemModel(selected.item, { displayContext: preview.displayContext });
1629
+ if (!model3) throw new Error(`Item ${key.toNamespacedString()} references missing item ${selected.item.toNamespacedString()}`);
1630
+ return model3;
1631
+ }
1632
+ const modelKey = AssetKey.parse("models", selected.model);
1633
+ modelKey.root = key.root;
1634
+ const model2 = await this.getRaw(modelKey);
1635
+ if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);
1636
+ return { ...model2, ...selected.special && { special: selected.special }, ...selected.tints && { tints: selected.tints } };
1637
+ };
1638
+ return load(this.selectItemModel(result.asset.model, key, preview));
1624
1639
  });
1625
- return model ? { ...model, key: Object.assign(new AssetKey("", ""), model.key) } : void 0;
1640
+ const restore = (model2) => ({
1641
+ ...model2,
1642
+ key: Object.assign(new AssetKey("", ""), model2.key),
1643
+ ...model2.parts && { parts: model2.parts.map(restore) }
1644
+ });
1645
+ return model ? restore(model) : void 0;
1646
+ }
1647
+ static contextIdentifier(id) {
1648
+ if (typeof id !== "string" || !/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(id)) {
1649
+ throw new Error(`Invalid item-preview identifier: ${id}`);
1650
+ }
1651
+ return id.includes(":") ? id : `minecraft:${id}`;
1652
+ }
1653
+ static snapshotContext(key, context) {
1654
+ const displayContext = context.displayContext ?? "gui" /* GUI */;
1655
+ if (displayContext !== "none" && !Object.values(DisplayPosition).includes(displayContext)) {
1656
+ throw new Error(`Unsupported item display context: ${displayContext}`);
1657
+ }
1658
+ for (const map of [context.properties, context.components, context.itemReferences]) {
1659
+ if (map !== void 0 && (!map || typeof map !== "object" || Array.isArray(map))) {
1660
+ throw new Error("Item-preview properties, components, and references must be objects keyed by identifier");
1661
+ }
1662
+ }
1663
+ const count = context.count === void 0 ? 1 : context.count;
1664
+ if (!Number.isSafeInteger(count) || count < 0) throw new Error("Item-preview count must be a nonnegative safe integer");
1665
+ const properties = {};
1666
+ for (const [id, value] of Object.entries(context.properties ?? {})) {
1667
+ const property = this.contextIdentifier(id);
1668
+ if (!["boolean", "string", "number"].includes(typeof value) || typeof value === "number" && !Number.isFinite(value)) {
1669
+ throw new Error(`Item-preview property ${property} must be a boolean, string, or finite number`);
1670
+ }
1671
+ if (Object.prototype.hasOwnProperty.call(properties, property)) throw new Error(`Duplicate item-preview property: ${property}`);
1672
+ properties[property] = value;
1673
+ }
1674
+ const components = {};
1675
+ for (const [id, value] of Object.entries(context.components ?? {})) {
1676
+ const component = this.contextIdentifier(id);
1677
+ if (Object.prototype.hasOwnProperty.call(components, component)) throw new Error(`Duplicate item-preview component: ${component}`);
1678
+ components[component] = this.snapshotJson(value);
1679
+ }
1680
+ const itemReferences = {};
1681
+ for (const [id, value] of Object.entries(context.itemReferences ?? {})) {
1682
+ const reference = this.contextIdentifier(id);
1683
+ if (!isAssetKey(value) || value.assetType !== "models" || value.type !== "item") {
1684
+ throw new Error(`Item-preview reference ${reference} must be an item-model AssetKey`);
1685
+ }
1686
+ this.contextIdentifier(`${value.namespace}:${value.path}`);
1687
+ if (Object.prototype.hasOwnProperty.call(itemReferences, reference)) throw new Error(`Duplicate item-preview reference: ${reference}`);
1688
+ itemReferences[reference] = Object.assign(new AssetKey("", ""), value, { root: value.root ?? key.root });
1689
+ }
1690
+ return { displayContext, properties, components, count, itemReferences };
1691
+ }
1692
+ static contextKey(context) {
1693
+ const itemReferences = Object.fromEntries(Object.entries(context.itemReferences).map(([id, key]) => [id, key.serialize()]));
1694
+ return `|item-v3:${JSON.stringify(this.snapshotJson({ ...context, itemReferences }))}`;
1626
1695
  }
1627
- // Item previews use the GUI context, false conditions, and zero numeric properties.
1628
- static defaultItemModel(node, key) {
1696
+ static snapshotJson(value, ancestors = /* @__PURE__ */ new Set()) {
1697
+ if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return value;
1698
+ if (typeof value !== "object" || ancestors.has(value) || !Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
1699
+ throw new Error("Item-preview components must contain finite JSON values without circular references");
1700
+ }
1701
+ ancestors.add(value);
1702
+ const copy = Array.isArray(value) ? Array.from(value, (entry) => this.snapshotJson(entry, ancestors)) : Object.fromEntries(Object.keys(value).sort().map((key) => [key, this.snapshotJson(value[key], ancestors)]));
1703
+ ancestors.delete(value);
1704
+ return copy;
1705
+ }
1706
+ static propertyValue(node, context) {
1707
+ const kind = node.type.replace(/^minecraft:/, "");
1708
+ const property = node.property ? this.contextIdentifier(node.property) : void 0;
1709
+ if (kind === "select" && property === "minecraft:display_context") return context.displayContext;
1710
+ if (property && Object.prototype.hasOwnProperty.call(context.properties, property)) return context.properties[property];
1711
+ const fallback = kind === "condition" ? false : kind === "range_dispatch" ? 0 : void 0;
1712
+ const component = (id) => context.components[this.contextIdentifier(id)];
1713
+ if (property === "minecraft:custom_model_data") {
1714
+ const index = node.index ?? 0;
1715
+ if (!Number.isSafeInteger(index) || index < 0) throw new Error("Item-model custom_model_data index must be a nonnegative integer");
1716
+ const data = component("custom_model_data");
1717
+ if (data === void 0) return fallback;
1718
+ if (!data || typeof data !== "object" || Array.isArray(data)) throw new Error("Item-preview custom_model_data must be an object");
1719
+ const field = kind === "condition" ? "flags" : kind === "select" ? "strings" : "floats";
1720
+ const values = data[field];
1721
+ if (values === void 0) return fallback;
1722
+ if (!Array.isArray(values)) throw new Error(`Item-preview custom_model_data.${field} must be an array`);
1723
+ return index < values.length ? values[index] : fallback;
1724
+ }
1725
+ if (kind === "condition" && property === "minecraft:has_component") {
1726
+ if (node.ignore_default) throw new Error("Item-preview has_component with ignore_default requires an explicit properties override; item defaults are unavailable");
1727
+ return Object.prototype.hasOwnProperty.call(context.components, this.contextIdentifier(node.component));
1728
+ }
1729
+ if (kind === "select") {
1730
+ switch (property) {
1731
+ case "minecraft:component":
1732
+ return component(node.component);
1733
+ case "minecraft:block_state": {
1734
+ const state = component("block_state");
1735
+ if (state === void 0) return void 0;
1736
+ if (!state || typeof state !== "object" || Array.isArray(state)) throw new Error("Item-preview block_state must be an object");
1737
+ if (typeof node.block_state_property !== "string") throw new Error("Item-model block_state requires block_state_property");
1738
+ return Object.prototype.hasOwnProperty.call(state, node.block_state_property) ? state[node.block_state_property] : void 0;
1739
+ }
1740
+ case "minecraft:charge_type": {
1741
+ const projectiles = component("charged_projectiles");
1742
+ if (projectiles === void 0) return "none";
1743
+ if (!Array.isArray(projectiles)) throw new Error("Item-preview charged_projectiles must be an array of item stacks");
1744
+ const ids = projectiles.map((stack) => {
1745
+ if (!stack || typeof stack !== "object" || Array.isArray(stack)) throw new Error("Item-preview charged_projectiles must contain item-stack objects");
1746
+ return this.contextIdentifier(stack.id);
1747
+ });
1748
+ return !ids.length ? "none" : ids.includes("minecraft:firework_rocket") ? "rocket" : "arrow";
1749
+ }
1750
+ }
1751
+ }
1752
+ if (kind === "range_dispatch" && (property === "minecraft:damage" || property === "minecraft:count")) {
1753
+ const damage = property === "minecraft:damage";
1754
+ const maximumComponent = component(damage ? "max_damage" : "max_stack_size");
1755
+ const maximum = maximumComponent === void 0 ? damage ? 0 : 1 : maximumComponent;
1756
+ const damageComponent = component("damage");
1757
+ const value = damage ? damageComponent === void 0 ? 0 : damageComponent : context.count;
1758
+ if (typeof value !== "number" || typeof maximum !== "number" || maximum < 0) throw new Error(`Item-preview ${property} requires numeric components and a nonnegative maximum`);
1759
+ const clamped = Math.max(0, Math.min(maximum, value));
1760
+ return node.normalize === false ? clamped : clamped / maximum;
1761
+ }
1762
+ return fallback;
1763
+ }
1764
+ static selectItemModel(node, key, context) {
1629
1765
  if (!node || typeof node.type !== "string") {
1630
1766
  throw new Error(`Unsupported item model definition for ${key.toNamespacedString()}`);
1631
1767
  }
1632
1768
  switch (node.type.replace(/^minecraft:/, "")) {
1769
+ case "composite":
1770
+ if (Array.isArray(node.models)) return { parts: node.models.map((child) => this.selectItemModel(child, key, context)) };
1771
+ break;
1772
+ case "bundle/selected_item": {
1773
+ const item = context.itemReferences["minecraft:bundle/selected_item"];
1774
+ return item ? { item } : { parts: [] };
1775
+ }
1633
1776
  case "model":
1634
1777
  if (typeof node.model === "string" && node.model) return { model: node.model, tints: node.tints };
1635
1778
  break;
@@ -1650,17 +1793,29 @@ var init_Models = __esm({
1650
1793
  }
1651
1794
  throw new Error(`Unsupported special item renderer ${special.type} for ${key.toNamespacedString()}`);
1652
1795
  }
1653
- case "condition":
1654
- return this.defaultItemModel(node.on_false, key);
1796
+ case "condition": {
1797
+ const value = this.propertyValue(node, context);
1798
+ if (typeof value !== "boolean") throw new Error(`Item-preview condition ${node.property} requires a boolean`);
1799
+ return this.selectItemModel(value ? node.on_true : node.on_false, key, context);
1800
+ }
1655
1801
  case "select": {
1656
- const selected = node.property?.replace(/^minecraft:/, "") === "display_context" ? node.cases?.find((entry) => Array.isArray(entry.when) ? entry.when.includes("gui") : entry.when === "gui")?.model : void 0;
1657
- return this.defaultItemModel(selected ?? node.fallback, key);
1802
+ const value = this.propertyValue(node, context);
1803
+ const component = node.property && this.contextIdentifier(node.property) === "minecraft:component";
1804
+ if (!component && value !== void 0 && typeof value !== "string") throw new Error(`Item-preview selector ${node.property} requires a string`);
1805
+ const matches = (candidate) => component ? JSON.stringify(this.snapshotJson(candidate)) === JSON.stringify(this.snapshotJson(value)) : candidate === value;
1806
+ const selected = value === void 0 ? void 0 : node.cases?.find((entry) => matches(entry.when) || Array.isArray(entry.when) && entry.when.some(matches))?.model;
1807
+ return this.selectItemModel(selected ?? node.fallback, key, context);
1658
1808
  }
1659
1809
  case "range_dispatch": {
1810
+ const value = this.propertyValue(node, context);
1811
+ if (typeof value !== "number") throw new Error(`Item-preview range ${node.property} requires a number`);
1812
+ if (Number.isNaN(value)) return this.selectItemModel(node.fallback, key, context);
1813
+ const scaled = value * (node.scale ?? 1);
1814
+ if (!Number.isFinite(scaled)) throw new Error(`Item-preview range ${node.property} requires a finite value and scale`);
1660
1815
  const selected = node.entries?.reduce((match, entry) => {
1661
- return entry.threshold <= 0 && (!match || entry.threshold >= match.threshold) ? entry : match;
1816
+ return entry.threshold <= scaled && (!match || entry.threshold >= match.threshold) ? entry : match;
1662
1817
  }, void 0);
1663
- return this.defaultItemModel(selected?.model ?? node.fallback, key);
1818
+ return this.selectItemModel(selected?.model ?? node.fallback, key, context);
1664
1819
  }
1665
1820
  }
1666
1821
  throw new Error(`Unsupported item model ${node?.type ?? "definition"} for ${key.toNamespacedString()}`);
@@ -1687,25 +1842,28 @@ var init_Models = __esm({
1687
1842
  }
1688
1843
  /**
1689
1844
  * Loads a model and resolves its parent chain. Returns `undefined` when the model is missing.
1690
- * Item keys use GUI context, false conditions, and zero numeric properties.
1845
+ * Item keys default to GUI context and a stack count of 1. Unresolved conditions are false and numeric properties are zero.
1846
+ * Pass `context` to supply component values, property overrides, and item references for a preview.
1847
+ * Composite items retain independently merged children in `ItemModel.parts`.
1691
1848
  *
1692
1849
  * @param key - Model key, for example `AssetKey.parse("models", "minecraft:item/diamond_sword")`.
1693
1850
  */
1694
- static async getMerged(key) {
1851
+ static async getMerged(key, context = {}) {
1695
1852
  if (!key.assetType) {
1696
1853
  key.assetType = "models";
1697
1854
  }
1698
1855
  if (!key.extension) {
1699
1856
  key.extension = ".json";
1700
1857
  }
1701
- const keyStr = key.serialize();
1858
+ const preview = this.snapshotContext(key, context);
1859
+ const keyStr = key.serialize() + (key.type === "item" ? this.contextKey(preview) : "");
1702
1860
  return Caching.mergedModelCache.get(keyStr, (k) => {
1703
- return _Models.loadAndMerge(key);
1861
+ return _Models.loadAndMerge(key, preview);
1704
1862
  });
1705
1863
  }
1706
1864
  /** Alias for {@link getMerged}. */
1707
- static async get(key) {
1708
- return this.getMerged(key);
1865
+ static async get(key, context = {}) {
1866
+ return this.getMerged(key, context);
1709
1867
  }
1710
1868
  /** Clears persisted models. Use {@link Caching.clear} to also discard in-memory assets. */
1711
1869
  static async clearCache() {
@@ -5576,9 +5734,10 @@ var init_ModelObject = __esm({
5576
5734
  this.originalModel = originalModel;
5577
5735
  this.isModelObject = true;
5578
5736
  this.specialMaterials = /* @__PURE__ */ new Map();
5737
+ this.geometries = /* @__PURE__ */ new Set();
5579
5738
  this.meshesCreated = false;
5580
5739
  this.options = (0, import_ts_deepmerge5.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
5581
- if (originalModel.special) this.options.instanceMeshes = false;
5740
+ if (originalModel.special || originalModel.parts) this.options.instanceMeshes = false;
5582
5741
  if (this.options.tints) this.options.tints = { ...this.options.tints };
5583
5742
  this.addEventListener("added", () => this.updateAnimationSubscription());
5584
5743
  this.addEventListener("removed", () => this.updateAnimationSubscription());
@@ -5587,14 +5746,36 @@ var init_ModelObject = __esm({
5587
5746
  this.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
5588
5747
  }
5589
5748
  async init() {
5749
+ const parts = this.originalModel.parts;
5750
+ if (parts) {
5751
+ try {
5752
+ for (const part of parts) {
5753
+ const object3 = new _ModelObject(part, { ...this.options, instanceMeshes: false });
5754
+ this.add(object3);
5755
+ await object3.init();
5756
+ }
5757
+ let order = 0;
5758
+ this.iterateAllMeshes((mesh) => {
5759
+ mesh.renderOrder = order++;
5760
+ for (const material of Array.isArray(mesh.material) ? mesh.material : [mesh.material]) {
5761
+ material.transparent = true;
5762
+ }
5763
+ });
5764
+ } catch (error) {
5765
+ this.disposeAndRemoveAllChildren();
5766
+ throw error;
5767
+ }
5768
+ this.notifyDirty();
5769
+ return;
5770
+ }
5590
5771
  this.options.tints = await ItemTints.get(this.originalModel, this.options.tints);
5591
5772
  const special = this.originalModel.special;
5592
5773
  if (special) {
5593
- const parts = await SpecialItems.getParts(special, this.originalModel.key?.root);
5774
+ const parts2 = await SpecialItems.getParts(special, this.originalModel.key?.root);
5594
5775
  const transform = this.options.displayPosition ? DisplayTransforms.getMatrix(this.originalModel.display, this.options.displayPosition) : new import_three25.Matrix4();
5595
5776
  transform.multiply(new import_three25.Matrix4().makeTranslation(-8, -8, -8));
5596
5777
  try {
5597
- for (const part of parts) {
5778
+ for (const part of parts2) {
5598
5779
  const object3 = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe });
5599
5780
  object3.matrix.copy(transform).multiply(part.transform);
5600
5781
  object3.matrixWorldNeedsUpdate = true;
@@ -5645,6 +5826,7 @@ var init_ModelObject = __esm({
5645
5826
  if (this.atlas.model.elements) {
5646
5827
  this.atlas.model.elements?.forEach((el) => {
5647
5828
  const elGeo = this._getBoxGeometryFromElement(el).clone();
5829
+ this.geometries.add(elGeo);
5648
5830
  if (this.options.cullMask) {
5649
5831
  const indices = Array.from(elGeo.getIndex().array);
5650
5832
  elGeo.setIndex(indices.filter((_, index) => {
@@ -5698,10 +5880,14 @@ var init_ModelObject = __esm({
5698
5880
  let combinedGeo;
5699
5881
  if (allGeos.length > 0) {
5700
5882
  combinedGeo = mergeBufferGeometries(allGeos);
5883
+ for (const geometry of allGeos) {
5884
+ this.geometries.delete(geometry);
5885
+ }
5701
5886
  } else {
5702
5887
  combinedGeo = new import_three25.BoxGeometry(16, 16, 16);
5703
5888
  if (displayTransform) DisplayTransforms.apply(combinedGeo, displayTransform);
5704
5889
  }
5890
+ this.geometries.add(combinedGeo);
5705
5891
  combinedGeo.computeBoundingBox();
5706
5892
  let mesh;
5707
5893
  if (this.options.instanceMeshes) {
@@ -5726,6 +5912,9 @@ var init_ModelObject = __esm({
5726
5912
  const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false, true);
5727
5913
  this.atlasMaterial = mat;
5728
5914
  this.atlasTexture = mat.uniforms?.map?.value ?? mat.map;
5915
+ if (this.options.displayPosition === "gui" /* GUI */ && this.originalModel.gui_light === "front" /* FRONT */ && mat.uniforms?.SHADE) {
5916
+ mat.uniforms.SHADE.value = false;
5917
+ }
5729
5918
  this.iterateAllMeshes((mesh) => {
5730
5919
  if (mesh.geometry.hasAttribute("color")) mat.vertexColors = true;
5731
5920
  mesh.material = mat;
@@ -5734,7 +5923,9 @@ var init_ModelObject = __esm({
5734
5923
  }
5735
5924
  }
5736
5925
  updateAnimationSubscription() {
5737
- const active = !!this.parent && (!this.isInstanced || this.instanceCounter > 0);
5926
+ let root = this;
5927
+ while (root.parent && isModelObject(root.parent)) root = root.parent;
5928
+ const active = !!root.parent && (!this.isInstanced || this.instanceCounter > 0);
5738
5929
  if (active && this.atlas?.hasAnimation && this.atlasTexture) {
5739
5930
  if (!this.unsubscribeAtlas) {
5740
5931
  this.atlasTexture.needsUpdate = true;
@@ -5750,6 +5941,9 @@ var init_ModelObject = __esm({
5750
5941
  this.unsubscribeAtlas?.();
5751
5942
  this.unsubscribeAtlas = void 0;
5752
5943
  }
5944
+ for (const child of this.children) {
5945
+ if (isModelObject(child)) child.updateAnimationSubscription();
5946
+ }
5753
5947
  }
5754
5948
  nextInstance() {
5755
5949
  const reference = super.nextInstance();
@@ -5769,6 +5963,8 @@ var init_ModelObject = __esm({
5769
5963
  this.atlasMaterial = void 0;
5770
5964
  for (const material of this.specialMaterials.values()) material.dispose();
5771
5965
  this.specialMaterials.clear();
5966
+ for (const geometry of this.geometries) geometry.dispose();
5967
+ this.geometries.clear();
5772
5968
  super.disposeAndRemoveAllChildren();
5773
5969
  }
5774
5970
  };
@@ -9868,7 +10064,6 @@ init_SceneObject();
9868
10064
  init_Materials();
9869
10065
  init_ModelObject();
9870
10066
  init_DisplayPosition();
9871
- init_GuiLight();
9872
10067
  var GuiObject = class extends SceneObject {
9873
10068
  constructor(textureLayers, options) {
9874
10069
  super({ ...options, instanceMeshes: false, mergeMeshes: false });
@@ -9936,12 +10131,16 @@ var GuiObject = class extends SceneObject {
9936
10131
  mesh2.geometry.computeBoundingBox();
9937
10132
  bounds.union(mesh2.geometry.boundingBox.clone().applyMatrix4(new import_three26.Matrix4().multiplyMatrices(inverse, mesh2.matrixWorld)));
9938
10133
  });
9939
- item.position.z = depth - bounds.min.z;
9940
- depth += bounds.max.z - bounds.min.z + 0.01;
10134
+ item.position.z = depth;
10135
+ if (!bounds.isEmpty()) {
10136
+ item.position.z -= bounds.min.z;
10137
+ depth += bounds.max.z - bounds.min.z;
10138
+ this.bounds.expandByPoint(new import_three26.Vector2(bounds.min.x, -bounds.max.y));
10139
+ this.bounds.expandByPoint(new import_three26.Vector2(bounds.max.x, -bounds.min.y));
10140
+ }
10141
+ depth += 0.01;
9941
10142
  this.bounds.expandByPoint(new import_three26.Vector2(x, y));
9942
10143
  this.bounds.expandByPoint(new import_three26.Vector2(x + width2, y + height2));
9943
- this.bounds.expandByPoint(new import_three26.Vector2(bounds.min.x, -bounds.max.y));
9944
- this.bounds.expandByPoint(new import_three26.Vector2(bounds.max.x, -bounds.min.y));
9945
10144
  continue;
9946
10145
  }
9947
10146
  const key = typeof layer.texture === "string" ? AssetKey.parse("textures", layer.texture) : layer.texture;
@@ -9981,15 +10180,13 @@ var GuiObject = class extends SceneObject {
9981
10180
  item.name = `group:${layer.name ?? index}`;
9982
10181
  this.add(item);
9983
10182
  await item.init();
9984
- item.iterateAllMeshes((mesh) => {
9985
- if (!model.special) this.geometries.add(mesh.geometry);
10183
+ const meshes = [];
10184
+ item.iterateAllMeshes((mesh) => meshes.push(mesh));
10185
+ meshes.forEach((mesh, partIndex) => {
9986
10186
  mesh.name = `mesh:${layer.name ?? index}`;
9987
- mesh.renderOrder = index;
10187
+ mesh.renderOrder = index + partIndex / (meshes.length + 1) * 0.5;
9988
10188
  for (const material of Array.isArray(mesh.material) ? mesh.material : [mesh.material]) {
9989
10189
  material.transparent = true;
9990
- if (model.gui_light === "front" /* FRONT */ && material.uniforms?.SHADE) {
9991
- material.uniforms.SHADE.value = false;
9992
- }
9993
10190
  }
9994
10191
  });
9995
10192
  return item;