minerender 2.1.0-beta.7 → 2.1.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/browser/esm/armor/Armor.mjs +84 -0
- package/dist/browser/esm/armor/Armor.mjs.map +1 -0
- package/dist/browser/esm/armor/index.mjs +3 -0
- package/dist/browser/esm/armor/index.mjs.map +1 -0
- package/dist/browser/esm/assets/BlockEntities.mjs +2 -0
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +39 -11
- package/dist/browser/esm/assets/Entities.mjs.map +1 -1
- package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
- package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
- package/dist/browser/esm/assets/ModelTextures.mjs +13 -7
- package/dist/browser/esm/assets/ModelTextures.mjs.map +1 -1
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
- package/dist/browser/esm/cache/Caching.mjs +8 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityObject.mjs +31 -5
- package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserEnv.mjs +11 -4
- package/dist/browser/esm/env/browser/BrowserEnv.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +129 -13
- package/dist/browser/esm/index.browser.mjs.map +1 -1
- package/dist/browser/esm/index.mjs +1 -0
- package/dist/browser/esm/index.mjs.map +1 -1
- package/dist/browser/esm/model/ItemGlint.mjs +7 -6
- package/dist/browser/esm/model/ItemGlint.mjs.map +1 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs +16 -5
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/esm/scene/SceneDocument.mjs +35 -5
- package/dist/browser/esm/scene/SceneDocument.mjs.map +1 -1
- package/dist/browser/esm/scene/SceneDocumentLoader.mjs +14 -3
- package/dist/browser/esm/scene/SceneDocumentLoader.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinGeometries.mjs +4 -1
- package/dist/browser/esm/skin/SkinGeometries.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinPart.mjs +2 -0
- package/dist/browser/esm/skin/SkinPart.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinTextureCoordinates.mjs +11 -1
- package/dist/browser/esm/skin/SkinTextureCoordinates.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinTextures.mjs +1 -1
- package/dist/browser/esm/skin/SkinTextures.mjs.map +1 -1
- package/dist/browser/esm/skin/scene/SkinObject.mjs +119 -7
- package/dist/browser/esm/skin/scene/SkinObject.mjs.map +1 -1
- package/dist/browser/esm/texture/PalettedTextures.mjs +46 -0
- package/dist/browser/esm/texture/PalettedTextures.mjs.map +1 -0
- package/dist/browser/esm/texture/index.mjs +1 -0
- package/dist/browser/esm/texture/index.mjs.map +1 -1
- package/dist/browser/esm/util/util.mjs +0 -2
- package/dist/browser/esm/util/util.mjs.map +1 -1
- package/dist/browser/esm/world/Chunk.mjs +62 -33
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +98 -13
- package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
- package/dist/browser/esm/world/SectionMesh.mjs +65 -9
- package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
- package/dist/browser/esm/world/SectionModels.mjs +21 -15
- package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
- package/dist/browser/esm/world/SectionWorker.mjs +8 -2
- package/dist/browser/esm/world/SectionWorker.mjs.map +1 -1
- package/dist/browser/esm/world/WorldStreamer.mjs +109 -15
- package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
- package/dist/browser/index.d.ts +129 -13
- package/dist/browser/index.js +1592 -894
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +1330 -619
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +117 -12
- package/dist/node/index.d.ts +117 -12
- package/dist/node/index.js +1505 -793
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +1303 -593
- package/dist/node/index.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/model/block/scene/BlockObject.ts"],"sourcesContent":["import { SceneObject } from \"../../../renderer/SceneObject\";\nimport { BlockState, BlockStateVariant } from \"../BlockState\";\nimport { SceneObjectOptions } from \"../../../renderer/SceneObjectOptions\";\nimport { isModelObject, ModelObject, ModelObjectOptions } from \"../../scene/ModelObject\";\nimport { Caching } from \"../../../cache/Caching\";\nimport { Models } from \"../../../assets/Models\";\nimport { merge } from \"../../../util/_internal/merge\";\nimport { Euler, Matrix4, Quaternion, Vector3 } from \"three\";\nimport { Maybe } from \"../../../util/util\";\nimport { MineRenderError } from \"../../../error/MineRenderError\";\nimport { BlockStateProperties, BlockStatePropertyDefaults } from \"../BlockStateProperties\";\nimport { InstanceReference, isInstanceReference } from \"../../../instance/InstanceReference\";\nimport { AssetKey, BasicAssetKey } from \"../../../assets/AssetKey\";\nimport { BlockTints } from \"../BlockTints\";\nimport { ModelCulling } from \"../../ModelCulling\";\nimport { BlockStateResolver } from \"../BlockStateResolver\";\nimport { FluidKind, FluidRules, FluidSampler, resolveBlockFluidState } from \"../../fluid/FluidGeometry\";\nimport { MineRenderData } from \"../../../assets/MineRenderData\";\nimport { BlockEntities, ResolvedBlockEntity } from \"../../../assets/BlockEntities\";\nimport { Entities } from \"../../../assets/Entities\";\nimport type { EntityObject } from \"../../../entity/scene/EntityObject\";\nimport { Biomes } from \"../../../assets/Biomes\";\nimport type { TripleArray } from \"../../Model\";\nimport { logger } from \"../../../util/log\";\n\nconst log = logger(\"BlockObject\");\n\n/** Controls the model parts selected by a blockstate. Create it through {@link MineRenderScene.addBlock}. */\nexport class BlockObject extends SceneObject {\n\n public readonly isBlockObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: BlockObjectOptions = merge({}, ModelObject.DEFAULT_OPTIONS, <BlockObjectOptions>{\n applyDefaultState: true\n });\n public readonly options: BlockObjectOptions;\n private readonly variantPosition?: TripleArray;\n\n private _previousState: BlockStateProperties = {};\n private _state: BlockStateProperties = {};\n private _variant: Maybe<BlockStateVariant> = undefined;\n\n private _instanceState: BlockStateProperties[] = [];\n private _instanceVariant: BlockStateVariant[][] = [];\n private _instanceModel: (ModelObject | InstanceReference<ModelObject>)[] = [];\n\n private _variants: BlockStateVariant[] = [];\n private _models: (ModelObject | InstanceReference<ModelObject>)[] = [];\n private _cullMask = 0;\n private _fluidKey?: string;\n private _fluidRules: FluidRules = {};\n private _fluidSampler?: FluidSampler;\n private readonly biomePosition?: TripleArray;\n private waterTint?: number;\n private _fluidModel?: ModelObject | InstanceReference<ModelObject>;\n private _entities: EntityObject[] = [];\n private _entityPlacement = new Matrix4();\n private _entityGeneration = 0;\n\n constructor(readonly blockState: BlockState, options?: Partial<BlockObjectOptions>) {\n super(options);\n this.options = merge({}, BlockObject.DEFAULT_OPTIONS, options ?? {});\n this.variantPosition = options?.variantPosition ? [...options.variantPosition] : undefined;\n this.biomePosition = options?.biomePosition ? [...options.biomePosition] : undefined;\n //TODO\n }\n\n async init(): Promise<void> {\n this._fluidRules = await MineRenderData.get(\"fluids\", this.blockState.key?.root);\n if (this.options.applyDefaultState) {\n this._setState(await BlockStateResolver.defaults(this.blockState));\n }\n if (this.options.initialState !== undefined) this._setState(this.options.initialState);\n await this.recreateModels();\n //TODO\n }\n\n dispose() {\n this.clearModels();\n super.dispose();\n }\n\n removeFromScene() {\n this.clearModels();\n super.removeFromScene();\n }\n\n private clearModels() {\n this.removeModels(this._models.splice(0));\n this._entityGeneration++;\n this.removeEntities(this._entities.splice(0));\n this._fluidKey = undefined;\n this._fluidModel = undefined;\n this._isInstanced = false;\n this._instanceCounter = 0;\n }\n\n private removeModels(models: (ModelObject | InstanceReference<ModelObject>)[]) {\n for (const model of models) {\n model.removeFromScene();\n if (!isInstanceReference(model)) model.dispose();\n }\n }\n\n private removeEntities(entities: EntityObject[]) {\n for (const entity of entities) {\n entity.removeFromScene();\n entity.dispose();\n }\n }\n\n /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */\n public get blockEntities(): readonly EntityObject[] {\n return this._entities;\n }\n\n /** Model placements drawn for this block, including its fluid surface. */\n public get models(): readonly (ModelObject | InstanceReference<ModelObject>)[] {\n return this._models;\n }\n\n /** Sets visibility for this block's model instances and block entities. */\n public setVisible(visible: boolean): void {\n this.visible = visible;\n for (const model of this._models) {\n if (isInstanceReference(model)) {\n model.setVisible(visible);\n } else {\n model.visible = visible;\n }\n }\n for (const entity of this._entities) {\n entity.visible = visible;\n }\n this.notifyDirty();\n }\n\n /**\n * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,\n * when the block is not listed or one of its models cannot be loaded.\n */\n private async createBlockEntities(): Promise<boolean> {\n const key = this.blockState.key;\n if (!key || this.options.displayPosition) return false;\n const generation = this._entityGeneration;\n const created: EntityObject[] = [];\n let resolved: Maybe<ResolvedBlockEntity>;\n try {\n resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);\n if (!resolved) return false;\n for (const part of resolved.parts) {\n const [namespace, path] = part.model.includes(\":\") ? part.model.split(\":\") : [key.namespace, part.model];\n const texture = part.textureLocation === undefined ? undefined\n : AssetKey.parse(\"textures\", part.textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (texture) texture.root = key.root;\n const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });\n if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);\n created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }) as EntityObject);\n }\n } catch (error) {\n log.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);\n this.removeEntities(created);\n return false;\n }\n // The block was cleared while the models loaded.\n if (generation !== this._entityGeneration) {\n this.removeEntities(created);\n return true;\n }\n BlockEntities.matrix(resolved, this._entityPlacement);\n this._entities = created;\n this.placeEntities();\n this.setVisible(this.visible);\n return true;\n }\n\n private placeEntities() {\n // Block models are centred on the block position; entity transforms use the block's 0..16 space.\n const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);\n for (const entity of this._entities) {\n matrix.decompose(entity.position, entity.quaternion, entity.scale);\n }\n }\n\n public get isOccluding(): boolean {\n if (!this.visible) {\n return false;\n }\n return this._models.some(model => {\n const object = isInstanceReference(model) ? model.instanceable : model;\n return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;\n });\n }\n\n private getModelMatrix(model: ModelObject | InstanceReference<ModelObject>): Matrix4 {\n if (isInstanceReference(model)) return model.getMatrix();\n if (model.matrixAutoUpdate) model.updateMatrix();\n return model.matrix.clone();\n }\n\n private getModelCullMask(model: ModelObject | InstanceReference<ModelObject>, worldMask: number): number {\n const object = isInstanceReference(model) ? model.instanceable : model;\n if (object.options.displayPosition) return 0;\n const position = new Vector3();\n const rotation = new Quaternion();\n const scale = new Vector3();\n this.getModelMatrix(model).decompose(position, rotation, scale);\n if (position.distanceToSquared(this.position) > 1e-10\n || scale.distanceToSquared(new Vector3(1, 1, 1)) > 1e-10) return 0;\n return ModelCulling.toLocalMask(worldMask, new Euler().setFromQuaternion(rotation));\n }\n\n /** World-space face mask currently applied to this block. */\n public get cullMask(): number {\n return this._cullMask;\n }\n\n public async setCullMask(worldMask: number): Promise<void> {\n worldMask &= 63;\n const replacements: (ModelObject | InstanceReference<ModelObject>)[] = [];\n try {\n for (const model of this._models) {\n if (model === this._fluidModel) {\n replacements.push(model);\n continue;\n }\n const object = isInstanceReference(model) ? model.instanceable : model;\n const cullMask = this.getModelCullMask(model, worldMask);\n if (cullMask === (object.options.cullMask ?? 0)) {\n replacements.push(model);\n continue;\n }\n const matrix = this.getModelMatrix(model);\n const replacement = await this.scene.addModel(object.originalModel, { ...object.options, cullMask });\n replacements.push(replacement);\n if (isInstanceReference(replacement)) {\n replacement.setMatrix(matrix);\n } else {\n replacement.matrix.copy(matrix);\n replacement.matrixWorldNeedsUpdate = true;\n matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n replacement.matrixAutoUpdate = object.matrixAutoUpdate;\n replacement.visible = object.visible;\n }\n }\n } catch (error) {\n this.removeModels(replacements.filter(model => !this._models.includes(model)));\n throw error;\n }\n const previous = this._models;\n this._models = replacements;\n this._cullMask = worldMask;\n this.removeModels(previous.filter(model => !replacements.includes(model)));\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n /** Selected property values. Use {@link setState} to change properties and rebuild the rendered models. */\n public get state(): { [key: string]: string; } {\n return this._state;\n }\n\n public get fluidKind(): FluidKind | undefined {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.kind;\n }\n\n public get fluidLevel(): number {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.level ?? 0;\n }\n\n /** Refreshes fluid surfaces from relative neighbors; standalone previews use air around the block. */\n public async updateFluid(sample?: FluidSampler): Promise<void> {\n const kind = this.fluidKind;\n if (!kind) return;\n const { FluidModelObject, sampleFluid } = await import(\"../../fluid/FluidModelObject\");\n this._fluidSampler = sample;\n const surface = sampleFluid(kind, (x, y, z) => x === 0 && y === 0 && z === 0\n ? { fluid: kind, level: this.fluidLevel } : sample?.(x, y, z) ?? {});\n const tint = this.options.tints?.[0] ?? this.waterTint;\n const fluidKey = `${surface.key}|${tint ?? \"default\"}`;\n if (this._fluidKey === fluidKey) return;\n const key = new AssetKey(\"minecraft\", `${kind}/${surface.key}`, \"models\", \"fluid\", \"assets\", \".json\", this.blockState.key?.root);\n const replacement = await this.scene.addSceneObject({ key },\n () => new FluidModelObject(kind, surface.sample, this.blockState.key, {\n ...this.options, tints: tint === undefined ? this.options.tints : { ...this.options.tints, 0: tint }\n }));\n const previous = this._fluidModel;\n const matrix = previous ? this.getModelMatrix(previous) : new Matrix4().makeTranslation(...this.position.toArray());\n if (isInstanceReference(replacement)) replacement.setMatrix(matrix);\n else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n this._models = this._models.filter(model => model !== previous);\n this._models.push(replacement);\n this._fluidModel = replacement;\n this._fluidKey = fluidKey;\n this._isInstanced ||= isInstanceReference(replacement);\n this._instanceCounter = this._isInstanced ? 1 : 0;\n if (previous) this.removeModels([previous]);\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n nextInstance(): InstanceReference<SceneObject> {\n\n const ref = super.nextInstance();\n for (let child of this.children) {\n if (isModelObject(child)) {\n child._instanceCounter = this.instanceCounter;\n }\n }\n return ref;\n }\n\n protected async mapStateToVariant(state: BlockStateProperties): Promise<BlockStateVariant[]> {\n return BlockStateResolver.select(this.blockState, state, variants => this.getSingleVariant(variants));\n }\n\n public async recreateModels(): Promise<void> {\n //TODO: change this to create models once, and then modify rotations when updating the state\n\n // Remove all children\n // this.disposeAndRemoveAllChildren(); //TODO: just removes all children of all instances atm...\n\n // TODO: try to reuse models instead of just removing them and creating new ones\n this.clearModels();\n\n this.waterTint = this.fluidKind === \"water\" && this.options.biome && this.options.tints?.[0] === undefined\n ? await Biomes.getColor(this.options.biome, \"water\", this.blockState.key) : undefined;\n\n if (resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.renderModel === false) {\n await this.updateFluid(this._fluidSampler);\n return;\n }\n\n\n //TODO: might want to preload all possible states & cache their data\n //TODO: make sure to only instance stuff with different rotations together; i.e. not those with different multipart settings, or different models\n\n /*\n if (this.isInstanced) {\n //TODO: only map once per state\n for (let i = 0; i < this.instanceCounter; i++) {\n this._instanceVariant[i] = await this.mapStateToVariant(this._instanceState[i]);\n for (let variant of this._instanceVariant[i]) {\n this._instanceModel[i] = await this.createVariant(variant);\n }\n }\n //TODO: actually create\n //TODO: group by model\n this._isInstanced = true;\n } else {\n */\n const hasEntities = await this.createBlockEntities();\n const variantsToCreate = await this.mapStateToVariant(this.state);\n this._variants = variantsToCreate;\n for (let blockStateVariant of variantsToCreate) {\n // A block entity replaces only block models without geometry (a chest); a bell keeps its frame.\n if (hasEntities && !await this.hasGeometry(blockStateVariant)) continue;\n this._models.push(await this.createVariant(blockStateVariant));\n }\n await this.updateFluid(this._fluidSampler);\n this.setVisible(this.visible);\n /*\n }\n\n */\n\n }\n\n private async hasGeometry(variant: BlockStateVariant): Promise<boolean> {\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n return !!(await Models.getMerged(modelKey))?.elements?.length;\n }\n\n protected getSingleVariant(variants: BlockStateVariant | BlockStateVariant[]): BlockStateVariant {\n return BlockStateResolver.choose(variants, this.variantPosition);\n }\n\n // @deprecated\n protected async createAVariant(variants: BlockStateVariant | BlockStateVariant[], instanceInfo: Matrix4[]) {\n const variant = this.getSingleVariant(variants);\n await this.createVariant(variant);\n }\n\n protected async createVariant(variant: BlockStateVariant): Promise<ModelObject | InstanceReference<ModelObject>> {\n const rotation = BlockStateResolver.rotation(variant);\n\n // The model and its textures must come from the same asset root as the blockstate.\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n const model = await Models.getMerged(modelKey);\n const options: Partial<ModelObjectOptions> = {\n ...this.options,\n tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints,\n () => BlockTints.getBiomeColor(this.blockState.key, this.options.biome, this.biomePosition)) : this.options.tints,\n uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0)\n ? [rotation.x, rotation.y, rotation.z] : undefined,\n cullMask: this.options.displayPosition ? 0 : ModelCulling.toLocalMask(this._cullMask, rotation)\n };\n const obj = await this.scene.addModel(model!, options);\n if (isInstanceReference(obj) || (<ModelObject>obj).isInstanced) {\n this._isInstanced = true;\n this._instanceCounter = 1;//TODO: BlockObject itself isn't technically instanced, but needs the id for the get/setMatrix calls to work properly\n }\n obj.setRotation(rotation);\n obj.setPosition(this.position);\n return obj;\n }\n\n /** Clears selected properties and rebuilds models without reapplying property defaults. */\n public async resetState() {\n this._previousState = this._state;\n this._state = {};\n await this.recreateModels();\n }\n\n // TODO: support state per instance\n /**\n * Updates properties and rebuilds the selected models.\n * Accepts `\"facing=north,open=true\"`, a property object, or a key and value.\n * Properties omitted from the call keep their current values.\n */\n public async setState(string: string);\n public async setState(state: BlockStateProperties);\n public async setState(key: string, value: string);\n public async setState(stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setState(stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setState(stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n this._previousState = this._state;\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setState(k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._state[k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._state[stringOrKeyOrState as string] = value;\n }\n }\n\n /*\n public async setStateAt(index: number, string: string);\n public async setStateAt(index: number, state: BlockStateProperties);\n public async setStateAt(index: number, key: string, value: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setStateAt(index, stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n if (!this._instanceState[index]) this._instanceState[index] = {};\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setStateAt(index, k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._instanceState[index][k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._instanceState[index][stringOrKeyOrState as string] = value;\n }\n }\n\n _getStateAt(index: number): BlockStateProperties {\n return this._instanceState[index];\n }\n\n */\n\n setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3) {\n super.setPositionRotationScaleAt(index, position, rotation, scale);\n }\n\n getMatrixAt(index: number, matrix: Matrix4 = new Matrix4()): Matrix4 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const child = this._models[0];\n if (child && isModelObject(child)) {\n child.getMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.getMatrix(matrix);\n }\n /*\n const child = this.children[0];\n if (child && isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.getMatrixAt(index, matrix);\n }\n return matrix;\n */\n // return super.getMatrixAt(0, matrix);\n return matrix;\n }\n\n setMatrixAt(index: number, matrix: Matrix4) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n // const child = this._models[0];\n for(let child of this._models) {\n if (child && isModelObject(child)) {\n child.setMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.setMatrix(matrix);\n }\n }\n /*\n for (let child of this.children) {\n if (isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.setMatrixAt(index, matrix);\n }\n }\n */\n }\n\n setPosition(position: Vector3) {\n this.position.copy(position);\n // Each part keeps its own variant rotation when the block moves.\n for (let model of this._models) {\n model.setPosition(position);\n }\n this.placeEntities();\n this.notifyDirty();\n }\n\n //TODO: should override rotation + scale methods\n\n //TODO\n\n}\n\n/** Block settings passed to `scene.addBlock(blockState, options)` or the BlockObject constructor. */\nexport interface BlockObjectOptions extends ModelObjectOptions {\n /** Loads vanilla property defaults before applying `initialState`. Defaults to `true`. */\n applyDefaultState: boolean;\n /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */\n initialState?: BlockStateProperties;\n /** Absolute block coordinates for repeatable variants, copied at construction. Omit for random previews. */\n variantPosition?: TripleArray;\n /** Saved biome ID used for automatic grass, foliage, and water colors. */\n biome?: string;\n /** World block coordinates used by biome grass modifiers. Copied at construction; defaults to the origin. */\n biomePosition?: TripleArray;\n}\n\nexport function isBlockObject(obj: any): obj is BlockObject {\n return (<BlockObject>obj).isBlockObject;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/model/block/scene/BlockObject.ts"],"sourcesContent":["import { SceneObject } from \"../../../renderer/SceneObject\";\nimport { BlockState, BlockStateVariant } from \"../BlockState\";\nimport { SceneObjectOptions } from \"../../../renderer/SceneObjectOptions\";\nimport { isModelObject, ModelObject, ModelObjectOptions } from \"../../scene/ModelObject\";\nimport { Caching } from \"../../../cache/Caching\";\nimport { Models } from \"../../../assets/Models\";\nimport { merge } from \"../../../util/_internal/merge\";\nimport { Euler, Matrix4, Quaternion, Vector3 } from \"three\";\nimport { Maybe } from \"../../../util/util\";\nimport { MineRenderError } from \"../../../error/MineRenderError\";\nimport { BlockStateProperties, BlockStatePropertyDefaults } from \"../BlockStateProperties\";\nimport { InstanceReference, isInstanceReference } from \"../../../instance/InstanceReference\";\nimport { AssetKey, BasicAssetKey } from \"../../../assets/AssetKey\";\nimport { BlockTints } from \"../BlockTints\";\nimport { ModelCulling } from \"../../ModelCulling\";\nimport { BlockStateResolver } from \"../BlockStateResolver\";\nimport { FluidKind, FluidRules, FluidSampler, resolveBlockFluidState } from \"../../fluid/FluidGeometry\";\nimport { MineRenderData } from \"../../../assets/MineRenderData\";\nimport { BlockEntities, ResolvedBlockEntity } from \"../../../assets/BlockEntities\";\nimport { Entities } from \"../../../assets/Entities\";\nimport type { EntityObject } from \"../../../entity/scene/EntityObject\";\nimport { Biomes } from \"../../../assets/Biomes\";\nimport type { TripleArray } from \"../../Model\";\nimport { logger } from \"../../../util/log\";\n\nconst log = logger(\"BlockObject\");\n\n/** Controls the model parts selected by a blockstate. Create it through {@link MineRenderScene.addBlock}. */\nexport class BlockObject extends SceneObject {\n\n public readonly isBlockObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: BlockObjectOptions = merge({}, ModelObject.DEFAULT_OPTIONS, <BlockObjectOptions>{\n applyDefaultState: true\n });\n public readonly options: BlockObjectOptions;\n private readonly variantPosition?: TripleArray;\n\n private _previousState: BlockStateProperties = {};\n private _state: BlockStateProperties = {};\n private _variant: Maybe<BlockStateVariant> = undefined;\n\n private _instanceState: BlockStateProperties[] = [];\n private _instanceVariant: BlockStateVariant[][] = [];\n private _instanceModel: (ModelObject | InstanceReference<ModelObject>)[] = [];\n\n private _variants: BlockStateVariant[] = [];\n private _models: (ModelObject | InstanceReference<ModelObject>)[] = [];\n private _cullMask = 0;\n private _fluidKey?: string;\n private _fluidRules: FluidRules = {};\n private _fluidSampler?: FluidSampler;\n private readonly biomePosition?: TripleArray;\n private waterTint?: number;\n private _fluidModel?: ModelObject | InstanceReference<ModelObject>;\n private _entities: EntityObject[] = [];\n private _entityPlacement = new Matrix4();\n private _entityGeneration = 0;\n\n constructor(readonly blockState: BlockState, options?: Partial<BlockObjectOptions>) {\n super(options);\n this.options = merge({}, BlockObject.DEFAULT_OPTIONS, options ?? {});\n this.variantPosition = options?.variantPosition ? [...options.variantPosition] : undefined;\n this.biomePosition = options?.biomePosition ? [...options.biomePosition] : undefined;\n //TODO\n }\n\n async init(): Promise<void> {\n this._fluidRules = await MineRenderData.get(\"fluids\", this.blockState.key?.root);\n if (this.options.applyDefaultState) {\n this._setState(await BlockStateResolver.defaults(this.blockState));\n }\n if (this.options.initialState !== undefined) this._setState(this.options.initialState);\n await this.recreateModels();\n //TODO\n }\n\n dispose() {\n this.clearModels();\n super.dispose();\n }\n\n removeFromScene() {\n this.clearModels();\n super.removeFromScene();\n }\n\n private clearModels() {\n this.removeModels(this._models.splice(0));\n this._entityGeneration++;\n this.removeEntities(this._entities.splice(0));\n this._fluidKey = undefined;\n this._fluidModel = undefined;\n this._isInstanced = false;\n this._instanceCounter = 0;\n }\n\n private removeModels(models: (ModelObject | InstanceReference<ModelObject>)[]) {\n for (const model of models) {\n model.removeFromScene();\n if (!isInstanceReference(model)) model.dispose();\n }\n }\n\n private removeEntities(entities: EntityObject[]) {\n for (const entity of entities) {\n entity.removeFromScene();\n entity.dispose();\n }\n }\n\n /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */\n public get blockEntities(): readonly EntityObject[] {\n return this._entities;\n }\n\n /** Model placements drawn for this block, including its fluid surface. */\n public get models(): readonly (ModelObject | InstanceReference<ModelObject>)[] {\n return this._models;\n }\n\n /** Sets visibility for this block's model instances and block entities. */\n public setVisible(visible: boolean): void {\n this.visible = visible;\n for (const model of this._models) {\n if (isInstanceReference(model)) {\n model.setVisible(visible);\n } else {\n model.visible = visible;\n }\n }\n for (const entity of this._entities) {\n entity.visible = visible;\n }\n this.notifyDirty();\n }\n\n /**\n * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,\n * when the block is not listed or one of its models cannot be loaded.\n */\n private async createBlockEntities(): Promise<boolean> {\n const key = this.blockState.key;\n if (!key || this.options.displayPosition) return false;\n const generation = this._entityGeneration;\n const created: EntityObject[] = [];\n const placement = new Matrix4();\n let resolved: Maybe<ResolvedBlockEntity>;\n try {\n resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);\n if (!resolved) return false;\n BlockEntities.matrix(resolved, placement);\n for (const part of resolved.parts) {\n const [namespace, path] = part.model.includes(\":\") ? part.model.split(\":\") : [key.namespace, part.model];\n let texture = part.textureLocation === undefined ? undefined\n : AssetKey.parse(\"textures\", part.textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (part.textureLocation === undefined && namespace === \"minecraft\" && path === \"player_head\") {\n const { PlayerHeadTextures } = await import(\"../../../skin/PlayerHeadTextures\");\n texture = (await PlayerHeadTextures.get(undefined, key.root)).texture;\n }\n if (texture) texture.root = key.root;\n const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });\n if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);\n const object = await this.scene.addEntity(entity, { wireframe: this.options.wireframe }) as EntityObject;\n this.placeEntity(object, placement);\n created.push(object);\n }\n } catch (error) {\n log.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);\n this.removeEntities(created);\n return false;\n }\n // The block was cleared while the models loaded.\n if (generation !== this._entityGeneration) {\n this.removeEntities(created);\n return true;\n }\n this._entityPlacement.copy(placement);\n this._entities = created;\n this.placeEntities();\n this.setVisible(this.visible);\n return true;\n }\n\n private placeEntities() {\n for (const entity of this._entities) {\n this.placeEntity(entity, this._entityPlacement);\n }\n }\n\n private placeEntity(entity: EntityObject, placement: Matrix4) {\n // Block models are centred on the block position; entity transforms use the block's 0..16 space.\n const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(placement);\n matrix.decompose(entity.position, entity.quaternion, entity.scale);\n }\n\n public get isOccluding(): boolean {\n if (!this.visible) {\n return false;\n }\n return this._models.some(model => {\n const object = isInstanceReference(model) ? model.instanceable : model;\n return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;\n });\n }\n\n private getModelMatrix(model: ModelObject | InstanceReference<ModelObject>): Matrix4 {\n if (isInstanceReference(model)) return model.getMatrix();\n if (model.matrixAutoUpdate) model.updateMatrix();\n return model.matrix.clone();\n }\n\n private getModelCullMask(model: ModelObject | InstanceReference<ModelObject>, worldMask: number): number {\n const object = isInstanceReference(model) ? model.instanceable : model;\n if (object.options.displayPosition) return 0;\n const position = new Vector3();\n const rotation = new Quaternion();\n const scale = new Vector3();\n this.getModelMatrix(model).decompose(position, rotation, scale);\n if (position.distanceToSquared(this.position) > 1e-10\n || scale.distanceToSquared(new Vector3(1, 1, 1)) > 1e-10) return 0;\n return ModelCulling.toLocalMask(worldMask, new Euler().setFromQuaternion(rotation));\n }\n\n /** World-space face mask currently applied to this block. */\n public get cullMask(): number {\n return this._cullMask;\n }\n\n public async setCullMask(worldMask: number): Promise<void> {\n worldMask &= 63;\n const replacements: (ModelObject | InstanceReference<ModelObject>)[] = [];\n try {\n for (const model of this._models) {\n if (model === this._fluidModel) {\n replacements.push(model);\n continue;\n }\n const object = isInstanceReference(model) ? model.instanceable : model;\n const cullMask = this.getModelCullMask(model, worldMask);\n if (cullMask === (object.options.cullMask ?? 0)) {\n replacements.push(model);\n continue;\n }\n const matrix = this.getModelMatrix(model);\n const replacement = await this.scene.addModel(object.originalModel, { ...object.options, cullMask });\n replacements.push(replacement);\n if (isInstanceReference(replacement)) {\n replacement.setMatrix(matrix);\n } else {\n replacement.matrix.copy(matrix);\n replacement.matrixWorldNeedsUpdate = true;\n matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n replacement.matrixAutoUpdate = object.matrixAutoUpdate;\n replacement.visible = object.visible;\n }\n }\n } catch (error) {\n this.removeModels(replacements.filter(model => !this._models.includes(model)));\n throw error;\n }\n const previous = this._models;\n this._models = replacements;\n this._cullMask = worldMask;\n this.removeModels(previous.filter(model => !replacements.includes(model)));\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n /** Selected property values. Use {@link setState} to change properties and rebuild the rendered models. */\n public get state(): { [key: string]: string; } {\n return this._state;\n }\n\n public get fluidKind(): FluidKind | undefined {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.kind;\n }\n\n public get fluidLevel(): number {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.level ?? 0;\n }\n\n /** Refreshes fluid surfaces from relative neighbors; standalone previews use air around the block. */\n public async updateFluid(sample?: FluidSampler): Promise<void> {\n const kind = this.fluidKind;\n if (!kind) return;\n const { FluidModelObject, sampleFluid } = await import(\"../../fluid/FluidModelObject\");\n this._fluidSampler = sample;\n const surface = sampleFluid(kind, (x, y, z) => x === 0 && y === 0 && z === 0\n ? { fluid: kind, level: this.fluidLevel } : sample?.(x, y, z) ?? {});\n const tint = this.options.tints?.[0] ?? this.waterTint;\n const fluidKey = `${surface.key}|${tint ?? \"default\"}`;\n if (this._fluidKey === fluidKey) return;\n const key = new AssetKey(\"minecraft\", `${kind}/${surface.key}`, \"models\", \"fluid\", \"assets\", \".json\", this.blockState.key?.root);\n const replacement = await this.scene.addSceneObject({ key },\n () => new FluidModelObject(kind, surface.sample, this.blockState.key, {\n ...this.options, tints: tint === undefined ? this.options.tints : { ...this.options.tints, 0: tint }\n }));\n const previous = this._fluidModel;\n const matrix = previous ? this.getModelMatrix(previous) : new Matrix4().makeTranslation(...this.position.toArray());\n if (isInstanceReference(replacement)) replacement.setMatrix(matrix);\n else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n this._models = this._models.filter(model => model !== previous);\n this._models.push(replacement);\n this._fluidModel = replacement;\n this._fluidKey = fluidKey;\n this._isInstanced ||= isInstanceReference(replacement);\n this._instanceCounter = this._isInstanced ? 1 : 0;\n if (previous) this.removeModels([previous]);\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n nextInstance(): InstanceReference<SceneObject> {\n\n const ref = super.nextInstance();\n for (let child of this.children) {\n if (isModelObject(child)) {\n child._instanceCounter = this.instanceCounter;\n }\n }\n return ref;\n }\n\n protected async mapStateToVariant(state: BlockStateProperties): Promise<BlockStateVariant[]> {\n return BlockStateResolver.select(this.blockState, state, variants => this.getSingleVariant(variants));\n }\n\n public async recreateModels(): Promise<void> {\n //TODO: change this to create models once, and then modify rotations when updating the state\n\n // Remove all children\n // this.disposeAndRemoveAllChildren(); //TODO: just removes all children of all instances atm...\n\n // TODO: try to reuse models instead of just removing them and creating new ones\n this.clearModels();\n\n this.waterTint = this.fluidKind === \"water\" && this.options.biome && this.options.tints?.[0] === undefined\n ? await Biomes.getColor(this.options.biome, \"water\", this.blockState.key) : undefined;\n\n if (resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.renderModel === false) {\n await this.updateFluid(this._fluidSampler);\n return;\n }\n\n\n //TODO: might want to preload all possible states & cache their data\n //TODO: make sure to only instance stuff with different rotations together; i.e. not those with different multipart settings, or different models\n\n /*\n if (this.isInstanced) {\n //TODO: only map once per state\n for (let i = 0; i < this.instanceCounter; i++) {\n this._instanceVariant[i] = await this.mapStateToVariant(this._instanceState[i]);\n for (let variant of this._instanceVariant[i]) {\n this._instanceModel[i] = await this.createVariant(variant);\n }\n }\n //TODO: actually create\n //TODO: group by model\n this._isInstanced = true;\n } else {\n */\n const hasEntities = await this.createBlockEntities();\n const variantsToCreate = await this.mapStateToVariant(this.state);\n this._variants = variantsToCreate;\n for (let blockStateVariant of variantsToCreate) {\n // A block entity replaces only block models without geometry (a chest); a bell keeps its frame.\n if (hasEntities && !await this.hasGeometry(blockStateVariant)) continue;\n this._models.push(await this.createVariant(blockStateVariant));\n }\n await this.updateFluid(this._fluidSampler);\n this.setVisible(this.visible);\n /*\n }\n\n */\n\n }\n\n private async hasGeometry(variant: BlockStateVariant): Promise<boolean> {\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n return !!(await Models.getMerged(modelKey))?.elements?.length;\n }\n\n protected getSingleVariant(variants: BlockStateVariant | BlockStateVariant[]): BlockStateVariant {\n return BlockStateResolver.choose(variants, this.variantPosition);\n }\n\n // @deprecated\n protected async createAVariant(variants: BlockStateVariant | BlockStateVariant[], instanceInfo: Matrix4[]) {\n const variant = this.getSingleVariant(variants);\n await this.createVariant(variant);\n }\n\n protected async createVariant(variant: BlockStateVariant): Promise<ModelObject | InstanceReference<ModelObject>> {\n const rotation = BlockStateResolver.rotation(variant);\n\n // The model and its textures must come from the same asset root as the blockstate.\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n const model = await Models.getMerged(modelKey);\n const options: Partial<ModelObjectOptions> = {\n ...this.options,\n tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints,\n () => BlockTints.getBiomeColor(this.blockState.key, this.options.biome, this.biomePosition)) : this.options.tints,\n uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0)\n ? [rotation.x, rotation.y, rotation.z] : undefined,\n cullMask: this.options.displayPosition ? 0 : ModelCulling.toLocalMask(this._cullMask, rotation)\n };\n const obj = await this.scene.addModel(model!, options);\n if (isInstanceReference(obj) || (<ModelObject>obj).isInstanced) {\n this._isInstanced = true;\n this._instanceCounter = 1;//TODO: BlockObject itself isn't technically instanced, but needs the id for the get/setMatrix calls to work properly\n }\n obj.setRotation(rotation);\n obj.setPosition(this.position);\n return obj;\n }\n\n /** Clears selected properties and rebuilds models without reapplying property defaults. */\n public async resetState() {\n this._previousState = this._state;\n this._state = {};\n await this.recreateModels();\n }\n\n // TODO: support state per instance\n /**\n * Updates properties and rebuilds the selected models.\n * Accepts `\"facing=north,open=true\"`, a property object, or a key and value.\n * Properties omitted from the call keep their current values.\n */\n public async setState(string: string);\n public async setState(state: BlockStateProperties);\n public async setState(key: string, value: string);\n public async setState(stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setState(stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setState(stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n this._previousState = this._state;\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setState(k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._state[k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._state[stringOrKeyOrState as string] = value;\n }\n }\n\n /*\n public async setStateAt(index: number, string: string);\n public async setStateAt(index: number, state: BlockStateProperties);\n public async setStateAt(index: number, key: string, value: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setStateAt(index, stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n if (!this._instanceState[index]) this._instanceState[index] = {};\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setStateAt(index, k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._instanceState[index][k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._instanceState[index][stringOrKeyOrState as string] = value;\n }\n }\n\n _getStateAt(index: number): BlockStateProperties {\n return this._instanceState[index];\n }\n\n */\n\n setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3) {\n super.setPositionRotationScaleAt(index, position, rotation, scale);\n }\n\n getMatrixAt(index: number, matrix: Matrix4 = new Matrix4()): Matrix4 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const child = this._models[0];\n if (child && isModelObject(child)) {\n child.getMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.getMatrix(matrix);\n }\n /*\n const child = this.children[0];\n if (child && isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.getMatrixAt(index, matrix);\n }\n return matrix;\n */\n // return super.getMatrixAt(0, matrix);\n return matrix;\n }\n\n setMatrixAt(index: number, matrix: Matrix4) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n // const child = this._models[0];\n for(let child of this._models) {\n if (child && isModelObject(child)) {\n child.setMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.setMatrix(matrix);\n }\n }\n /*\n for (let child of this.children) {\n if (isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.setMatrixAt(index, matrix);\n }\n }\n */\n }\n\n setPosition(position: Vector3) {\n this.position.copy(position);\n // Each part keeps its own variant rotation when the block moves.\n for (let model of this._models) {\n model.setPosition(position);\n }\n this.placeEntities();\n this.notifyDirty();\n }\n\n //TODO: should override rotation + scale methods\n\n //TODO\n\n}\n\n/** Block settings passed to `scene.addBlock(blockState, options)` or the BlockObject constructor. */\nexport interface BlockObjectOptions extends ModelObjectOptions {\n /** Loads vanilla property defaults before applying `initialState`. Defaults to `true`. */\n applyDefaultState: boolean;\n /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */\n initialState?: BlockStateProperties;\n /** Absolute block coordinates for repeatable variants, copied at construction. Omit for random previews. */\n variantPosition?: TripleArray;\n /** Saved biome ID used for automatic grass, foliage, and water colors. */\n biome?: string;\n /** World block coordinates used by biome grass modifiers. Copied at construction; defaults to the origin. */\n biomePosition?: TripleArray;\n}\n\nexport function isBlockObject(obj: any): obj is BlockObject {\n return (<BlockObject>obj).isBlockObject;\n}\n"],"mappings":";AAAA,SAAS,mBAAmB;AAG5B,SAAS,eAAe,mBAAuC;AAE/D,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,OAAO,SAAS,YAAY,eAAe;AAEpD,SAAS,uBAAuB;AAEhC,SAA4B,2BAA2B;AACvD,SAAS,UAAU,qBAAqB;AACxC,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAA8C,8BAA8B;AAC5E,SAAS,sBAAsB;AAC/B,SAAS,qBAA0C;AACnD,SAAS,gBAAgB;AAEzB,SAAS,cAAc;AAEvB,SAAS,cAAc;AAEvB,IAAM,MAAM,OAAO,aAAa;AAGzB,IAAM,eAAN,MAAM,qBAAoB,YAAY;AAAA,EA+BzC,YAAqB,YAAwB,SAAuC;AAChF,UAAM,OAAO;AADI;AA7BrB,SAAgB,gBAAsB;AAQtC,SAAQ,iBAAuC,CAAC;AAChD,SAAQ,SAA+B,CAAC;AACxC,SAAQ,WAAqC;AAE7C,SAAQ,iBAAyC,CAAC;AAClD,SAAQ,mBAA0C,CAAC;AACnD,SAAQ,iBAAmE,CAAC;AAE5E,SAAQ,YAAiC,CAAC;AAC1C,SAAQ,UAA4D,CAAC;AACrE,SAAQ,YAAY;AAEpB,SAAQ,cAA0B,CAAC;AAKnC,SAAQ,YAA4B,CAAC;AACrC,SAAQ,mBAAmB,IAAI,QAAQ;AACvC,SAAQ,oBAAoB;AAIxB,SAAK,UAAU,MAAM,CAAC,GAAG,aAAY,iBAAiB,WAAW,CAAC,CAAC;AACnE,SAAK,kBAAkB,SAAS,kBAAkB,CAAC,GAAG,QAAQ,eAAe,IAAI;AACjF,SAAK,gBAAgB,SAAS,gBAAgB,CAAC,GAAG,QAAQ,aAAa,IAAI;AAAA,EAE/E;AAAA,EAEA,MAAM,OAAsB;AACxB,SAAK,cAAc,MAAM,eAAe,IAAI,UAAU,KAAK,WAAW,KAAK,IAAI;AAC/E,QAAI,KAAK,QAAQ,mBAAmB;AAChC,WAAK,UAAU,MAAM,mBAAmB,SAAS,KAAK,UAAU,CAAC;AAAA,IACrE;AACA,QAAI,KAAK,QAAQ,iBAAiB,OAAW,MAAK,UAAU,KAAK,QAAQ,YAAY;AACrF,UAAM,KAAK,eAAe;AAAA,EAE9B;AAAA,EAEA,UAAU;AACN,SAAK,YAAY;AACjB,UAAM,QAAQ;AAAA,EAClB;AAAA,EAEA,kBAAkB;AACd,SAAK,YAAY;AACjB,UAAM,gBAAgB;AAAA,EAC1B;AAAA,EAEQ,cAAc;AAClB,SAAK,aAAa,KAAK,QAAQ,OAAO,CAAC,CAAC;AACxC,SAAK;AACL,SAAK,eAAe,KAAK,UAAU,OAAO,CAAC,CAAC;AAC5C,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,mBAAmB;AAAA,EAC5B;AAAA,EAEQ,aAAa,QAA0D;AAC3E,eAAW,SAAS,QAAQ;AACxB,YAAM,gBAAgB;AACtB,UAAI,CAAC,oBAAoB,KAAK,EAAG,OAAM,QAAQ;AAAA,IACnD;AAAA,EACJ;AAAA,EAEQ,eAAe,UAA0B;AAC7C,eAAW,UAAU,UAAU;AAC3B,aAAO,gBAAgB;AACvB,aAAO,QAAQ;AAAA,IACnB;AAAA,EACJ;AAAA;AAAA,EAGA,IAAW,gBAAyC;AAChD,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGA,IAAW,SAAoE;AAC3E,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGO,WAAW,SAAwB;AACtC,SAAK,UAAU;AACf,eAAW,SAAS,KAAK,SAAS;AAC9B,UAAI,oBAAoB,KAAK,GAAG;AAC5B,cAAM,WAAW,OAAO;AAAA,MAC5B,OAAO;AACH,cAAM,UAAU;AAAA,MACpB;AAAA,IACJ;AACA,eAAW,UAAU,KAAK,WAAW;AACjC,aAAO,UAAU;AAAA,IACrB;AACA,SAAK,YAAY;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,sBAAwC;AAClD,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,OAAO,KAAK,QAAQ,gBAAiB,QAAO;AACjD,UAAM,aAAa,KAAK;AACxB,UAAM,UAA0B,CAAC;AACjC,UAAM,YAAY,IAAI,QAAQ;AAC9B,QAAI;AACJ,QAAI;AACA,iBAAW,cAAc,QAAQ,MAAM,cAAc,SAAS,IAAI,IAAI,GAAG,IAAI,mBAAmB,GAAG,KAAK,KAAK;AAC7G,UAAI,CAAC,SAAU,QAAO;AACtB,oBAAc,OAAO,UAAU,SAAS;AACxC,iBAAW,QAAQ,SAAS,OAAO;AAC/B,cAAM,CAAC,WAAW,IAAI,IAAI,KAAK,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,WAAW,KAAK,KAAK;AACvG,YAAI,UAAU,KAAK,oBAAoB,SAAY,SAC7C,SAAS,MAAM,YAAY,KAAK,gBAAgB,QAAQ,wBAAwB,IAAI,CAAC;AAC3F,YAAI,KAAK,oBAAoB,UAAa,cAAc,eAAe,SAAS,eAAe;AAC3F,gBAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,sCAAkC;AAC9E,qBAAW,MAAM,mBAAmB,IAAI,QAAW,IAAI,IAAI,GAAG;AAAA,QAClE;AACA,YAAI,QAAS,SAAQ,OAAO,IAAI;AAChC,cAAM,SAAS,MAAM,SAAS,UAAU,IAAI,cAAc,WAAW,IAAI,GAAG,SAAS,EAAE,OAAO,KAAK,MAAM,CAAC;AAC1G,YAAI,CAAC,OAAQ,OAAM,IAAI,gBAAgB,wBAAwB,KAAK,KAAK,EAAE;AAC3E,cAAM,SAAS,MAAM,KAAK,MAAM,UAAU,QAAQ,EAAE,WAAW,KAAK,QAAQ,UAAU,CAAC;AACvF,aAAK,YAAY,QAAQ,SAAS;AAClC,gBAAQ,KAAK,MAAM;AAAA,MACvB;AAAA,IACJ,SAAS,OAAO;AACZ,UAAI,KAAK,+BAA+B,IAAI,mBAAmB,CAAC,2BAA2B,KAAK;AAChG,WAAK,eAAe,OAAO;AAC3B,aAAO;AAAA,IACX;AAEA,QAAI,eAAe,KAAK,mBAAmB;AACvC,WAAK,eAAe,OAAO;AAC3B,aAAO;AAAA,IACX;AACA,SAAK,iBAAiB,KAAK,SAAS;AACpC,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,WAAW,KAAK,OAAO;AAC5B,WAAO;AAAA,EACX;AAAA,EAEQ,gBAAgB;AACpB,eAAW,UAAU,KAAK,WAAW;AACjC,WAAK,YAAY,QAAQ,KAAK,gBAAgB;AAAA,IAClD;AAAA,EACJ;AAAA,EAEQ,YAAY,QAAsB,WAAoB;AAE1D,UAAM,SAAS,IAAI,QAAQ,EAAE,gBAAgB,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,EAAE,SAAS,SAAS;AAC9H,WAAO,UAAU,OAAO,UAAU,OAAO,YAAY,OAAO,KAAK;AAAA,EACrE;AAAA,EAEA,IAAW,cAAuB;AAC9B,QAAI,CAAC,KAAK,SAAS;AACf,aAAO;AAAA,IACX;AACA,WAAO,KAAK,QAAQ,KAAK,WAAS;AAC9B,YAAM,SAAS,oBAAoB,KAAK,IAAI,MAAM,eAAe;AACjE,aAAO,OAAO,oBAAoB,KAAK,iBAAiB,OAAO,EAAE,MAAM;AAAA,IAC3E,CAAC;AAAA,EACL;AAAA,EAEQ,eAAe,OAA8D;AACjF,QAAI,oBAAoB,KAAK,EAAG,QAAO,MAAM,UAAU;AACvD,QAAI,MAAM,iBAAkB,OAAM,aAAa;AAC/C,WAAO,MAAM,OAAO,MAAM;AAAA,EAC9B;AAAA,EAEQ,iBAAiB,OAAqD,WAA2B;AACrG,UAAM,SAAS,oBAAoB,KAAK,IAAI,MAAM,eAAe;AACjE,QAAI,OAAO,QAAQ,gBAAiB,QAAO;AAC3C,UAAM,WAAW,IAAI,QAAQ;AAC7B,UAAM,WAAW,IAAI,WAAW;AAChC,UAAM,QAAQ,IAAI,QAAQ;AAC1B,SAAK,eAAe,KAAK,EAAE,UAAU,UAAU,UAAU,KAAK;AAC9D,QAAI,SAAS,kBAAkB,KAAK,QAAQ,IAAI,SACzC,MAAM,kBAAkB,IAAI,QAAQ,GAAG,GAAG,CAAC,CAAC,IAAI,MAAO,QAAO;AACrE,WAAO,aAAa,YAAY,WAAW,IAAI,MAAM,EAAE,kBAAkB,QAAQ,CAAC;AAAA,EACtF;AAAA;AAAA,EAGA,IAAW,WAAmB;AAC1B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAa,YAAY,WAAkC;AACvD,iBAAa;AACb,UAAM,eAAiE,CAAC;AACxE,QAAI;AACA,iBAAW,SAAS,KAAK,SAAS;AAC9B,YAAI,UAAU,KAAK,aAAa;AAC5B,uBAAa,KAAK,KAAK;AACvB;AAAA,QACJ;AACA,cAAM,SAAS,oBAAoB,KAAK,IAAI,MAAM,eAAe;AACjE,cAAM,WAAW,KAAK,iBAAiB,OAAO,SAAS;AACvD,YAAI,cAAc,OAAO,QAAQ,YAAY,IAAI;AAC7C,uBAAa,KAAK,KAAK;AACvB;AAAA,QACJ;AACA,cAAM,SAAS,KAAK,eAAe,KAAK;AACxC,cAAM,cAAc,MAAM,KAAK,MAAM,SAAS,OAAO,eAAe,EAAE,GAAG,OAAO,SAAS,SAAS,CAAC;AACnG,qBAAa,KAAK,WAAW;AAC7B,YAAI,oBAAoB,WAAW,GAAG;AAClC,sBAAY,UAAU,MAAM;AAAA,QAChC,OAAO;AACH,sBAAY,OAAO,KAAK,MAAM;AAC9B,sBAAY,yBAAyB;AACrC,iBAAO,UAAU,YAAY,UAAU,YAAY,YAAY,YAAY,KAAK;AAChF,sBAAY,mBAAmB,OAAO;AACtC,sBAAY,UAAU,OAAO;AAAA,QACjC;AAAA,MACJ;AAAA,IACJ,SAAS,OAAO;AACZ,WAAK,aAAa,aAAa,OAAO,WAAS,CAAC,KAAK,QAAQ,SAAS,KAAK,CAAC,CAAC;AAC7E,YAAM;AAAA,IACV;AACA,UAAM,WAAW,KAAK;AACtB,SAAK,UAAU;AACf,SAAK,YAAY;AACjB,SAAK,aAAa,SAAS,OAAO,WAAS,CAAC,aAAa,SAAS,KAAK,CAAC,CAAC;AACzE,QAAI,CAAC,KAAK,SAAS;AACf,WAAK,WAAW,KAAK;AAAA,IACzB;AACA,SAAK,YAAY;AAAA,EACrB;AAAA;AAAA,EAGA,IAAW,QAAoC;AAC3C,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAW,YAAmC;AAC1C,WAAO,uBAAuB,KAAK,WAAW,KAAK,KAAK,OAAO,KAAK,WAAW,GAAG;AAAA,EACtF;AAAA,EAEA,IAAW,aAAqB;AAC5B,WAAO,uBAAuB,KAAK,WAAW,KAAK,KAAK,OAAO,KAAK,WAAW,GAAG,SAAS;AAAA,EAC/F;AAAA;AAAA,EAGA,MAAa,YAAY,QAAsC;AAC3D,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,KAAM;AACX,UAAM,EAAE,kBAAkB,YAAY,IAAI,MAAM,OAAO,kCAA8B;AACrF,SAAK,gBAAgB;AACrB,UAAM,UAAU,YAAY,MAAM,CAAC,GAAG,GAAG,MAAM,MAAM,KAAK,MAAM,KAAK,MAAM,IACrE,EAAE,OAAO,MAAM,OAAO,KAAK,WAAW,IAAI,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;AACvE,UAAM,OAAO,KAAK,QAAQ,QAAQ,CAAC,KAAK,KAAK;AAC7C,UAAM,WAAW,GAAG,QAAQ,GAAG,IAAI,QAAQ,SAAS;AACpD,QAAI,KAAK,cAAc,SAAU;AACjC,UAAM,MAAM,IAAI,SAAS,aAAa,GAAG,IAAI,IAAI,QAAQ,GAAG,IAAI,UAAU,SAAS,UAAU,SAAS,KAAK,WAAW,KAAK,IAAI;AAC/H,UAAM,cAAc,MAAM,KAAK,MAAM;AAAA,MAAe,EAAE,IAAI;AAAA,MACtD,MAAM,IAAI,iBAAiB,MAAM,QAAQ,QAAQ,KAAK,WAAW,KAAK;AAAA,QAClE,GAAG,KAAK;AAAA,QAAS,OAAO,SAAS,SAAY,KAAK,QAAQ,QAAQ,EAAE,GAAG,KAAK,QAAQ,OAAO,GAAG,KAAK;AAAA,MACvG,CAAC;AAAA,IAAC;AACN,UAAM,WAAW,KAAK;AACtB,UAAM,SAAS,WAAW,KAAK,eAAe,QAAQ,IAAI,IAAI,QAAQ,EAAE,gBAAgB,GAAG,KAAK,SAAS,QAAQ,CAAC;AAClH,QAAI,oBAAoB,WAAW,EAAG,aAAY,UAAU,MAAM;AAAA,QAC7D,QAAO,UAAU,YAAY,UAAU,YAAY,YAAY,YAAY,KAAK;AACrF,SAAK,UAAU,KAAK,QAAQ,OAAO,WAAS,UAAU,QAAQ;AAC9D,SAAK,QAAQ,KAAK,WAAW;AAC7B,SAAK,cAAc;AACnB,SAAK,YAAY;AACjB,SAAK,iBAAL,KAAK,eAAiB,oBAAoB,WAAW;AACrD,SAAK,mBAAmB,KAAK,eAAe,IAAI;AAChD,QAAI,SAAU,MAAK,aAAa,CAAC,QAAQ,CAAC;AAC1C,QAAI,CAAC,KAAK,SAAS;AACf,WAAK,WAAW,KAAK;AAAA,IACzB;AACA,SAAK,YAAY;AAAA,EACrB;AAAA,EAEA,eAA+C;AAE3C,UAAM,MAAM,MAAM,aAAa;AAC/B,aAAS,SAAS,KAAK,UAAU;AAC7B,UAAI,cAAc,KAAK,GAAG;AACtB,cAAM,mBAAmB,KAAK;AAAA,MAClC;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA,EAEA,MAAgB,kBAAkB,OAA2D;AACzF,WAAO,mBAAmB,OAAO,KAAK,YAAY,OAAO,cAAY,KAAK,iBAAiB,QAAQ,CAAC;AAAA,EACxG;AAAA,EAEA,MAAa,iBAAgC;AAOzC,SAAK,YAAY;AAEjB,SAAK,YAAY,KAAK,cAAc,WAAW,KAAK,QAAQ,SAAS,KAAK,QAAQ,QAAQ,CAAC,MAAM,SAC3F,MAAM,OAAO,SAAS,KAAK,QAAQ,OAAO,SAAS,KAAK,WAAW,GAAG,IAAI;AAEhF,QAAI,uBAAuB,KAAK,WAAW,KAAK,KAAK,OAAO,KAAK,WAAW,GAAG,gBAAgB,OAAO;AAClG,YAAM,KAAK,YAAY,KAAK,aAAa;AACzC;AAAA,IACJ;AAoBA,UAAM,cAAc,MAAM,KAAK,oBAAoB;AACnD,UAAM,mBAAmB,MAAM,KAAK,kBAAkB,KAAK,KAAK;AAChE,SAAK,YAAY;AACjB,aAAS,qBAAqB,kBAAkB;AAE5C,UAAI,eAAe,CAAC,MAAM,KAAK,YAAY,iBAAiB,EAAG;AAC/D,WAAK,QAAQ,KAAK,MAAM,KAAK,cAAc,iBAAiB,CAAC;AAAA,IACjE;AACA,UAAM,KAAK,YAAY,KAAK,aAAa;AACzC,SAAK,WAAW,KAAK,OAAO;AAAA,EAMhC;AAAA,EAEA,MAAc,YAAY,SAA8C;AACpE,UAAM,WAAW,SAAS,MAAM,UAAU,QAAQ,KAAM;AACxD,aAAS,OAAO,KAAK,WAAW,KAAK;AACrC,WAAO,CAAC,EAAE,MAAM,OAAO,UAAU,QAAQ,IAAI,UAAU;AAAA,EAC3D;AAAA,EAEU,iBAAiB,UAAsE;AAC7F,WAAO,mBAAmB,OAAO,UAAU,KAAK,eAAe;AAAA,EACnE;AAAA;AAAA,EAGA,MAAgB,eAAe,UAAmD,cAAyB;AACvG,UAAM,UAAU,KAAK,iBAAiB,QAAQ;AAC9C,UAAM,KAAK,cAAc,OAAO;AAAA,EACpC;AAAA,EAEA,MAAgB,cAAc,SAAmF;AAC7G,UAAM,WAAW,mBAAmB,SAAS,OAAO;AAGpD,UAAM,WAAW,SAAS,MAAM,UAAU,QAAQ,KAAM;AACxD,aAAS,OAAO,KAAK,WAAW,KAAK;AACrC,UAAM,QAAQ,MAAM,OAAO,UAAU,QAAQ;AAC7C,UAAM,UAAuC;AAAA,MACzC,GAAG,KAAK;AAAA,MACR,OAAO,QAAQ,MAAM,WAAW;AAAA,QAAI,KAAK,WAAW;AAAA,QAAK,KAAK;AAAA,QAAO;AAAA,QAAO,KAAK,QAAQ;AAAA,QACrF,MAAM,WAAW,cAAc,KAAK,WAAW,KAAK,KAAK,QAAQ,OAAO,KAAK,aAAa;AAAA,MAAC,IAAI,KAAK,QAAQ;AAAA,MAChH,gBAAgB,QAAQ,WAAW,SAAS,MAAM,KAAK,SAAS,MAAM,KAChE,CAAC,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC,IAAI;AAAA,MAC7C,UAAU,KAAK,QAAQ,kBAAkB,IAAI,aAAa,YAAY,KAAK,WAAW,QAAQ;AAAA,IAClG;AACA,UAAM,MAAM,MAAM,KAAK,MAAM,SAAS,OAAQ,OAAO;AACrD,QAAI,oBAAoB,GAAG,KAAmB,IAAK,aAAa;AAC5D,WAAK,eAAe;AACpB,WAAK,mBAAmB;AAAA,IAC5B;AACA,QAAI,YAAY,QAAQ;AACxB,QAAI,YAAY,KAAK,QAAQ;AAC7B,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,MAAa,aAAa;AACtB,SAAK,iBAAiB,KAAK;AAC3B,SAAK,SAAS,CAAC;AACf,UAAM,KAAK,eAAe;AAAA,EAC9B;AAAA,EAWA,MAAa,SAAS,oBAAmD,OAAgB;AACrF,SAAK,UAAU,oBAAoB,KAAK;AACxC,UAAM,KAAK,eAAe;AAAA,EAC9B;AAAA,EAEU,UAAU,oBAAmD,OAAsB;AACzF,SAAK,iBAAiB,KAAK;AAC3B,QAAI,OAAO,UAAU,aAAa;AAC9B,UAAI,OAAO,uBAAuB,UAAU;AACxC,YAAI,uBAAuB,GAAI;AAC/B,cAAM,QAAQ,mBAAmB,MAAM,GAAG;AAC1C,iBAAS,KAAK,OAAO;AACjB,cAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;AACxB,eAAK,UAAU,GAAG,CAAC;AAAA,QACvB;AAAA,MACJ,WAAW,OAAO,uBAAuB,UAAU;AAC/C,iBAAS,KAAK,oBAAoB;AAC9B,eAAK,OAAO,CAAC,IAAI,mBAAmB,CAAC;AAAA,QACzC;AAAA,MACJ;AAAA,IACJ,OAAO;AACH,WAAK,OAAO,kBAA4B,IAAI;AAAA,IAChD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCA,2BAA2B,OAAe,UAAoB,UAAkB,OAAiB;AAC7F,UAAM,2BAA2B,OAAO,UAAU,UAAU,KAAK;AAAA,EACrE;AAAA,EAEA,YAAY,OAAe,SAAkB,IAAI,QAAQ,GAAY;AACjE,QAAI,CAAC,KAAK,YAAa,OAAM,IAAI,gBAAgB,yBAAyB;AAC1E,UAAM,QAAQ,KAAK,QAAQ,CAAC;AAC5B,QAAI,SAAS,cAAc,KAAK,GAAG;AAC/B,YAAM,YAAY,OAAO,MAAM;AAAA,IACnC,WAAW,SAAS,oBAAoB,KAAK,GAAG;AAC5C,YAAM,UAAU,MAAM;AAAA,IAC1B;AAUA,WAAO;AAAA,EACX;AAAA,EAEA,YAAY,OAAe,QAAiB;AACxC,QAAI,CAAC,KAAK,YAAa,OAAM,IAAI,gBAAgB,yBAAyB;AAE1E,aAAQ,SAAS,KAAK,SAAS;AAC3B,UAAI,SAAS,cAAc,KAAK,GAAG;AAC/B,cAAM,YAAY,OAAO,MAAM;AAAA,MACnC,WAAW,SAAS,oBAAoB,KAAK,GAAG;AAC5C,cAAM,UAAU,MAAM;AAAA,MAC1B;AAAA,IACJ;AAAA,EASJ;AAAA,EAEA,YAAY,UAAmB;AAC3B,SAAK,SAAS,KAAK,QAAQ;AAE3B,aAAS,SAAS,KAAK,SAAS;AAC5B,YAAM,YAAY,QAAQ;AAAA,IAC9B;AACA,SAAK,cAAc;AACnB,SAAK,YAAY;AAAA,EACrB;AAAA;AAAA;AAMJ;AAphBa,aAIc,kBAAsC,MAAM,CAAC,GAAG,YAAY,iBAAqC;AAAA,EACpH,mBAAmB;AACvB,CAAC;AANE,IAAM,cAAN;AAoiBA,SAAS,cAAc,KAA8B;AACxD,SAAqB,IAAK;AAC9B;","names":[]}
|
|
@@ -95,6 +95,23 @@ var itemContext = (withDisplayContext) => (value, path) => {
|
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
97
|
};
|
|
98
|
+
function entityAnimation(value, path) {
|
|
99
|
+
const animation = object(value, path);
|
|
100
|
+
if (["name", "clips"].filter((key) => animation[key] !== void 0).length !== 1) {
|
|
101
|
+
fail(path, "expected exactly one of name or clips");
|
|
102
|
+
}
|
|
103
|
+
fields(value, path, { name: text, clips: (value2, path2) => {
|
|
104
|
+
list((value3, path3) => {
|
|
105
|
+
fields(value3, path3, { name: text, weight: nonnegative }, ["name"]);
|
|
106
|
+
})(value2, path2);
|
|
107
|
+
if (!value2.length) fail(path2, "expected at least one clip");
|
|
108
|
+
const names = /* @__PURE__ */ new Set();
|
|
109
|
+
for (const [index, clip] of value2.entries()) {
|
|
110
|
+
if (names.has(clip.name)) fail(`${path2}[${index}].name`, `duplicate clip "${clip.name}"`);
|
|
111
|
+
names.add(clip.name);
|
|
112
|
+
}
|
|
113
|
+
}, loop: boolean, speed: nonnegative, time: nonnegative, paused: boolean });
|
|
114
|
+
}
|
|
98
115
|
function guiLayer(value, path) {
|
|
99
116
|
const layer = object(value, path);
|
|
100
117
|
if (["texture", "item", "text"].filter((key) => layer[key] !== void 0).length !== 1) {
|
|
@@ -135,13 +152,27 @@ function validateObject(value, path) {
|
|
|
135
152
|
const required = ["id", "type"];
|
|
136
153
|
const renderOptions = { wireframe: boolean };
|
|
137
154
|
switch (input.type) {
|
|
138
|
-
case "skin":
|
|
155
|
+
case "skin": {
|
|
156
|
+
const piece = (value2, path2) => {
|
|
157
|
+
if (typeof value2 === "string") asset(value2, path2);
|
|
158
|
+
else fields(value2, path2, {
|
|
159
|
+
asset,
|
|
160
|
+
color,
|
|
161
|
+
glint: boolean,
|
|
162
|
+
trim: (value3, path3) => {
|
|
163
|
+
fields(value3, path3, { pattern: asset, material: asset }, ["pattern", "material"]);
|
|
164
|
+
}
|
|
165
|
+
}, ["asset"]);
|
|
166
|
+
};
|
|
139
167
|
fields(value, path, {
|
|
140
168
|
...common,
|
|
141
169
|
skin: text,
|
|
142
170
|
cape: (value2, path2) => {
|
|
143
171
|
fields(value2, path2, { texture: text, layout: enumeration(["minecraft", "optifine", "labymod"]) }, ["texture"]);
|
|
144
172
|
},
|
|
173
|
+
armor: (value2, path2) => {
|
|
174
|
+
fields(value2, path2, { head: piece, chest: piece, legs: piece, feet: piece });
|
|
175
|
+
},
|
|
145
176
|
hiddenParts: list(enumeration(SKIN_PARTS)),
|
|
146
177
|
pose: (value2, path2) => {
|
|
147
178
|
fields(value2, path2, {
|
|
@@ -155,10 +186,11 @@ function validateObject(value, path) {
|
|
|
155
186
|
});
|
|
156
187
|
},
|
|
157
188
|
options: (value2, path2) => {
|
|
158
|
-
fields(value2, path2, { slim: boolean, legacy: boolean });
|
|
189
|
+
fields(value2, path2, { slim: boolean, legacy: boolean, ears: boolean, upsideDown: boolean });
|
|
159
190
|
}
|
|
160
191
|
}, required);
|
|
161
192
|
break;
|
|
193
|
+
}
|
|
162
194
|
case "block":
|
|
163
195
|
fields(value, path, {
|
|
164
196
|
...common,
|
|
@@ -197,9 +229,7 @@ function validateObject(value, path) {
|
|
|
197
229
|
})
|
|
198
230
|
});
|
|
199
231
|
},
|
|
200
|
-
animation:
|
|
201
|
-
fields(value2, path2, { name: text, loop: boolean, speed: nonnegative, time: nonnegative, paused: boolean }, ["name"]);
|
|
202
|
-
}
|
|
232
|
+
animation: entityAnimation
|
|
203
233
|
}, [...required, "asset"]);
|
|
204
234
|
if (Array.isArray(input.layers) && !input.layers.length) fail(`${path}.layers`, "expected at least one layer");
|
|
205
235
|
break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/scene/SceneDocument.ts"],"sourcesContent":["import type { CapeLayout } from \"../skin/CapeLayout\";\nimport { SKIN_PARTS } from \"../skin/SkinPart\";\nimport type { TripleArray } from \"../model/Model\";\nimport { DISPLAY_POSITIONS, DisplayPosition } from \"../model/DisplayPosition\";\nimport type { GuiItemLayer, GuiTextLayer, GuiTextureLayer } from \"../gui/GuiLayer\";\n\n/** Portable scene setup. Positions use model units (16 per block); rotations use radians. */\nexport interface SceneDocument {\n format: \"minerender-scene\";\n version: 1;\n minecraftVersion?: string;\n camera?: { position: TripleArray; target: TripleArray };\n objects: SceneObjectDefinition[];\n}\n\nexport interface SceneObjectDefinitionBase {\n id: string;\n name?: string;\n position?: TripleArray;\n rotation?: TripleArray;\n scale?: TripleArray;\n visible?: boolean;\n}\n\nexport type SceneSkinPosePart = \"head\" | \"body\" | \"rightArm\" | \"leftArm\" | \"rightLeg\" | \"leftLeg\" | \"cape\";\n\nexport interface SceneSkinDefinition extends SceneObjectDefinitionBase {\n type: \"skin\";\n /** Texture URL, Minecraft username, or UUID. Omit for Steve, or Alex with slim: true, from the active asset version. */\n skin?: string;\n cape?: { texture: string; layout?: CapeLayout };\n options?: { slim?: boolean; legacy?: boolean };\n /** Mesh names from SkinPart; hiding a base part does not hide its overlay. */\n hiddenParts?: string[];\n /** Absolute local XYZ joint rotations in radians; omitted joints keep their default pose. */\n pose?: Partial<Record<SceneSkinPosePart, TripleArray>>;\n}\n\nexport interface SceneBlockDefinition extends SceneObjectDefinitionBase {\n type: \"block\";\n asset: string;\n state?: Record<string, string>;\n options?: { wireframe?: boolean; tints?: Record<number, number> };\n}\n\n/** Supplied item state; see ItemModelContext. Item references are item IDs such as minecraft:apple. */\nexport interface SceneItemContext {\n displayContext?: DisplayPosition | \"none\";\n properties?: Record<string, boolean | string | number>;\n components?: Record<string, unknown>;\n count?: number;\n itemReferences?: Record<string, string>;\n}\n\nexport interface SceneModelDefinition extends SceneObjectDefinitionBase {\n type: \"item\" | \"model\";\n asset: string;\n options?: { wireframe?: boolean; displayPosition?: DisplayPosition; tints?: Record<number, number> };\n /** Item state for `type: \"item\"` definitions only. */\n context?: SceneItemContext;\n}\n\nexport interface SceneEntityDefinition extends SceneObjectDefinitionBase {\n type: \"entity\";\n asset: string;\n texture?: string;\n layers?: string[];\n when?: string[];\n textures?: Record<string, string>;\n options?: { flip?: boolean; wireframe?: boolean; tints?: Record<string, string | number> };\n animation?: { name: string; loop?: boolean; speed?: number; time?: number; paused?: boolean };\n}\n\nexport type SceneGuiLayer = (Omit<GuiTextureLayer, \"texture\"> & { texture: string })\n | (Omit<GuiItemLayer, \"item\" | \"context\"> & { item: string; context?: Omit<SceneItemContext, \"displayContext\"> })\n | (Omit<GuiTextLayer, \"font\"> & { font?: string });\n\nexport interface SceneGuiDefinition extends SceneObjectDefinitionBase {\n type: \"gui\";\n layers: SceneGuiLayer[];\n}\n\nexport type SceneObjectDefinition = SceneSkinDefinition | SceneBlockDefinition | SceneModelDefinition\n | SceneEntityDefinition | SceneGuiDefinition;\n\ntype JsonObject = Record<string, unknown>;\ntype Validator = (value: unknown, path: string) => void;\n\nfunction fail(path: string, message: string): never {\n throw new Error(`${path}: ${message}`);\n}\n\nfunction object(value: unknown, path: string): JsonObject {\n if (!value || typeof value !== \"object\" || Array.isArray(value)\n || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) fail(path, \"expected a JSON object\");\n for (const key of Object.keys(value)) {\n if ([\"__proto__\", \"prototype\", \"constructor\"].includes(key)) fail(`${path}.${key}`, \"unsupported property\");\n }\n return value as JsonObject;\n}\n\nfunction fields(value: unknown, path: string, allowed: Record<string, Validator>, required: string[] = []): JsonObject {\n const input = object(value, path);\n for (const key of required) if (input[key] === undefined) fail(`${path}.${key}`, \"required\");\n for (const [key, entry] of Object.entries(input)) {\n if (!Object.prototype.hasOwnProperty.call(allowed, key)) fail(`${path}.${key}`, \"unsupported property\");\n if (entry !== undefined) allowed[key](entry, `${path}.${key}`);\n }\n return input;\n}\n\nconst text: Validator = (value, path) => {\n if (typeof value !== \"string\" || !value.trim()) fail(path, \"expected a nonempty string\");\n};\nconst literalText: Validator = (value, path) => {\n if (typeof value !== \"string\") fail(path, \"expected a string\");\n};\nconst boolean: Validator = (value, path) => {\n if (typeof value !== \"boolean\") fail(path, \"expected a boolean\");\n};\nconst number: Validator = (value, path) => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) fail(path, \"expected a finite number\");\n};\nconst positive: Validator = (value, path) => {\n number(value, path);\n if ((value as number) <= 0) fail(path, \"expected a positive number\");\n};\nconst nonnegative: Validator = (value, path) => {\n number(value, path);\n if ((value as number) < 0) fail(path, \"expected a nonnegative number\");\n};\nconst color: Validator = (value, path) => {\n number(value, path);\n if (!Number.isInteger(value) || (value as number) < 0 || (value as number) > 0xffffff) {\n fail(path, \"expected an RGB integer from 0 to 16777215\");\n }\n};\nconst asset: Validator = (value, path) => {\n text(value, path);\n if (!/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(value as string)\n || (value as string).split(/[:/]/).some(part => !part || part === \".\" || part === \"..\")) {\n fail(path, \"expected a resource ID such as minecraft:stone\");\n }\n};\nconst version: Validator = (value, path) => {\n text(value, path);\n if (!/^[a-zA-Z0-9._-]+$/.test(value as string)) fail(path, \"expected a Minecraft version without slashes\");\n};\nconst tuple = (size: number, item: Validator = number): Validator => (value, path) => {\n if (!Array.isArray(value) || value.length !== size) fail(path, `expected ${size} numbers`);\n for (let index = 0; index < size; index++) item(value[index], `${path}[${index}]`);\n};\nconst list = (item: Validator): Validator => (value, path) => {\n if (!Array.isArray(value)) fail(path, \"expected an array\");\n for (let index = 0; index < value.length; index++) item(value[index], `${path}[${index}]`);\n};\nconst dictionary = (item: Validator, numericKeys = false): Validator => (value, path) => {\n for (const [key, entry] of Object.entries(object(value, path))) {\n if (numericKeys && !/^\\d+$/.test(key)) fail(`${path}.${key}`, \"expected a nonnegative tint index\");\n item(entry, `${path}.${key}`);\n }\n};\nconst enumeration = (values: readonly string[]): Validator => (value, path) => {\n if (!values.includes(value as string)) fail(path, `expected one of: ${values.join(\", \")}`);\n};\nconst textStyle = { color, bold: boolean, italic: boolean };\nconst jsonValue: Validator = (value, path) => {\n if (value === null || typeof value === \"boolean\" || typeof value === \"string\") return;\n if (typeof value === \"number\") number(value, path);\n else if (Array.isArray(value)) list(jsonValue)(value, path);\n else dictionary(jsonValue)(value, path);\n};\nconst propertyValue: Validator = (value, path) => {\n if (typeof value === \"boolean\" || typeof value === \"string\") return;\n if (typeof value !== \"number\" || !Number.isFinite(value)) fail(path, \"expected a boolean, string, or finite number\");\n};\nconst itemContext = (withDisplayContext: boolean): Validator => (value, path) => {\n fields(value, path, {\n ...(withDisplayContext ? { displayContext: enumeration([...DISPLAY_POSITIONS, \"none\"]) } : {}),\n properties: dictionary(propertyValue), components: dictionary(jsonValue), itemReferences: dictionary(asset),\n count: (value, path) => { if (!Number.isInteger(value) || (value as number) < 0) fail(path, \"expected a nonnegative integer\"); }\n });\n};\n\nfunction guiLayer(value: unknown, path: string): void {\n const layer = object(value, path);\n if ([\"texture\", \"item\", \"text\"].filter(key => layer[key] !== undefined).length !== 1) {\n fail(path, \"expected exactly one of texture, item, or text\");\n }\n const layout = { name: text, position: tuple(2), size: tuple(2, positive) };\n if (layer.texture !== undefined) {\n fields(value, path, { ...layout, texture: asset, crop: (value, path) => {\n tuple(4)(value, path);\n const [x, y, width, height] = value as number[];\n nonnegative(x, `${path}[0]`); nonnegative(y, `${path}[1]`);\n positive(width, `${path}[2]`); positive(height, `${path}[3]`);\n } });\n } else if (layer.item !== undefined) {\n fields(value, path, { ...layout, item: asset, context: itemContext(false), tints: dictionary(color, true) });\n } else {\n fields(value, path, { ...layout, ...textStyle, font: asset, shadow: boolean, maxWidth: positive, lineHeight: positive,\n text: (value, path) => {\n if (typeof value === \"string\") return;\n list((run, path) => { fields(run, path, { text: literalText, ...textStyle }, [\"text\"]); })(value, path);\n }\n });\n }\n}\n\nfunction validateObject(value: unknown, path: string): void {\n const input = object(value, path);\n const common = { id: text, name: text, type: text, position: tuple(3), rotation: tuple(3), scale: tuple(3), visible: boolean };\n const required = [\"id\", \"type\"];\n const renderOptions = { wireframe: boolean };\n switch (input.type) {\n case \"skin\":\n fields(value, path, { ...common, skin: text,\n cape: (value, path) => { fields(value, path, { texture: text, layout: enumeration([\"minecraft\", \"optifine\", \"labymod\"]) }, [\"texture\"]); },\n hiddenParts: list(enumeration(SKIN_PARTS)),\n pose: (value, path) => { fields(value, path, {\n head: tuple(3), body: tuple(3), rightArm: tuple(3), leftArm: tuple(3),\n rightLeg: tuple(3), leftLeg: tuple(3), cape: tuple(3)\n }); },\n options: (value, path) => { fields(value, path, { slim: boolean, legacy: boolean }); }\n }, required);\n break;\n case \"block\":\n fields(value, path, { ...common, asset, state: dictionary(text),\n options: (value, path) => { fields(value, path, { ...renderOptions, tints: dictionary(color, true) }); }\n }, [...required, \"asset\"]);\n break;\n case \"item\":\n case \"model\":\n fields(value, path, { ...common, asset, ...(input.type === \"item\" ? { context: itemContext(true) } : {}),\n options: (value, path) => { fields(value, path, { ...renderOptions, displayPosition: enumeration(DISPLAY_POSITIONS), tints: dictionary(color, true) }); }\n }, [...required, \"asset\"]);\n break;\n case \"entity\":\n fields(value, path, { ...common, asset, texture: asset, layers: list(text), when: list(text), textures: dictionary(asset),\n options: (value, path) => { fields(value, path, { ...renderOptions, flip: boolean,\n tints: dictionary((value, path) => { typeof value === \"string\" ? text(value, path) : color(value, path); }) }); },\n animation: (value, path) => { fields(value, path, { name: text, loop: boolean, speed: nonnegative, time: nonnegative, paused: boolean }, [\"name\"]); }\n }, [...required, \"asset\"]);\n if (Array.isArray(input.layers) && !input.layers.length) fail(`${path}.layers`, \"expected at least one layer\");\n break;\n case \"gui\":\n fields(value, path, { ...common, layers: list(guiLayer) }, [...required, \"layers\"]);\n break;\n default:\n fail(`${path}.type`, \"expected skin, block, item, entity, model, or gui\");\n }\n}\n\n/** Validates and copies a scene document without requesting assets or changing the active asset version. */\nexport function parseSceneDocument(value: unknown): SceneDocument {\n if (typeof value === \"string\") {\n try { value = JSON.parse(value); }\n catch { fail(\"scene\", \"invalid JSON\"); }\n }\n const input = fields(value, \"scene\", {\n format: enumeration([\"minerender-scene\"]),\n version: (value, path) => { if (value !== 1) fail(path, \"only scene document version 1 is supported\"); },\n minecraftVersion: version,\n camera: (value, path) => { fields(value, path, { position: tuple(3), target: tuple(3) }, [\"position\", \"target\"]); },\n objects: list(validateObject)\n }, [\"format\", \"version\", \"objects\"]);\n const ids = new Set<string>();\n for (const [index, entry] of (input.objects as SceneObjectDefinition[]).entries()) {\n if (ids.has(entry.id)) fail(`scene.objects[${index}].id`, `duplicate object ID \"${entry.id}\"`);\n ids.add(entry.id);\n }\n return JSON.parse(JSON.stringify(input)) as SceneDocument;\n}\n"],"mappings":"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","names":["value","path"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/scene/SceneDocument.ts"],"sourcesContent":["import type { CapeLayout } from \"../skin/CapeLayout\";\nimport type { ArmorSet } from \"../armor/Armor\";\nimport { SKIN_PARTS } from \"../skin/SkinPart\";\nimport type { TripleArray } from \"../model/Model\";\nimport { DISPLAY_POSITIONS, DisplayPosition } from \"../model/DisplayPosition\";\nimport type { GuiItemLayer, GuiTextLayer, GuiTextureLayer } from \"../gui/GuiLayer\";\n\n/** Portable scene setup. Positions use model units (16 per block); rotations use radians. */\nexport interface SceneDocument {\n format: \"minerender-scene\";\n version: 1;\n minecraftVersion?: string;\n camera?: { position: TripleArray; target: TripleArray };\n objects: SceneObjectDefinition[];\n}\n\nexport interface SceneObjectDefinitionBase {\n id: string;\n name?: string;\n position?: TripleArray;\n rotation?: TripleArray;\n scale?: TripleArray;\n visible?: boolean;\n}\n\nexport type SceneSkinPosePart = \"head\" | \"body\" | \"rightArm\" | \"leftArm\" | \"rightLeg\" | \"leftLeg\" | \"cape\";\n\nexport interface SceneSkinDefinition extends SceneObjectDefinitionBase {\n type: \"skin\";\n /** Texture URL, Minecraft username, or UUID. Omit for Steve, or Alex with slim: true, from the active asset version. */\n skin?: string;\n cape?: { texture: string; layout?: CapeLayout };\n armor?: ArmorSet;\n options?: { slim?: boolean; legacy?: boolean; ears?: boolean; upsideDown?: boolean };\n /** Mesh names from SkinPart; hiding a base part does not hide its overlay. */\n hiddenParts?: string[];\n /** Absolute local XYZ joint rotations in radians; omitted joints keep their default pose. */\n pose?: Partial<Record<SceneSkinPosePart, TripleArray>>;\n}\n\nexport interface SceneBlockDefinition extends SceneObjectDefinitionBase {\n type: \"block\";\n asset: string;\n state?: Record<string, string>;\n options?: { wireframe?: boolean; tints?: Record<number, number> };\n}\n\n/** Supplied item state; see ItemModelContext. Item references are item IDs such as minecraft:apple. */\nexport interface SceneItemContext {\n displayContext?: DisplayPosition | \"none\";\n properties?: Record<string, boolean | string | number>;\n components?: Record<string, unknown>;\n count?: number;\n itemReferences?: Record<string, string>;\n}\n\nexport interface SceneModelDefinition extends SceneObjectDefinitionBase {\n type: \"item\" | \"model\";\n asset: string;\n options?: { wireframe?: boolean; displayPosition?: DisplayPosition; tints?: Record<number, number> };\n /** Item state for `type: \"item\"` definitions only. */\n context?: SceneItemContext;\n}\n\nexport interface SceneEntityDefinition extends SceneObjectDefinitionBase {\n type: \"entity\";\n asset: string;\n texture?: string;\n layers?: string[];\n when?: string[];\n textures?: Record<string, string>;\n options?: { flip?: boolean; wireframe?: boolean; tints?: Record<string, string | number> };\n /** Plays one named clip or blends clips with weights defaulting to 1, without normalization. */\n animation?: ({ name: string; clips?: never } | { name?: never; clips: { name: string; weight?: number }[] })\n & { loop?: boolean; speed?: number; time?: number; paused?: boolean };\n}\n\nexport type SceneGuiLayer = (Omit<GuiTextureLayer, \"texture\"> & { texture: string })\n | (Omit<GuiItemLayer, \"item\" | \"context\"> & { item: string; context?: Omit<SceneItemContext, \"displayContext\"> })\n | (Omit<GuiTextLayer, \"font\"> & { font?: string });\n\nexport interface SceneGuiDefinition extends SceneObjectDefinitionBase {\n type: \"gui\";\n layers: SceneGuiLayer[];\n}\n\nexport type SceneObjectDefinition = SceneSkinDefinition | SceneBlockDefinition | SceneModelDefinition\n | SceneEntityDefinition | SceneGuiDefinition;\n\ntype JsonObject = Record<string, unknown>;\ntype Validator = (value: unknown, path: string) => void;\n\nfunction fail(path: string, message: string): never {\n throw new Error(`${path}: ${message}`);\n}\n\nfunction object(value: unknown, path: string): JsonObject {\n if (!value || typeof value !== \"object\" || Array.isArray(value)\n || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) fail(path, \"expected a JSON object\");\n for (const key of Object.keys(value)) {\n if ([\"__proto__\", \"prototype\", \"constructor\"].includes(key)) fail(`${path}.${key}`, \"unsupported property\");\n }\n return value as JsonObject;\n}\n\nfunction fields(value: unknown, path: string, allowed: Record<string, Validator>, required: string[] = []): JsonObject {\n const input = object(value, path);\n for (const key of required) if (input[key] === undefined) fail(`${path}.${key}`, \"required\");\n for (const [key, entry] of Object.entries(input)) {\n if (!Object.prototype.hasOwnProperty.call(allowed, key)) fail(`${path}.${key}`, \"unsupported property\");\n if (entry !== undefined) allowed[key](entry, `${path}.${key}`);\n }\n return input;\n}\n\nconst text: Validator = (value, path) => {\n if (typeof value !== \"string\" || !value.trim()) fail(path, \"expected a nonempty string\");\n};\nconst literalText: Validator = (value, path) => {\n if (typeof value !== \"string\") fail(path, \"expected a string\");\n};\nconst boolean: Validator = (value, path) => {\n if (typeof value !== \"boolean\") fail(path, \"expected a boolean\");\n};\nconst number: Validator = (value, path) => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) fail(path, \"expected a finite number\");\n};\nconst positive: Validator = (value, path) => {\n number(value, path);\n if ((value as number) <= 0) fail(path, \"expected a positive number\");\n};\nconst nonnegative: Validator = (value, path) => {\n number(value, path);\n if ((value as number) < 0) fail(path, \"expected a nonnegative number\");\n};\nconst color: Validator = (value, path) => {\n number(value, path);\n if (!Number.isInteger(value) || (value as number) < 0 || (value as number) > 0xffffff) {\n fail(path, \"expected an RGB integer from 0 to 16777215\");\n }\n};\nconst asset: Validator = (value, path) => {\n text(value, path);\n if (!/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(value as string)\n || (value as string).split(/[:/]/).some(part => !part || part === \".\" || part === \"..\")) {\n fail(path, \"expected a resource ID such as minecraft:stone\");\n }\n};\nconst version: Validator = (value, path) => {\n text(value, path);\n if (!/^[a-zA-Z0-9._-]+$/.test(value as string)) fail(path, \"expected a Minecraft version without slashes\");\n};\nconst tuple = (size: number, item: Validator = number): Validator => (value, path) => {\n if (!Array.isArray(value) || value.length !== size) fail(path, `expected ${size} numbers`);\n for (let index = 0; index < size; index++) item(value[index], `${path}[${index}]`);\n};\nconst list = (item: Validator): Validator => (value, path) => {\n if (!Array.isArray(value)) fail(path, \"expected an array\");\n for (let index = 0; index < value.length; index++) item(value[index], `${path}[${index}]`);\n};\nconst dictionary = (item: Validator, numericKeys = false): Validator => (value, path) => {\n for (const [key, entry] of Object.entries(object(value, path))) {\n if (numericKeys && !/^\\d+$/.test(key)) fail(`${path}.${key}`, \"expected a nonnegative tint index\");\n item(entry, `${path}.${key}`);\n }\n};\nconst enumeration = (values: readonly string[]): Validator => (value, path) => {\n if (!values.includes(value as string)) fail(path, `expected one of: ${values.join(\", \")}`);\n};\nconst textStyle = { color, bold: boolean, italic: boolean };\nconst jsonValue: Validator = (value, path) => {\n if (value === null || typeof value === \"boolean\" || typeof value === \"string\") return;\n if (typeof value === \"number\") number(value, path);\n else if (Array.isArray(value)) list(jsonValue)(value, path);\n else dictionary(jsonValue)(value, path);\n};\nconst propertyValue: Validator = (value, path) => {\n if (typeof value === \"boolean\" || typeof value === \"string\") return;\n if (typeof value !== \"number\" || !Number.isFinite(value)) fail(path, \"expected a boolean, string, or finite number\");\n};\nconst itemContext = (withDisplayContext: boolean): Validator => (value, path) => {\n fields(value, path, {\n ...(withDisplayContext ? { displayContext: enumeration([...DISPLAY_POSITIONS, \"none\"]) } : {}),\n properties: dictionary(propertyValue), components: dictionary(jsonValue), itemReferences: dictionary(asset),\n count: (value, path) => { if (!Number.isInteger(value) || (value as number) < 0) fail(path, \"expected a nonnegative integer\"); }\n });\n};\n\nfunction entityAnimation(value: unknown, path: string): void {\n const animation = object(value, path);\n if ([\"name\", \"clips\"].filter(key => animation[key] !== undefined).length !== 1) {\n fail(path, \"expected exactly one of name or clips\");\n }\n fields(value, path, { name: text, clips: (value, path) => {\n list((value, path) => { fields(value, path, { name: text, weight: nonnegative }, [\"name\"]); })(value, path);\n if (!(value as unknown[]).length) fail(path, \"expected at least one clip\");\n const names = new Set<string>();\n for (const [index, clip] of (value as { name: string }[]).entries()) {\n if (names.has(clip.name)) fail(`${path}[${index}].name`, `duplicate clip \"${clip.name}\"`);\n names.add(clip.name);\n }\n }, loop: boolean, speed: nonnegative, time: nonnegative, paused: boolean });\n}\n\nfunction guiLayer(value: unknown, path: string): void {\n const layer = object(value, path);\n if ([\"texture\", \"item\", \"text\"].filter(key => layer[key] !== undefined).length !== 1) {\n fail(path, \"expected exactly one of texture, item, or text\");\n }\n const layout = { name: text, position: tuple(2), size: tuple(2, positive) };\n if (layer.texture !== undefined) {\n fields(value, path, { ...layout, texture: asset, crop: (value, path) => {\n tuple(4)(value, path);\n const [x, y, width, height] = value as number[];\n nonnegative(x, `${path}[0]`); nonnegative(y, `${path}[1]`);\n positive(width, `${path}[2]`); positive(height, `${path}[3]`);\n } });\n } else if (layer.item !== undefined) {\n fields(value, path, { ...layout, item: asset, context: itemContext(false), tints: dictionary(color, true) });\n } else {\n fields(value, path, { ...layout, ...textStyle, font: asset, shadow: boolean, maxWidth: positive, lineHeight: positive,\n text: (value, path) => {\n if (typeof value === \"string\") return;\n list((run, path) => { fields(run, path, { text: literalText, ...textStyle }, [\"text\"]); })(value, path);\n }\n });\n }\n}\n\nfunction validateObject(value: unknown, path: string): void {\n const input = object(value, path);\n const common = { id: text, name: text, type: text, position: tuple(3), rotation: tuple(3), scale: tuple(3), visible: boolean };\n const required = [\"id\", \"type\"];\n const renderOptions = { wireframe: boolean };\n switch (input.type) {\n case \"skin\": {\n const piece: Validator = (value, path) => {\n if (typeof value === \"string\") asset(value, path);\n else fields(value, path, { asset, color, glint: boolean,\n trim: (value, path) => { fields(value, path, { pattern: asset, material: asset }, [\"pattern\", \"material\"]); }\n }, [\"asset\"]);\n };\n fields(value, path, { ...common, skin: text,\n cape: (value, path) => { fields(value, path, { texture: text, layout: enumeration([\"minecraft\", \"optifine\", \"labymod\"]) }, [\"texture\"]); },\n armor: (value, path) => { fields(value, path, { head: piece, chest: piece, legs: piece, feet: piece }); },\n hiddenParts: list(enumeration(SKIN_PARTS)),\n pose: (value, path) => { fields(value, path, {\n head: tuple(3), body: tuple(3), rightArm: tuple(3), leftArm: tuple(3),\n rightLeg: tuple(3), leftLeg: tuple(3), cape: tuple(3)\n }); },\n options: (value, path) => { fields(value, path, { slim: boolean, legacy: boolean, ears: boolean, upsideDown: boolean }); }\n }, required);\n break;\n }\n case \"block\":\n fields(value, path, { ...common, asset, state: dictionary(text),\n options: (value, path) => { fields(value, path, { ...renderOptions, tints: dictionary(color, true) }); }\n }, [...required, \"asset\"]);\n break;\n case \"item\":\n case \"model\":\n fields(value, path, { ...common, asset, ...(input.type === \"item\" ? { context: itemContext(true) } : {}),\n options: (value, path) => { fields(value, path, { ...renderOptions, displayPosition: enumeration(DISPLAY_POSITIONS), tints: dictionary(color, true) }); }\n }, [...required, \"asset\"]);\n break;\n case \"entity\":\n fields(value, path, { ...common, asset, texture: asset, layers: list(text), when: list(text), textures: dictionary(asset),\n options: (value, path) => { fields(value, path, { ...renderOptions, flip: boolean,\n tints: dictionary((value, path) => { typeof value === \"string\" ? text(value, path) : color(value, path); }) }); },\n animation: entityAnimation\n }, [...required, \"asset\"]);\n if (Array.isArray(input.layers) && !input.layers.length) fail(`${path}.layers`, \"expected at least one layer\");\n break;\n case \"gui\":\n fields(value, path, { ...common, layers: list(guiLayer) }, [...required, \"layers\"]);\n break;\n default:\n fail(`${path}.type`, \"expected skin, block, item, entity, model, or gui\");\n }\n}\n\n/** Validates and copies a scene document without requesting assets or changing the active asset version. */\nexport function parseSceneDocument(value: unknown): SceneDocument {\n if (typeof value === \"string\") {\n try { value = JSON.parse(value); }\n catch { fail(\"scene\", \"invalid JSON\"); }\n }\n const input = fields(value, \"scene\", {\n format: enumeration([\"minerender-scene\"]),\n version: (value, path) => { if (value !== 1) fail(path, \"only scene document version 1 is supported\"); },\n minecraftVersion: version,\n camera: (value, path) => { fields(value, path, { position: tuple(3), target: tuple(3) }, [\"position\", \"target\"]); },\n objects: list(validateObject)\n }, [\"format\", \"version\", \"objects\"]);\n const ids = new Set<string>();\n for (const [index, entry] of (input.objects as SceneObjectDefinition[]).entries()) {\n if (ids.has(entry.id)) fail(`scene.objects[${index}].id`, `duplicate object ID \"${entry.id}\"`);\n ids.add(entry.id);\n }\n return JSON.parse(JSON.stringify(input)) as SceneDocument;\n}\n"],"mappings":"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","names":["value","path"]}
|
|
@@ -123,6 +123,7 @@ var SceneDocumentLoader = class {
|
|
|
123
123
|
await skin.setSkinTexture(texture);
|
|
124
124
|
await content.initialize(skin);
|
|
125
125
|
if (definition.cape) await skin.setCapeTexture(await skinTexture(definition.cape.texture, true), definition.cape.layout);
|
|
126
|
+
if (definition.armor) await skin.setArmor(definition.armor);
|
|
126
127
|
for (const [part, rotation] of Object.entries(definition.pose ?? {})) {
|
|
127
128
|
skin.getGroupByName(part)?.rotation.set(...rotation, "XYZ");
|
|
128
129
|
}
|
|
@@ -161,10 +162,20 @@ var SceneDocumentLoader = class {
|
|
|
161
162
|
const entity = await content.addEntity(model, { ...definition.options, instanceMeshes: false });
|
|
162
163
|
object = entity;
|
|
163
164
|
if (definition.animation) {
|
|
165
|
+
const animation = definition.animation;
|
|
164
166
|
const animations = await Entities.getAnimations(key);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
167
|
+
if (animation.name !== void 0) {
|
|
168
|
+
const clip = animations && Object.prototype.hasOwnProperty.call(animations, animation.name) ? animations[animation.name] : void 0;
|
|
169
|
+
if (!clip) throw new Error(`Entity ${definition.asset} has no animation "${animation.name}"`);
|
|
170
|
+
entity.playAnimation(clip, animation);
|
|
171
|
+
} else {
|
|
172
|
+
const clips = animation.clips.map(({ name }) => {
|
|
173
|
+
const clip = animations && Object.prototype.hasOwnProperty.call(animations, name) ? animations[name] : void 0;
|
|
174
|
+
if (!clip) throw new Error(`Entity ${definition.asset} has no animation "${name}"`);
|
|
175
|
+
return clip;
|
|
176
|
+
});
|
|
177
|
+
entity.playAnimations(clips, { ...animation, weights: animation.clips.map((clip) => clip.weight ?? 1) });
|
|
178
|
+
}
|
|
168
179
|
}
|
|
169
180
|
break;
|
|
170
181
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/scene/SceneDocumentLoader.ts"],"sourcesContent":["import { Group } from \"three\";\nimport type { Object3D } from \"three\";\nimport { AssetKey } from \"../assets/AssetKey\";\nimport { AssetLoader } from \"../assets/AssetLoader\";\nimport { BlockStates } from \"../assets/BlockStates\";\nimport { Entities } from \"../assets/Entities\";\nimport { ItemModelContext, Models } from \"../assets/Models\";\nimport type { BasicMinecraftAsset } from \"../MinecraftAsset\";\nimport { DisplayPosition } from \"../model/DisplayPosition\";\nimport { MineRenderScene } from \"../renderer/MineRenderScene\";\nimport { isSceneObject, SceneObject } from \"../renderer/SceneObject\";\nimport type { SceneObjectOptions } from \"../renderer/SceneObjectOptions\";\nimport { EntityObject } from \"../entity/scene/EntityObject\";\nimport { SkinObject } from \"../skin/scene/SkinObject\";\nimport { Skins } from \"../skin/Skins\";\nimport { GuiObject } from \"../gui/scene/GuiObject\";\nimport type { GuiLayer } from \"../gui/GuiLayer\";\nimport { parseSceneDocument, SceneDocument, SceneItemContext, SceneObjectDefinition } from \"./SceneDocument\";\n\nfunction itemKey(asset: string): AssetKey {\n const key = AssetKey.parse(\"models\", asset);\n return key.type === \"item\" ? key : new AssetKey(key.namespace, key.getFullPath(), \"models\", \"item\");\n}\n\nfunction itemContext(context: SceneItemContext | undefined): ItemModelContext {\n const { itemReferences, ...rest } = context ?? {};\n return itemReferences\n ? { ...rest, itemReferences: Object.fromEntries(Object.entries(itemReferences).map(([id, item]) => [id, itemKey(item)])) }\n : rest;\n}\n\nexport interface LoadedSceneObject {\n readonly root: Group;\n readonly object: SceneObject;\n readonly definition: SceneObjectDefinition;\n /** Advances entity playback in seconds unless the definition has paused it. */\n advanceAnimation(delta: number): void;\n /** Removes this object and releases its owned resources. Safe to call more than once. */\n dispose(): void;\n}\n\nexport interface LoadedSceneDocument {\n readonly root: Group;\n readonly objects: LoadedSceneObject[];\n readonly definition: SceneDocument;\n advanceAnimations(delta: number): void;\n dispose(): void;\n}\n\n// Blocks create models and block entities through their scene, without forwarding a parent.\n// A nested scene keeps those visuals inside the object's transform group, including after state changes.\nclass DocumentObjectScene extends MineRenderScene {\n public async addSceneObject<A extends BasicMinecraftAsset, T extends SceneObject, O extends SceneObjectOptions>(\n _asset: A, supplier: () => T | Promise<T>, _options?: Partial<O>, parent: Object3D = this\n ): Promise<T> {\n const object = await supplier();\n return this.initialize(object, parent);\n }\n\n public async initialize<T extends SceneObject>(object: T, parent: Object3D = this): Promise<T> {\n object.scene = this;\n try {\n await object.init();\n parent.add(object);\n return object;\n } catch (error) {\n object.dispose();\n object.removeFromParent();\n throw error;\n }\n }\n\n public dispose(): void {\n for (const child of [...this.children]) {\n if (child.parent !== this) continue;\n if (isSceneObject(child)) child.dispose();\n child.removeFromParent();\n }\n }\n}\n\nasync function skinTexture(value: string, cape = false): Promise<string> {\n if (!/^[a-zA-Z0-9_-]{1,36}$/.test(value)) return value;\n const texture = await (cape ? Skins.capeFromUuidOrUsername(value) : Skins.fromUuidOrUsername(value));\n if (!texture) throw new Error(`Could not find ${cape ? \"cape\" : \"skin\"} for \"${value}\"`);\n return texture;\n}\n\n/** Loads portable scene documents using the asset sources already configured by the caller. */\nexport class SceneDocumentLoader {\n public static parse(value: unknown): SceneDocument {\n return parseSceneDocument(value);\n }\n\n /**\n * Loads objects concurrently and attaches them in document order after every load succeeds.\n * A failure waits for all loads, disposes staged objects, and reports the first error in document order.\n */\n public static async load(scene: MineRenderScene, value: unknown, parent: Object3D = scene): Promise<LoadedSceneDocument> {\n const definition = this.parse(value);\n if (definition.minecraftVersion !== undefined && definition.minecraftVersion !== AssetLoader.version) {\n throw new Error(`Scene requires Minecraft ${definition.minecraftVersion}; call AssetLoader.setVersion(\"${definition.minecraftVersion}\") before loading it`);\n }\n const root = new Group();\n root.name = \"MineRender scene document\";\n const objects: LoadedSceneObject[] = [];\n let disposed = false;\n const loaded: LoadedSceneDocument = {\n root, objects, definition,\n advanceAnimations: delta => { if (!disposed) for (const object of objects) object.advanceAnimation(delta); },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n root.removeFromParent();\n for (const object of objects) object.dispose();\n root.clear();\n scene.dirty = true;\n }\n };\n try {\n const results = await Promise.allSettled(definition.objects.map(object => this.loadValidatedObject(scene, object)));\n for (const result of results) if (result.status === \"fulfilled\") objects.push(result.value);\n const failure = results.find((result): result is PromiseRejectedResult => result.status === \"rejected\");\n if (failure) throw failure.reason;\n for (const object of objects) root.add(object.root);\n parent.add(root);\n scene.dirty = true;\n return loaded;\n } catch (error) {\n loaded.dispose();\n throw error;\n }\n }\n\n /** Loads an independently editable object. Its root owns the document's position, rotation, and scale. */\n public static async loadObject(scene: MineRenderScene, value: SceneObjectDefinition, parent: Object3D = scene): Promise<LoadedSceneObject> {\n const definition = this.parse({ format: \"minerender-scene\", version: 1, objects: [value] }).objects[0];\n return this.loadValidatedObject(scene, definition, parent);\n }\n\n private static async loadValidatedObject(scene: MineRenderScene, definition: SceneObjectDefinition, parent?: Object3D): Promise<LoadedSceneObject> {\n const root = new Group();\n root.name = definition.name ?? definition.id;\n root.userData.sceneObjectId = definition.id;\n root.position.fromArray(definition.position ?? [0, 0, 0]);\n root.rotation.set(...(definition.rotation ?? [0, 0, 0]));\n root.scale.fromArray(definition.scale ?? [1, 1, 1]);\n root.visible = definition.visible ?? true;\n const content = new DocumentObjectScene();\n root.add(content);\n let object: SceneObject | undefined;\n try {\n switch (definition.type) {\n case \"skin\": {\n const skin = new SkinObject({ ...definition.options, instanceMeshes: false });\n object = skin;\n const texture = definition.skin ? await skinTexture(definition.skin)\n : `${AssetLoader.ROOT}/assets/minecraft/textures/entity/player/${definition.options?.slim ? \"slim/alex\" : \"wide/steve\"}.png`;\n await skin.setSkinTexture(texture);\n await content.initialize(skin);\n if (definition.cape) await skin.setCapeTexture(await skinTexture(definition.cape.texture, true), definition.cape.layout);\n for (const [part, rotation] of Object.entries(definition.pose ?? {})) {\n skin.getGroupByName(part)?.rotation.set(...rotation, \"XYZ\");\n }\n for (const part of definition.hiddenParts ?? []) {\n const mesh = skin.getMeshByName(part);\n if (mesh) mesh.visible = false;\n }\n break;\n }\n case \"block\": {\n const state = await BlockStates.get(AssetKey.parse(\"blockstates\", definition.asset));\n if (!state) throw new Error(`Could not load block ${definition.asset}`);\n object = await content.addBlock(state, { ...definition.options, initialState: definition.state, instanceMeshes: false }) as SceneObject;\n break;\n }\n case \"item\":\n case \"model\": {\n const key = definition.type === \"item\" ? itemKey(definition.asset) : AssetKey.parse(\"models\", definition.asset);\n const model = await Models.getMerged(key, definition.type === \"item\" ? itemContext(definition.context) : {});\n if (!model) throw new Error(`Could not load ${definition.type} ${definition.asset}`);\n object = await content.addModel(model, { ...(definition.type === \"item\" ? { displayPosition: DisplayPosition.GUI } : {}),\n ...definition.options, instanceMeshes: false }) as SceneObject;\n break;\n }\n case \"entity\": {\n const key = AssetKey.parse(\"entity-models\", definition.asset);\n const model = await Entities.getEntity(key, definition.texture ? AssetKey.parse(\"textures\", definition.texture) : undefined, {\n layers: definition.layers, when: definition.when,\n textures: definition.textures && Object.fromEntries(Object.entries(definition.textures).map(([name, texture]) => [name, AssetKey.parse(\"textures\", texture)]))\n });\n if (!model) throw new Error(`Could not load entity ${definition.asset}`);\n const entity = await content.addEntity(model, { ...definition.options, instanceMeshes: false }) as EntityObject;\n object = entity;\n if (definition.animation) {\n const animations = await Entities.getAnimations(key);\n const clip = animations?.[definition.animation.name];\n if (!clip) throw new Error(`Entity ${definition.asset} has no animation \"${definition.animation.name}\"`);\n entity.playAnimation(clip, definition.animation);\n }\n break;\n }\n case \"gui\":\n object = await content.initialize(new GuiObject(definition.layers.map((layer): GuiLayer =>\n \"item\" in layer ? { ...layer, context: layer.context && itemContext(layer.context) } : layer)));\n break;\n }\n let disposed = false;\n const loaded: LoadedSceneObject = {\n root, object, definition,\n advanceAnimation: delta => {\n if (!disposed && definition.type === \"entity\" && !definition.animation?.paused) (object as EntityObject).advanceAnimation(delta);\n },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n root.removeFromParent();\n object!.dispose();\n object!.removeFromParent();\n content.dispose();\n root.clear();\n scene.dirty = true;\n }\n };\n parent?.add(root);\n scene.dirty = true;\n return loaded;\n } catch (error) {\n object?.dispose();\n object?.removeFromParent();\n content.dispose();\n root.removeFromParent();\n root.clear();\n throw new Error(`Scene object \"${definition.name ?? definition.id}\": ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/scene/SceneDocumentLoader.ts"],"sourcesContent":["import { Group } from \"three\";\nimport type { Object3D } from \"three\";\nimport { AssetKey } from \"../assets/AssetKey\";\nimport { AssetLoader } from \"../assets/AssetLoader\";\nimport { BlockStates } from \"../assets/BlockStates\";\nimport { Entities } from \"../assets/Entities\";\nimport { ItemModelContext, Models } from \"../assets/Models\";\nimport type { BasicMinecraftAsset } from \"../MinecraftAsset\";\nimport { DisplayPosition } from \"../model/DisplayPosition\";\nimport { MineRenderScene } from \"../renderer/MineRenderScene\";\nimport { isSceneObject, SceneObject } from \"../renderer/SceneObject\";\nimport type { SceneObjectOptions } from \"../renderer/SceneObjectOptions\";\nimport { EntityObject } from \"../entity/scene/EntityObject\";\nimport { SkinObject } from \"../skin/scene/SkinObject\";\nimport { Skins } from \"../skin/Skins\";\nimport { GuiObject } from \"../gui/scene/GuiObject\";\nimport type { GuiLayer } from \"../gui/GuiLayer\";\nimport { parseSceneDocument, SceneDocument, SceneItemContext, SceneObjectDefinition } from \"./SceneDocument\";\n\nfunction itemKey(asset: string): AssetKey {\n const key = AssetKey.parse(\"models\", asset);\n return key.type === \"item\" ? key : new AssetKey(key.namespace, key.getFullPath(), \"models\", \"item\");\n}\n\nfunction itemContext(context: SceneItemContext | undefined): ItemModelContext {\n const { itemReferences, ...rest } = context ?? {};\n return itemReferences\n ? { ...rest, itemReferences: Object.fromEntries(Object.entries(itemReferences).map(([id, item]) => [id, itemKey(item)])) }\n : rest;\n}\n\nexport interface LoadedSceneObject {\n readonly root: Group;\n readonly object: SceneObject;\n readonly definition: SceneObjectDefinition;\n /** Advances entity playback in seconds unless the definition has paused it. */\n advanceAnimation(delta: number): void;\n /** Removes this object and releases its owned resources. Safe to call more than once. */\n dispose(): void;\n}\n\nexport interface LoadedSceneDocument {\n readonly root: Group;\n readonly objects: LoadedSceneObject[];\n readonly definition: SceneDocument;\n advanceAnimations(delta: number): void;\n dispose(): void;\n}\n\n// Blocks create models and block entities through their scene, without forwarding a parent.\n// A nested scene keeps those visuals inside the object's transform group, including after state changes.\nclass DocumentObjectScene extends MineRenderScene {\n public async addSceneObject<A extends BasicMinecraftAsset, T extends SceneObject, O extends SceneObjectOptions>(\n _asset: A, supplier: () => T | Promise<T>, _options?: Partial<O>, parent: Object3D = this\n ): Promise<T> {\n const object = await supplier();\n return this.initialize(object, parent);\n }\n\n public async initialize<T extends SceneObject>(object: T, parent: Object3D = this): Promise<T> {\n object.scene = this;\n try {\n await object.init();\n parent.add(object);\n return object;\n } catch (error) {\n object.dispose();\n object.removeFromParent();\n throw error;\n }\n }\n\n public dispose(): void {\n for (const child of [...this.children]) {\n if (child.parent !== this) continue;\n if (isSceneObject(child)) child.dispose();\n child.removeFromParent();\n }\n }\n}\n\nasync function skinTexture(value: string, cape = false): Promise<string> {\n if (!/^[a-zA-Z0-9_-]{1,36}$/.test(value)) return value;\n const texture = await (cape ? Skins.capeFromUuidOrUsername(value) : Skins.fromUuidOrUsername(value));\n if (!texture) throw new Error(`Could not find ${cape ? \"cape\" : \"skin\"} for \"${value}\"`);\n return texture;\n}\n\n/** Loads portable scene documents using the asset sources already configured by the caller. */\nexport class SceneDocumentLoader {\n public static parse(value: unknown): SceneDocument {\n return parseSceneDocument(value);\n }\n\n /**\n * Loads objects concurrently and attaches them in document order after every load succeeds.\n * A failure waits for all loads, disposes staged objects, and reports the first error in document order.\n */\n public static async load(scene: MineRenderScene, value: unknown, parent: Object3D = scene): Promise<LoadedSceneDocument> {\n const definition = this.parse(value);\n if (definition.minecraftVersion !== undefined && definition.minecraftVersion !== AssetLoader.version) {\n throw new Error(`Scene requires Minecraft ${definition.minecraftVersion}; call AssetLoader.setVersion(\"${definition.minecraftVersion}\") before loading it`);\n }\n const root = new Group();\n root.name = \"MineRender scene document\";\n const objects: LoadedSceneObject[] = [];\n let disposed = false;\n const loaded: LoadedSceneDocument = {\n root, objects, definition,\n advanceAnimations: delta => { if (!disposed) for (const object of objects) object.advanceAnimation(delta); },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n root.removeFromParent();\n for (const object of objects) object.dispose();\n root.clear();\n scene.dirty = true;\n }\n };\n try {\n const results = await Promise.allSettled(definition.objects.map(object => this.loadValidatedObject(scene, object)));\n for (const result of results) if (result.status === \"fulfilled\") objects.push(result.value);\n const failure = results.find((result): result is PromiseRejectedResult => result.status === \"rejected\");\n if (failure) throw failure.reason;\n for (const object of objects) root.add(object.root);\n parent.add(root);\n scene.dirty = true;\n return loaded;\n } catch (error) {\n loaded.dispose();\n throw error;\n }\n }\n\n /** Loads an independently editable object. Its root owns the document's position, rotation, and scale. */\n public static async loadObject(scene: MineRenderScene, value: SceneObjectDefinition, parent: Object3D = scene): Promise<LoadedSceneObject> {\n const definition = this.parse({ format: \"minerender-scene\", version: 1, objects: [value] }).objects[0];\n return this.loadValidatedObject(scene, definition, parent);\n }\n\n private static async loadValidatedObject(scene: MineRenderScene, definition: SceneObjectDefinition, parent?: Object3D): Promise<LoadedSceneObject> {\n const root = new Group();\n root.name = definition.name ?? definition.id;\n root.userData.sceneObjectId = definition.id;\n root.position.fromArray(definition.position ?? [0, 0, 0]);\n root.rotation.set(...(definition.rotation ?? [0, 0, 0]));\n root.scale.fromArray(definition.scale ?? [1, 1, 1]);\n root.visible = definition.visible ?? true;\n const content = new DocumentObjectScene();\n root.add(content);\n let object: SceneObject | undefined;\n try {\n switch (definition.type) {\n case \"skin\": {\n const skin = new SkinObject({ ...definition.options, instanceMeshes: false });\n object = skin;\n const texture = definition.skin ? await skinTexture(definition.skin)\n : `${AssetLoader.ROOT}/assets/minecraft/textures/entity/player/${definition.options?.slim ? \"slim/alex\" : \"wide/steve\"}.png`;\n await skin.setSkinTexture(texture);\n await content.initialize(skin);\n if (definition.cape) await skin.setCapeTexture(await skinTexture(definition.cape.texture, true), definition.cape.layout);\n if (definition.armor) await skin.setArmor(definition.armor);\n for (const [part, rotation] of Object.entries(definition.pose ?? {})) {\n skin.getGroupByName(part)?.rotation.set(...rotation, \"XYZ\");\n }\n for (const part of definition.hiddenParts ?? []) {\n const mesh = skin.getMeshByName(part);\n if (mesh) mesh.visible = false;\n }\n break;\n }\n case \"block\": {\n const state = await BlockStates.get(AssetKey.parse(\"blockstates\", definition.asset));\n if (!state) throw new Error(`Could not load block ${definition.asset}`);\n object = await content.addBlock(state, { ...definition.options, initialState: definition.state, instanceMeshes: false }) as SceneObject;\n break;\n }\n case \"item\":\n case \"model\": {\n const key = definition.type === \"item\" ? itemKey(definition.asset) : AssetKey.parse(\"models\", definition.asset);\n const model = await Models.getMerged(key, definition.type === \"item\" ? itemContext(definition.context) : {});\n if (!model) throw new Error(`Could not load ${definition.type} ${definition.asset}`);\n object = await content.addModel(model, { ...(definition.type === \"item\" ? { displayPosition: DisplayPosition.GUI } : {}),\n ...definition.options, instanceMeshes: false }) as SceneObject;\n break;\n }\n case \"entity\": {\n const key = AssetKey.parse(\"entity-models\", definition.asset);\n const model = await Entities.getEntity(key, definition.texture ? AssetKey.parse(\"textures\", definition.texture) : undefined, {\n layers: definition.layers, when: definition.when,\n textures: definition.textures && Object.fromEntries(Object.entries(definition.textures).map(([name, texture]) => [name, AssetKey.parse(\"textures\", texture)]))\n });\n if (!model) throw new Error(`Could not load entity ${definition.asset}`);\n const entity = await content.addEntity(model, { ...definition.options, instanceMeshes: false }) as EntityObject;\n object = entity;\n if (definition.animation) {\n const animation = definition.animation;\n const animations = await Entities.getAnimations(key);\n if (animation.name !== undefined) {\n const clip = animations && Object.prototype.hasOwnProperty.call(animations, animation.name) ? animations[animation.name] : undefined;\n if (!clip) throw new Error(`Entity ${definition.asset} has no animation \"${animation.name}\"`);\n entity.playAnimation(clip, animation);\n } else {\n const clips = animation.clips.map(({ name }) => {\n const clip = animations && Object.prototype.hasOwnProperty.call(animations, name) ? animations[name] : undefined;\n if (!clip) throw new Error(`Entity ${definition.asset} has no animation \"${name}\"`);\n return clip;\n });\n entity.playAnimations(clips, { ...animation, weights: animation.clips.map(clip => clip.weight ?? 1) });\n }\n }\n break;\n }\n case \"gui\":\n object = await content.initialize(new GuiObject(definition.layers.map((layer): GuiLayer =>\n \"item\" in layer ? { ...layer, context: layer.context && itemContext(layer.context) } : layer)));\n break;\n }\n let disposed = false;\n const loaded: LoadedSceneObject = {\n root, object, definition,\n advanceAnimation: delta => {\n if (!disposed && definition.type === \"entity\" && !definition.animation?.paused) (object as EntityObject).advanceAnimation(delta);\n },\n dispose: () => {\n if (disposed) return;\n disposed = true;\n root.removeFromParent();\n object!.dispose();\n object!.removeFromParent();\n content.dispose();\n root.clear();\n scene.dirty = true;\n }\n };\n parent?.add(root);\n scene.dirty = true;\n return loaded;\n } catch (error) {\n object?.dispose();\n object?.removeFromParent();\n content.dispose();\n root.removeFromParent();\n root.clear();\n throw new Error(`Scene object \"${definition.name ?? definition.id}\": ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,6 +8,7 @@ var box4_12_4outer = [4.5, 12.5, 4.5];
|
|
|
8
8
|
var box3_12_4inner = [3, 12, 4];
|
|
9
9
|
var box3_12_4outer = [3.5, 12.5, 4.5];
|
|
10
10
|
var box10_16_1 = [10, 16, 1];
|
|
11
|
+
var box8_8_3ear = [8, 8, 3];
|
|
11
12
|
var baseSkinGeometries = {
|
|
12
13
|
head: box8inner,
|
|
13
14
|
hat: box8outer,
|
|
@@ -21,7 +22,9 @@ var baseSkinGeometries = {
|
|
|
21
22
|
leftTrousers: box4_12_4outer,
|
|
22
23
|
rightLeg: box4_12_4inner,
|
|
23
24
|
rightTrousers: box4_12_4outer,
|
|
24
|
-
cape: box10_16_1
|
|
25
|
+
cape: box10_16_1,
|
|
26
|
+
leftEar: box8_8_3ear,
|
|
27
|
+
rightEar: box8_8_3ear
|
|
25
28
|
};
|
|
26
29
|
var classicSkinGeometries = { ...{}, ...baseSkinGeometries };
|
|
27
30
|
var slimSkinGeometries = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/skin/SkinGeometries.ts"],"sourcesContent":["import { SkinPart } from \"./SkinPart\";\nimport { TripleArray } from \"../model/Model\";\nimport { merge } from \"../util/_internal/merge\";\n\nexport type SkinGeometries = Record<SkinPart, TripleArray>;\n\nconst box8inner: TripleArray = [8, 8, 8];\nconst box8outer: TripleArray = [9, 9, 9];\n\nconst box8_12_4inner: TripleArray = [8, 12, 4];\nconst box8_12_4outer: TripleArray = [8.5, 12.5, 4.5];\n\nconst box4_12_4inner: TripleArray = [4, 12, 4];\nconst box4_12_4outer: TripleArray = [4.5, 12.5, 4.5];\n\nconst box3_12_4inner: TripleArray = [3, 12, 4];\nconst box3_12_4outer: TripleArray = [3.5, 12.5, 4.5];\n\nconst box4_12_3inner: TripleArray = [4, 12, 3];\nconst box4_12_3outer: TripleArray = [4.504, 12.504, 3.504];\n\nconst box10_16_1: TripleArray = [10, 16, 1];\n\nconst baseSkinGeometries: SkinGeometries = {\n head: box8inner,\n hat: box8outer,\n\n body: box8_12_4inner,\n jacket: box8_12_4outer,\n\n leftArm: box4_12_4inner,\n leftSleeve: box4_12_4outer,\n\n rightArm: box4_12_4inner,\n rightSleeve: box4_12_4outer,\n\n leftLeg: box4_12_4inner,\n leftTrousers: box4_12_4outer,\n\n rightLeg: box4_12_4inner,\n rightTrousers: box4_12_4outer,\n\n cape: box10_16_1\n}\n\nexport const classicSkinGeometries: SkinGeometries = {...{}, ...baseSkinGeometries};\nexport const slimSkinGeometries: SkinGeometries = {\n ...{}, ...baseSkinGeometries, ...{\n leftArm: box3_12_4inner,\n leftSleeve: box3_12_4outer,\n\n rightArm: box3_12_4inner,\n rightSleeve: box3_12_4outer,\n }\n};\n"],"mappings":";AAMA,IAAM,YAAyB,CAAC,GAAG,GAAG,CAAC;AACvC,IAAM,YAAyB,CAAC,GAAG,GAAG,CAAC;AAEvC,IAAM,iBAA8B,CAAC,GAAG,IAAI,CAAC;AAC7C,IAAM,iBAA8B,CAAC,KAAK,MAAM,GAAG;AAEnD,IAAM,iBAA8B,CAAC,GAAG,IAAI,CAAC;AAC7C,IAAM,iBAA8B,CAAC,KAAK,MAAM,GAAG;AAEnD,IAAM,iBAA8B,CAAC,GAAG,IAAI,CAAC;AAC7C,IAAM,iBAA8B,CAAC,KAAK,MAAM,GAAG;AAKnD,IAAM,aAA0B,CAAC,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"sources":["../../../../src/skin/SkinGeometries.ts"],"sourcesContent":["import { SkinPart } from \"./SkinPart\";\nimport { TripleArray } from \"../model/Model\";\nimport { merge } from \"../util/_internal/merge\";\n\nexport type SkinGeometries = Record<SkinPart, TripleArray>;\n\nconst box8inner: TripleArray = [8, 8, 8];\nconst box8outer: TripleArray = [9, 9, 9];\n\nconst box8_12_4inner: TripleArray = [8, 12, 4];\nconst box8_12_4outer: TripleArray = [8.5, 12.5, 4.5];\n\nconst box4_12_4inner: TripleArray = [4, 12, 4];\nconst box4_12_4outer: TripleArray = [4.5, 12.5, 4.5];\n\nconst box3_12_4inner: TripleArray = [3, 12, 4];\nconst box3_12_4outer: TripleArray = [3.5, 12.5, 4.5];\n\nconst box4_12_3inner: TripleArray = [4, 12, 3];\nconst box4_12_3outer: TripleArray = [4.504, 12.504, 3.504];\n\nconst box10_16_1: TripleArray = [10, 16, 1];\n\n// Vanilla inflates the 6x6x1 ear cube by one unit on each side.\nconst box8_8_3ear: TripleArray = [8, 8, 3];\n\nconst baseSkinGeometries: SkinGeometries = {\n head: box8inner,\n hat: box8outer,\n\n body: box8_12_4inner,\n jacket: box8_12_4outer,\n\n leftArm: box4_12_4inner,\n leftSleeve: box4_12_4outer,\n\n rightArm: box4_12_4inner,\n rightSleeve: box4_12_4outer,\n\n leftLeg: box4_12_4inner,\n leftTrousers: box4_12_4outer,\n\n rightLeg: box4_12_4inner,\n rightTrousers: box4_12_4outer,\n\n cape: box10_16_1,\n\n leftEar: box8_8_3ear,\n rightEar: box8_8_3ear\n}\n\nexport const classicSkinGeometries: SkinGeometries = {...{}, ...baseSkinGeometries};\nexport const slimSkinGeometries: SkinGeometries = {\n ...{}, ...baseSkinGeometries, ...{\n leftArm: box3_12_4inner,\n leftSleeve: box3_12_4outer,\n\n rightArm: box3_12_4inner,\n rightSleeve: box3_12_4outer,\n }\n};\n"],"mappings":";AAMA,IAAM,YAAyB,CAAC,GAAG,GAAG,CAAC;AACvC,IAAM,YAAyB,CAAC,GAAG,GAAG,CAAC;AAEvC,IAAM,iBAA8B,CAAC,GAAG,IAAI,CAAC;AAC7C,IAAM,iBAA8B,CAAC,KAAK,MAAM,GAAG;AAEnD,IAAM,iBAA8B,CAAC,GAAG,IAAI,CAAC;AAC7C,IAAM,iBAA8B,CAAC,KAAK,MAAM,GAAG;AAEnD,IAAM,iBAA8B,CAAC,GAAG,IAAI,CAAC;AAC7C,IAAM,iBAA8B,CAAC,KAAK,MAAM,GAAG;AAKnD,IAAM,aAA0B,CAAC,IAAI,IAAI,CAAC;AAG1C,IAAM,cAA2B,CAAC,GAAG,GAAG,CAAC;AAEzC,IAAM,qBAAqC;AAAA,EACvC,MAAM;AAAA,EACN,KAAK;AAAA,EAEL,MAAM;AAAA,EACN,QAAQ;AAAA,EAER,SAAS;AAAA,EACT,YAAY;AAAA,EAEZ,UAAU;AAAA,EACV,aAAa;AAAA,EAEb,SAAS;AAAA,EACT,cAAc;AAAA,EAEd,UAAU;AAAA,EACV,eAAe;AAAA,EAEf,MAAM;AAAA,EAEN,SAAS;AAAA,EACT,UAAU;AACd;AAEO,IAAM,wBAAwC,EAAC,GAAG,CAAC,GAAG,GAAG,mBAAkB;AAC3E,IAAM,qBAAqC;AAAA,EAC9C,GAAG,CAAC;AAAA,EAAG,GAAG;AAAA,EAAoB,GAAG;AAAA,IAC7B,SAAS;AAAA,IACT,YAAY;AAAA,IAEZ,UAAU;AAAA,IACV,aAAa;AAAA,EACjB;AACJ;","names":[]}
|
|
@@ -13,6 +13,8 @@ var SkinPart = /* @__PURE__ */ ((SkinPart2) => {
|
|
|
13
13
|
SkinPart2["RIGHT_TROUSERS"] = "rightTrousers";
|
|
14
14
|
SkinPart2["LEFT_TROUSERS"] = "leftTrousers";
|
|
15
15
|
SkinPart2["CAPE"] = "cape";
|
|
16
|
+
SkinPart2["LEFT_EAR"] = "leftEar";
|
|
17
|
+
SkinPart2["RIGHT_EAR"] = "rightEar";
|
|
16
18
|
return SkinPart2;
|
|
17
19
|
})(SkinPart || {});
|
|
18
20
|
var SKIN_PARTS = Object.values(SkinPart);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/skin/SkinPart.ts"],"sourcesContent":["export enum SkinPart {\n HEAD = \"head\",\n BODY = \"body\",\n RIGHT_ARM = \"rightArm\",\n LEFT_ARM = \"leftArm\",\n RIGHT_LEG = \"rightLeg\",\n LEFT_LEG = \"leftLeg\",\n\n HAT = \"hat\",\n JACKET = \"jacket\",\n RIGHT_SLEEVE = \"rightSleeve\",\n LEFT_SLEEVE = \"leftSleeve\",\n RIGHT_TROUSERS = \"rightTrousers\",\n LEFT_TROUSERS = \"leftTrousers\",\n\n CAPE = \"cape\"\n}\n\nexport const SKIN_PARTS: SkinPart[] = Object.values(SkinPart);\n"],"mappings":";AAAO,IAAK,WAAL,kBAAKA,cAAL;AACH,EAAAA,UAAA,UAAO;AACP,EAAAA,UAAA,UAAO;AACP,EAAAA,UAAA,eAAY;AACZ,EAAAA,UAAA,cAAW;AACX,EAAAA,UAAA,eAAY;AACZ,EAAAA,UAAA,cAAW;AAEX,EAAAA,UAAA,SAAM;AACN,EAAAA,UAAA,YAAS;AACT,EAAAA,UAAA,kBAAe;AACf,EAAAA,UAAA,iBAAc;AACd,EAAAA,UAAA,oBAAiB;AACjB,EAAAA,UAAA,mBAAgB;AAEhB,EAAAA,UAAA,UAAO;
|
|
1
|
+
{"version":3,"sources":["../../../../src/skin/SkinPart.ts"],"sourcesContent":["export enum SkinPart {\n HEAD = \"head\",\n BODY = \"body\",\n RIGHT_ARM = \"rightArm\",\n LEFT_ARM = \"leftArm\",\n RIGHT_LEG = \"rightLeg\",\n LEFT_LEG = \"leftLeg\",\n\n HAT = \"hat\",\n JACKET = \"jacket\",\n RIGHT_SLEEVE = \"rightSleeve\",\n LEFT_SLEEVE = \"leftSleeve\",\n RIGHT_TROUSERS = \"rightTrousers\",\n LEFT_TROUSERS = \"leftTrousers\",\n\n CAPE = \"cape\",\n\n LEFT_EAR = \"leftEar\",\n RIGHT_EAR = \"rightEar\"\n}\n\nexport const SKIN_PARTS: SkinPart[] = Object.values(SkinPart);\n"],"mappings":";AAAO,IAAK,WAAL,kBAAKA,cAAL;AACH,EAAAA,UAAA,UAAO;AACP,EAAAA,UAAA,UAAO;AACP,EAAAA,UAAA,eAAY;AACZ,EAAAA,UAAA,cAAW;AACX,EAAAA,UAAA,eAAY;AACZ,EAAAA,UAAA,cAAW;AAEX,EAAAA,UAAA,SAAM;AACN,EAAAA,UAAA,YAAS;AACT,EAAAA,UAAA,kBAAe;AACf,EAAAA,UAAA,iBAAc;AACd,EAAAA,UAAA,oBAAiB;AACjB,EAAAA,UAAA,mBAAgB;AAEhB,EAAAA,UAAA,UAAO;AAEP,EAAAA,UAAA,cAAW;AACX,EAAAA,UAAA,eAAY;AAlBJ,SAAAA;AAAA,GAAA;AAqBL,IAAM,aAAyB,OAAO,OAAO,QAAQ;","names":["SkinPart"]}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// src/skin/SkinTextureCoordinates.ts
|
|
2
|
+
var earCoordinates = {
|
|
3
|
+
west: { uv: [24, 1, 25, 7] },
|
|
4
|
+
east: { uv: [31, 1, 32, 7] },
|
|
5
|
+
south: { uv: [25, 1, 31, 7] },
|
|
6
|
+
north: { uv: [32, 1, 38, 7] },
|
|
7
|
+
up: { uv: [25, 0, 31, 1] },
|
|
8
|
+
down: { uv: [31, 1, 37, 0] }
|
|
9
|
+
};
|
|
2
10
|
var baseSkinCoordinates = {
|
|
3
11
|
head: {
|
|
4
12
|
west: {
|
|
@@ -619,7 +627,9 @@ var baseSkinCoordinates = {
|
|
|
619
627
|
south: { uv: [12, 1, 22, 17] },
|
|
620
628
|
up: { uv: [11, 1, 1, 0] },
|
|
621
629
|
down: { uv: [21, 0, 11, 1] }
|
|
622
|
-
}
|
|
630
|
+
},
|
|
631
|
+
leftEar: earCoordinates,
|
|
632
|
+
rightEar: earCoordinates
|
|
623
633
|
};
|
|
624
634
|
var classicSkinTextureCoordinates = {
|
|
625
635
|
...baseSkinCoordinates
|