minerender 2.1.0-beta.6 → 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/Materials.mjs +3 -1
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/Ticker.mjs +3 -1
- package/dist/browser/esm/Ticker.mjs.map +1 -1
- package/dist/browser/esm/UVMapper.mjs +9 -9
- package/dist/browser/esm/UVMapper.mjs.map +1 -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/AssetDefaults.mjs +8 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetKey.mjs +1 -1
- package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
- package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
- package/dist/browser/esm/assets/Assets.mjs +1 -5
- package/dist/browser/esm/assets/Assets.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockEntities.mjs +5 -1
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +40 -12
- 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/Models.mjs +1 -1
- package/dist/browser/esm/assets/Models.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +5 -3
- package/dist/browser/esm/assets/_fonts/Unihex.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/assets/index.mjs +1 -0
- package/dist/browser/esm/assets/index.mjs.map +1 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +7 -8
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- 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/BrowserCache.mjs +3 -3
- package/dist/browser/esm/env/browser/BrowserCache.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/image/ImageLoader.mjs +3 -3
- package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +191 -22
- 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/inspector/SceneInspector.mjs +3 -3
- package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
- package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
- package/dist/browser/esm/instance/InstanceManager.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 +19 -6
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
- package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
- package/dist/browser/esm/model/scene/ModelObject.mjs +4 -4
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
- package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
- package/dist/browser/esm/renderer/Renderer.mjs +4 -2
- package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
- package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
- package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
- package/dist/browser/esm/request/Requests.mjs +3 -3
- package/dist/browser/esm/request/Requests.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/Skins.mjs +6 -4
- package/dist/browser/esm/skin/Skins.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/TextureLoader.mjs +4 -2
- package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
- package/dist/browser/esm/texture/index.mjs +1 -0
- package/dist/browser/esm/texture/index.mjs.map +1 -1
- package/dist/browser/esm/util/log.mjs +75 -0
- package/dist/browser/esm/util/log.mjs.map +1 -1
- package/dist/browser/esm/util/performance.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 +70 -38
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +187 -60
- 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 +129 -34
- package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
- package/dist/browser/index.d.ts +191 -22
- package/dist/browser/index.js +4461 -3648
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +13482 -12651
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +179 -21
- package/dist/node/index.d.ts +179 -21
- package/dist/node/index.js +4495 -3666
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +4412 -3586
- package/dist/node/index.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/renderer/SceneObject.ts"],"sourcesContent":["import { BoxGeometry, Color, EdgesGeometry, Euler, InstancedBufferAttribute, InstancedMesh, LineBasicMaterial, LineSegments, Matrix4, Mesh, Object3D, Quaternion, Scene, Vector3 } from \"three\";\nimport { ModelElement, ModelFaces } from \"../model/ModelElement\";\nimport { Geometries } from \"../Geometries\";\nimport { facesToUvArray } from \"../util/_internal/cubeUv\";\nimport { DoubleArray, TripleArray } from \"../model/Model\";\nimport { Axis, axisToVec3 } from \"../Axis\";\nimport type { BufferGeometry, Material, Object3DEventMap } from \"three\";\nimport { SkinPart } from \"../skin/SkinPart\";\nimport { changeEvent, Maybe } from \"../util/util\";\nimport { InstanceReference } from \"../instance/InstanceReference\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { isMesh } from \"../util/three\";\nimport { Disposable, isDisposable } from \"../Disposable\";\nimport { SceneObjectOptions } from \"./SceneObjectOptions\";\nimport { merge } from \"../util/_internal/merge\";\nimport { Instanceable } from \"../instance/Instanceable\";\nimport type { MineRenderScene } from \"./MineRenderScene\";\nimport { Transformable } from \"../Transformable\";\nimport { prefix } from \"../util/log\";\n\nconst p = prefix(\"SceneObject\");\n\n/**\n * Base for renderable Minecraft objects, with named parts and optional shared instances.\n * Use {@link notifyDirty} after changing a part directly so the renderer redraws it.\n */\nexport class SceneObject extends Object3D<Object3DEventMap & { change: {} }> implements Disposable, Instanceable, Transformable {\n\n public readonly isSceneObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: SceneObjectOptions = merge({}, <SceneObjectOptions>{\n instanceMeshes: true,\n maxInstanceCount: 50,\n mergeMeshes: true,\n wireframe: false\n });\n public readonly options: SceneObjectOptions;\n\n private _scene: Maybe<MineRenderScene>;\n\n private materialCallbacks: { [key: string]: Array<(mat: Material, key: string) => void>; } = {};\n\n protected _isInstanced: boolean = false;\n _instanceCounter: number = 0;\n protected instanceMesh?: InstancedMesh;\n private readonly instanceReferences = new Map<number, InstanceReference<SceneObject>>();\n private readonly freeInstanceIndices: number[] = [];\n private readonly hiddenInstanceMatrices = new Map<number, Matrix4>();\n\n constructor(options?: Partial<SceneObjectOptions>) {\n super();\n this.options = merge({}, SceneObject.DEFAULT_OPTIONS, options ?? {});\n console.log(\"SceneObject options\", this.options);\n }\n\n public set scene(scene: MineRenderScene) {\n if (!!this._scene) throw new MineRenderError(\"Scene already set\");\n this._scene = scene;\n }\n\n public get scene(): MineRenderScene {\n if (!this._scene) throw new MineRenderError(\"Scene not set\");\n return this._scene;\n }\n\n async init(): Promise<void> {\n }\n\n /** Marks ancestor scenes for redraw and emits a `change` event. */\n public notifyDirty() {\n this.traverseAncestors(parent => {\n const scene = parent as MineRenderScene;\n if (scene.isMineRenderScene) scene.dirty = true;\n });\n this.dispatchEvent(changeEvent);\n }\n\n //<editor-fold desc=\"GROUPS\">\n\n protected createAndAddGroup(name?: string, x: number = 0, y: number = 0, z: number = 0, offsetAxis?: Axis, offset: number = 0): Object3D {\n const group = this.createGroup(name, x, y, z, offsetAxis, offset);\n\n if (name) {\n let existing = this.getObjectByName(group.name);\n if (existing) {\n this.remove(existing);\n }\n }\n\n console.log(\"add\", group, group.name);\n this.add(group);\n this.notifyDirty();\n return group;\n }\n\n protected createGroup(name?: string, x: number = 0, y: number = 0, z: number = 0, offsetAxis?: Axis, offset: number = 0): Object3D {\n const obj = new Object3D();\n if (name) {\n obj.name = `group:${name}`;\n }\n if (x > 0 || y > 0 || z > 0) {\n obj.position.set(x, y, z);\n }\n if (offsetAxis) {\n obj.translateOnAxis(axisToVec3(offsetAxis), offset);\n }\n return obj;\n }\n\n /**\n * Finds a named part, such as `head`, without the internal `group:` prefix.\n * Returns `undefined` when the group does not exist.\n */\n public getGroupByName(name: string): Maybe<Object3D> {\n return this.getObjectByName(`group:${name}`) as Object3D;\n }\n\n /**\n * Changes a named group's visibility and requests a redraw.\n * @param name - Part name without the `group:` prefix.\n * @param visible - Visibility to assign. Omit it to toggle the current value.\n * @returns The resulting visibility, or `false` if the group does not exist.\n */\n public toggleGroupVisibility(name: string, visible?: boolean): boolean {\n return this.toggleObjectVisibility(this.getGroupByName(name), visible);\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"MESHES\">\n\n protected addOrReplaceMesh(mesh: Mesh, parent: Object3D, name?: string) {\n if (name) {\n const existing = parent.getObjectByName(mesh.name);\n if (existing) {\n console.log(\"remove\", existing.name, existing);\n parent.remove(existing);\n }\n }\n console.log(\"add\", mesh, mesh.name);\n parent.add(mesh);\n }\n\n protected createAndAddMesh(name?: string, group?: Object3D, geometry?: BufferGeometry, material?: Material | Material[], offsetAxis?: Axis, offset: number = 0): Mesh {\n const mesh = this.createMesh(name, geometry, material, offsetAxis, offset);\n if (group) {\n this.addOrReplaceMesh(mesh, group, name);\n } else {\n this.addOrReplaceMesh(mesh, this, name);\n }\n this.notifyDirty();\n return mesh;\n }\n\n protected createMesh(name?: string, geometry?: BufferGeometry, material?: Material | Material[], offsetAxis?: Axis, offset: number = 0): Mesh {\n const mesh = new Mesh(geometry, material);\n if (name) {\n mesh.name = `mesh:${name}`;\n }\n\n //TODO\n mesh.castShadow = true;\n mesh.receiveShadow = true;\n\n if (offsetAxis) {\n mesh.translateOnAxis(axisToVec3(offsetAxis), offset);\n }\n return mesh;\n }\n\n protected createInstancedMesh(name: Maybe<string>, geometry: BufferGeometry, material: Material | Material[], count: number): InstancedMesh {\n const mesh = new InstancedMesh(geometry, material, count);\n mesh.count = 0;\n this.instanceMesh = mesh;\n this._isInstanced = true;\n if (name) {\n mesh.name = `mesh:${name}`;\n }\n return mesh;\n }\n\n /**\n * Finds a named mesh without the internal `mesh:` prefix, or returns `undefined`.\n */\n public getMeshByName(name: string): Maybe<Mesh> {\n return this.getObjectByName(`mesh:${name}`) as Mesh;\n }\n\n /**\n * Changes a named mesh's visibility and requests a redraw.\n * @param name - Mesh name without the `mesh:` prefix.\n * @param visible - Visibility to assign. Omit it to toggle the current value.\n * @returns The resulting visibility, or `false` if the mesh does not exist.\n */\n public toggleMeshVisibility(name: string, visible?: boolean): boolean {\n return this.toggleObjectVisibility(this.getMeshByName(name), visible);\n }\n\n public iterateAllMeshes(cb: (mesh: Mesh) => void) {\n this.traverse(obj => {\n if (isMesh(obj)) cb(obj);\n });\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"GEOMETRIES\">\n\n protected _getBoxGeometryFromDimensions([width, height, depth]: TripleArray, faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): BoxGeometry {\n const uv = facesToUvArray(faces, originalTextureSize, actualTextureSize);\n return Geometries.getBox({\n width,\n height,\n depth,\n uv\n });\n }\n\n protected _getBoxGeometryFromElement(element: ModelElement): BoxGeometry {\n const width = element.to[0] - element.from[0];\n const height = element.to[1] - element.from[1];\n const depth = element.to[2] - element.from[2];\n\n const uv = element.mappedUv;\n\n return Geometries.getBox({\n width,\n height,\n depth,\n uv\n });\n }\n\n protected _getBoxGeometryForDimensionsAndUv(width: number, height: number, depth: number, uv: number[]): BoxGeometry {\n return Geometries.getBox({\n width,\n height,\n depth,\n uv\n });\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"INSTANCING\">\n\n get isInstanced(): boolean {\n return this._isInstanced;\n }\n\n /** Number of live placements, excluding released instance slots. */\n get instanceCounter(): number {\n return this._instanceCounter;\n }\n\n protected constructInstanceReference(i: number): InstanceReference<SceneObject> {\n return new InstanceReference<this>(this, i);\n }\n\n /** Allocates a placement of this instanced object, reusing a released slot when available. */\n nextInstance(): InstanceReference<SceneObject> {\n const mesh = this.instanceMesh;\n if (!mesh) throw new MineRenderError(\"Object is not instanced\");\n const index = this.freeInstanceIndices.pop() ?? mesh.count;\n if (index >= mesh.instanceMatrix.count) this.growInstances(index + 1);\n const reference = this.constructInstanceReference(index);\n this.instanceReferences.set(index, reference);\n this._instanceCounter = this.instanceReferences.size;\n mesh.count = Math.max(mesh.count, index + 1);\n if (mesh.instanceColor) {\n mesh.setColorAt(index, new Color(0xffffff));\n mesh.instanceColor.needsUpdate = true;\n }\n if (this._scene) this._scene.stats.instanceCount++;\n this.setMatrixAt(index, new Matrix4());\n return reference;\n }\n\n /** Returns the live reference for a raycast hit on this object's instance mesh. */\n public getInstanceReference(mesh: Object3D, index: number): Maybe<InstanceReference<SceneObject>> {\n return mesh === this.instanceMesh ? this.instanceReferences.get(index) : undefined;\n }\n\n isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean {\n return this.instanceReferences.get(index) === reference;\n }\n\n removeInstanceAt(index: number): void {\n if (!this.instanceReferences.has(index)) return;\n const mesh = this.instanceMesh!;\n this.hiddenInstanceMatrices.delete(index);\n this.setMatrixAt(index, new Matrix4().makeScale(0, 0, 0));\n this.instanceReferences.delete(index);\n this.freeInstanceIndices.push(index);\n this._instanceCounter = this.instanceReferences.size;\n while (mesh.count > 0 && !this.instanceReferences.has(mesh.count - 1)) mesh.count--;\n if (this._scene) this._scene.stats.instanceCount--;\n }\n\n private growInstances(required: number): void {\n const mesh = this.instanceMesh!;\n const capacity = Math.max(required, mesh.instanceMatrix.count * 2);\n const grow = (attribute: InstancedBufferAttribute, fill: number) => {\n const array = new Float32Array(capacity * attribute.itemSize).fill(fill);\n array.set(attribute.array);\n return new InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute)\n .setUsage(attribute.usage);\n };\n const matrix = grow(mesh.instanceMatrix, 0);\n const color = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;\n // Release uploaded instance buffers before replacing their attributes.\n mesh.dispose();\n mesh.instanceMatrix = matrix;\n mesh.instanceColor = color;\n }\n\n protected *activeInstanceIndices(): Iterable<number> {\n if (this.instanceMesh) {\n yield* this.instanceReferences.keys();\n } else {\n for (let i = 0; i < this.instanceCounter; i++) yield i;\n }\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"TRANSFORMATION\">\n\n getMatrixAt(index: number, matrix: Matrix4 = new Matrix4()): Matrix4 {\n if (!this.instanceReferences.has(index)) throw new MineRenderError(\"Instance is not active\");\n const hidden = this.hiddenInstanceMatrices.get(index);\n if (hidden) {\n return matrix.copy(hidden);\n }\n this.instanceMesh!.getMatrixAt(index, matrix);\n return matrix;\n }\n\n setMatrixAt(index: number, matrix: Matrix4) {\n if (!this.instanceReferences.has(index)) throw new MineRenderError(\"Instance is not active\");\n const mesh = this.instanceMesh!;\n const hidden = this.hiddenInstanceMatrices.get(index);\n if (hidden) {\n hidden.copy(matrix);\n }\n mesh.setMatrixAt(index, hidden ? new Matrix4().makeScale(0, 0, 0) : matrix);\n mesh.instanceMatrix.needsUpdate = true;\n mesh.boundingBox = null;\n mesh.boundingSphere = null;\n this.notifyDirty();\n }\n\n setInstanceVisibleAt(index: number, visible: boolean): void {\n if (!this.instanceReferences.has(index)) {\n throw new MineRenderError(\"Instance is not active\");\n }\n const hidden = this.hiddenInstanceMatrices.get(index);\n if (visible) {\n if (!hidden) {\n return;\n }\n this.hiddenInstanceMatrices.delete(index);\n this.setMatrixAt(index, hidden);\n } else {\n if (hidden) {\n return;\n }\n const matrix = this.getMatrixAt(index);\n this.hiddenInstanceMatrices.set(index, matrix);\n this.setMatrixAt(index, matrix);\n }\n }\n\n setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n\n const oldPosition = new Vector3();\n const oldRotation = new Quaternion();\n const oldScale = new Vector3();\n\n const matrix = new Matrix4();\n if (!scale || !rotation || !position) {\n this.getMatrixAt(index, matrix).decompose(oldPosition, oldRotation, oldScale);\n }\n\n matrix.compose(\n position ? position : oldPosition,\n rotation ? new Quaternion().setFromEuler(rotation) : oldRotation,\n scale ? scale : oldScale\n );\n\n this.setMatrixAt(index, matrix);\n }\n\n setPositionAt(index: number, position: Vector3) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n this.setPositionRotationScaleAt(index, position);\n }\n\n getPositionAt(index: number, vector: Vector3 = new Vector3()): Vector3 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const matrix = this.getMatrixAt(index)\n vector.setFromMatrixPosition(matrix);\n return vector;\n }\n\n setRotationAt(index: number, rotation: Euler) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n this.setPositionRotationScaleAt(index, undefined, rotation, undefined);\n }\n\n getRotationAt(index: number, euler: Euler = new Euler()): Euler {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const rotation = new Quaternion();\n this.getMatrixAt(index).decompose(new Vector3(), rotation, new Vector3());\n return euler.setFromQuaternion(rotation);\n }\n\n setScaleAt(index: number, scale: Vector3) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n this.setPositionRotationScaleAt(index, undefined, undefined, scale);\n }\n\n getScaleAt(index: number, vector: Vector3 = new Vector3()): Vector3 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const matrix = this.getMatrixAt(index)\n vector.setFromMatrixScale(matrix);\n return vector;\n }\n\n /** Updates supplied transform components. For a shared model, affects every live instance. */\n setPositionRotationScale(position?: Vector3, rotation?: Euler, scale?: Vector3): void {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, position, rotation, scale);\n }\n } else {\n if (position) {\n this.position.set(position.x, position.y, position.z);\n }\n if (rotation) {\n this.rotation.set(rotation.x, rotation.y, rotation.z);\n }\n if (scale) {\n this.scale.set(scale.x, scale.y, scale.z);\n }\n }\n this.notifyDirty();\n }\n\n /** Sets position in scene units. For a shared model, updates every live instance. */\n setPosition(position: Vector3) {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, position);\n }\n } else {\n this.position.set(position.x, position.y, position.z);\n }\n this.notifyDirty();\n }\n\n getPosition(): Vector3 {\n if (this.isInstanced) {\n return this.getPositionAt(this.instanceReferences.keys().next().value ?? 0);\n } else {\n return this.position;\n }\n }\n\n /** Sets rotation in radians. For a shared model, updates every live instance. */\n setRotation(rotation: Euler) {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, undefined, rotation);\n }\n } else {\n this.rotation.set(rotation.x, rotation.y, rotation.z);\n }\n this.notifyDirty();\n }\n\n getRotation(): Euler {\n if (this.isInstanced) {\n return this.getRotationAt(this.instanceReferences.keys().next().value ?? 0);\n } else {\n return this.rotation;\n }\n }\n\n /** Sets scale factors. For a shared model, updates every live instance. */\n setScale(scale: Vector3) {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, undefined, undefined, scale);\n }\n } else {\n this.scale.set(scale.x, scale.y, scale.z);\n }\n this.notifyDirty();\n }\n\n getScale(): Vector3 {\n if (this.isInstanced) {\n return this.getScaleAt(this.instanceReferences.keys().next().value ?? 0);\n } else {\n return this.scale;\n }\n }\n\n //</editor-fold>\n\n protected toggleObjectVisibility(object?: Object3D, visible?: boolean): boolean {\n if (object) {\n if (typeof visible !== \"undefined\") {\n object.visible = visible;\n } else {\n object.visible = !object.visible;\n }\n this.notifyDirty();\n return object.visible;\n }\n this.notifyDirty();\n return false;\n }\n\n //<editor-fold desc=\"CLEANUP\">\n\n public dispose() {\n this.disposeAndRemoveAllChildren();\n this.notifyDirty();\n super.dispose();\n }\n\n /** Releases instance slots and removes children, disposing children that implement Disposable. */\n public disposeAndRemoveAllChildren() {\n if (this.instanceMesh) {\n if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;\n this.instanceReferences.clear();\n this.freeInstanceIndices.length = 0;\n this.hiddenInstanceMatrices.clear();\n this._instanceCounter = 0;\n this.instanceMesh.count = 0;\n this.instanceMesh.dispose();\n this.instanceMesh.removeFromParent();\n this.instanceMesh = undefined;\n this._isInstanced = false;\n }\n while (this.children.length > 0) {\n let c = this.children[0];\n if (isDisposable(c)) {\n c.dispose();\n }\n this.remove(c);\n }\n this.notifyDirty();\n }\n\n /** Detaches the object from its parent and requests a redraw. */\n public removeFromScene() {\n this.notifyDirty();\n this.removeFromParent();\n }\n\n //</editor-fold>\n\n}\n\nexport function isSceneObject(obj: any): obj is SceneObject {\n return (<SceneObject>obj).isSceneObject;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/renderer/SceneObject.ts"],"sourcesContent":["import { BoxGeometry, Color, EdgesGeometry, Euler, InstancedBufferAttribute, InstancedMesh, LineBasicMaterial, LineSegments, Matrix4, Mesh, Object3D, Quaternion, Scene, Vector3 } from \"three\";\nimport { ModelElement, ModelFaces } from \"../model/ModelElement\";\nimport { Geometries } from \"../Geometries\";\nimport { facesToUvArray } from \"../util/_internal/cubeUv\";\nimport { DoubleArray, TripleArray } from \"../model/Model\";\nimport { Axis, axisToVec3 } from \"../Axis\";\nimport type { BufferGeometry, Material, Object3DEventMap } from \"three\";\nimport { SkinPart } from \"../skin/SkinPart\";\nimport { changeEvent, Maybe } from \"../util/util\";\nimport { InstanceReference } from \"../instance/InstanceReference\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { isMesh } from \"../util/three\";\nimport { Disposable, isDisposable } from \"../Disposable\";\nimport { SceneObjectOptions } from \"./SceneObjectOptions\";\nimport { merge } from \"../util/_internal/merge\";\nimport { Instanceable } from \"../instance/Instanceable\";\nimport type { MineRenderScene } from \"./MineRenderScene\";\nimport { Transformable } from \"../Transformable\";\n\n\n/**\n * Base for renderable Minecraft objects, with named parts and optional shared instances.\n * Use {@link notifyDirty} after changing a part directly so the renderer redraws it.\n */\nexport class SceneObject extends Object3D<Object3DEventMap & { change: {} }> implements Disposable, Instanceable, Transformable {\n\n public readonly isSceneObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: SceneObjectOptions = merge({}, <SceneObjectOptions>{\n instanceMeshes: true,\n maxInstanceCount: 50,\n mergeMeshes: true,\n wireframe: false\n });\n public readonly options: SceneObjectOptions;\n\n private _scene: Maybe<MineRenderScene>;\n\n private materialCallbacks: { [key: string]: Array<(mat: Material, key: string) => void>; } = {};\n\n protected _isInstanced: boolean = false;\n _instanceCounter: number = 0;\n protected instanceMesh?: InstancedMesh;\n private readonly instanceReferences = new Map<number, InstanceReference<SceneObject>>();\n private readonly freeInstanceIndices: number[] = [];\n private readonly hiddenInstanceMatrices = new Map<number, Matrix4>();\n\n constructor(options?: Partial<SceneObjectOptions>) {\n super();\n this.options = merge({}, SceneObject.DEFAULT_OPTIONS, options ?? {});\n }\n\n public set scene(scene: MineRenderScene) {\n if (!!this._scene) throw new MineRenderError(\"Scene already set\");\n this._scene = scene;\n }\n\n public get scene(): MineRenderScene {\n if (!this._scene) throw new MineRenderError(\"Scene not set\");\n return this._scene;\n }\n\n async init(): Promise<void> {\n }\n\n /** Marks ancestor scenes for redraw and emits a `change` event. */\n public notifyDirty() {\n this.traverseAncestors(parent => {\n const scene = parent as MineRenderScene;\n if (scene.isMineRenderScene) scene.dirty = true;\n });\n this.dispatchEvent(changeEvent);\n }\n\n //<editor-fold desc=\"GROUPS\">\n\n protected createAndAddGroup(name?: string, x: number = 0, y: number = 0, z: number = 0, offsetAxis?: Axis, offset: number = 0): Object3D {\n const group = this.createGroup(name, x, y, z, offsetAxis, offset);\n\n if (name) {\n let existing = this.getObjectByName(group.name);\n if (existing) {\n this.remove(existing);\n }\n }\n\n this.add(group);\n this.notifyDirty();\n return group;\n }\n\n protected createGroup(name?: string, x: number = 0, y: number = 0, z: number = 0, offsetAxis?: Axis, offset: number = 0): Object3D {\n const obj = new Object3D();\n if (name) {\n obj.name = `group:${name}`;\n }\n if (x > 0 || y > 0 || z > 0) {\n obj.position.set(x, y, z);\n }\n if (offsetAxis) {\n obj.translateOnAxis(axisToVec3(offsetAxis), offset);\n }\n return obj;\n }\n\n /**\n * Finds a named part, such as `head`, without the internal `group:` prefix.\n * Returns `undefined` when the group does not exist.\n */\n public getGroupByName(name: string): Maybe<Object3D> {\n return this.getObjectByName(`group:${name}`) as Object3D;\n }\n\n /**\n * Changes a named group's visibility and requests a redraw.\n * @param name - Part name without the `group:` prefix.\n * @param visible - Visibility to assign. Omit it to toggle the current value.\n * @returns The resulting visibility, or `false` if the group does not exist.\n */\n public toggleGroupVisibility(name: string, visible?: boolean): boolean {\n return this.toggleObjectVisibility(this.getGroupByName(name), visible);\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"MESHES\">\n\n protected addOrReplaceMesh(mesh: Mesh, parent: Object3D, name?: string) {\n if (name) {\n const existing = parent.getObjectByName(mesh.name);\n if (existing) {\n parent.remove(existing);\n }\n }\n parent.add(mesh);\n }\n\n protected createAndAddMesh(name?: string, group?: Object3D, geometry?: BufferGeometry, material?: Material | Material[], offsetAxis?: Axis, offset: number = 0): Mesh {\n const mesh = this.createMesh(name, geometry, material, offsetAxis, offset);\n if (group) {\n this.addOrReplaceMesh(mesh, group, name);\n } else {\n this.addOrReplaceMesh(mesh, this, name);\n }\n this.notifyDirty();\n return mesh;\n }\n\n protected createMesh(name?: string, geometry?: BufferGeometry, material?: Material | Material[], offsetAxis?: Axis, offset: number = 0): Mesh {\n const mesh = new Mesh(geometry, material);\n if (name) {\n mesh.name = `mesh:${name}`;\n }\n\n //TODO\n mesh.castShadow = true;\n mesh.receiveShadow = true;\n\n if (offsetAxis) {\n mesh.translateOnAxis(axisToVec3(offsetAxis), offset);\n }\n return mesh;\n }\n\n protected createInstancedMesh(name: Maybe<string>, geometry: BufferGeometry, material: Material | Material[], count: number): InstancedMesh {\n const mesh = new InstancedMesh(geometry, material, count);\n mesh.count = 0;\n this.instanceMesh = mesh;\n this._isInstanced = true;\n if (name) {\n mesh.name = `mesh:${name}`;\n }\n return mesh;\n }\n\n /**\n * Finds a named mesh without the internal `mesh:` prefix, or returns `undefined`.\n */\n public getMeshByName(name: string): Maybe<Mesh> {\n return this.getObjectByName(`mesh:${name}`) as Mesh;\n }\n\n /**\n * Changes a named mesh's visibility and requests a redraw.\n * @param name - Mesh name without the `mesh:` prefix.\n * @param visible - Visibility to assign. Omit it to toggle the current value.\n * @returns The resulting visibility, or `false` if the mesh does not exist.\n */\n public toggleMeshVisibility(name: string, visible?: boolean): boolean {\n return this.toggleObjectVisibility(this.getMeshByName(name), visible);\n }\n\n public iterateAllMeshes(cb: (mesh: Mesh) => void) {\n this.traverse(obj => {\n if (isMesh(obj)) cb(obj);\n });\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"GEOMETRIES\">\n\n protected _getBoxGeometryFromDimensions([width, height, depth]: TripleArray, faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): BoxGeometry {\n const uv = facesToUvArray(faces, originalTextureSize, actualTextureSize);\n return Geometries.getBox({\n width,\n height,\n depth,\n uv\n });\n }\n\n protected _getBoxGeometryFromElement(element: ModelElement): BoxGeometry {\n const width = element.to[0] - element.from[0];\n const height = element.to[1] - element.from[1];\n const depth = element.to[2] - element.from[2];\n\n const uv = element.mappedUv;\n\n return Geometries.getBox({\n width,\n height,\n depth,\n uv\n });\n }\n\n protected _getBoxGeometryForDimensionsAndUv(width: number, height: number, depth: number, uv: number[]): BoxGeometry {\n return Geometries.getBox({\n width,\n height,\n depth,\n uv\n });\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"INSTANCING\">\n\n get isInstanced(): boolean {\n return this._isInstanced;\n }\n\n /** Number of live placements, excluding released instance slots. */\n get instanceCounter(): number {\n return this._instanceCounter;\n }\n\n protected constructInstanceReference(i: number): InstanceReference<SceneObject> {\n return new InstanceReference<this>(this, i);\n }\n\n /** Allocates a placement of this instanced object, reusing a released slot when available. */\n nextInstance(): InstanceReference<SceneObject> {\n const mesh = this.instanceMesh;\n if (!mesh) throw new MineRenderError(\"Object is not instanced\");\n const index = this.freeInstanceIndices.pop() ?? mesh.count;\n if (index >= mesh.instanceMatrix.count) this.growInstances(index + 1);\n const reference = this.constructInstanceReference(index);\n this.instanceReferences.set(index, reference);\n this._instanceCounter = this.instanceReferences.size;\n mesh.count = Math.max(mesh.count, index + 1);\n if (mesh.instanceColor) {\n mesh.setColorAt(index, new Color(0xffffff));\n mesh.instanceColor.needsUpdate = true;\n }\n if (this._scene) this._scene.stats.instanceCount++;\n this.setMatrixAt(index, new Matrix4());\n return reference;\n }\n\n /** Returns the live reference for a raycast hit on this object's instance mesh. */\n public getInstanceReference(mesh: Object3D, index: number): Maybe<InstanceReference<SceneObject>> {\n return mesh === this.instanceMesh ? this.instanceReferences.get(index) : undefined;\n }\n\n isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean {\n return this.instanceReferences.get(index) === reference;\n }\n\n removeInstanceAt(index: number): void {\n if (!this.instanceReferences.has(index)) return;\n const mesh = this.instanceMesh!;\n this.hiddenInstanceMatrices.delete(index);\n this.setMatrixAt(index, new Matrix4().makeScale(0, 0, 0));\n this.instanceReferences.delete(index);\n this.freeInstanceIndices.push(index);\n this._instanceCounter = this.instanceReferences.size;\n while (mesh.count > 0 && !this.instanceReferences.has(mesh.count - 1)) mesh.count--;\n if (this._scene) this._scene.stats.instanceCount--;\n }\n\n private growInstances(required: number): void {\n const mesh = this.instanceMesh!;\n const capacity = Math.max(required, mesh.instanceMatrix.count * 2);\n const grow = (attribute: InstancedBufferAttribute, fill: number) => {\n const array = new Float32Array(capacity * attribute.itemSize).fill(fill);\n array.set(attribute.array);\n return new InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute)\n .setUsage(attribute.usage);\n };\n const matrix = grow(mesh.instanceMatrix, 0);\n const color = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;\n // Release uploaded instance buffers before replacing their attributes.\n mesh.dispose();\n mesh.instanceMatrix = matrix;\n mesh.instanceColor = color;\n }\n\n protected *activeInstanceIndices(): Iterable<number> {\n if (this.instanceMesh) {\n yield* this.instanceReferences.keys();\n } else {\n for (let i = 0; i < this.instanceCounter; i++) yield i;\n }\n }\n\n //</editor-fold>\n\n //<editor-fold desc=\"TRANSFORMATION\">\n\n getMatrixAt(index: number, matrix: Matrix4 = new Matrix4()): Matrix4 {\n if (!this.instanceReferences.has(index)) throw new MineRenderError(\"Instance is not active\");\n const hidden = this.hiddenInstanceMatrices.get(index);\n if (hidden) {\n return matrix.copy(hidden);\n }\n this.instanceMesh!.getMatrixAt(index, matrix);\n return matrix;\n }\n\n setMatrixAt(index: number, matrix: Matrix4) {\n if (!this.instanceReferences.has(index)) throw new MineRenderError(\"Instance is not active\");\n const mesh = this.instanceMesh!;\n const hidden = this.hiddenInstanceMatrices.get(index);\n if (hidden) {\n hidden.copy(matrix);\n }\n mesh.setMatrixAt(index, hidden ? new Matrix4().makeScale(0, 0, 0) : matrix);\n mesh.instanceMatrix.needsUpdate = true;\n mesh.boundingBox = null;\n mesh.boundingSphere = null;\n this.notifyDirty();\n }\n\n setInstanceVisibleAt(index: number, visible: boolean): void {\n if (!this.instanceReferences.has(index)) {\n throw new MineRenderError(\"Instance is not active\");\n }\n const hidden = this.hiddenInstanceMatrices.get(index);\n if (visible) {\n if (!hidden) {\n return;\n }\n this.hiddenInstanceMatrices.delete(index);\n this.setMatrixAt(index, hidden);\n } else {\n if (hidden) {\n return;\n }\n const matrix = this.getMatrixAt(index);\n this.hiddenInstanceMatrices.set(index, matrix);\n this.setMatrixAt(index, matrix);\n }\n }\n\n setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n\n const oldPosition = new Vector3();\n const oldRotation = new Quaternion();\n const oldScale = new Vector3();\n\n const matrix = new Matrix4();\n if (!scale || !rotation || !position) {\n this.getMatrixAt(index, matrix).decompose(oldPosition, oldRotation, oldScale);\n }\n\n matrix.compose(\n position ? position : oldPosition,\n rotation ? new Quaternion().setFromEuler(rotation) : oldRotation,\n scale ? scale : oldScale\n );\n\n this.setMatrixAt(index, matrix);\n }\n\n setPositionAt(index: number, position: Vector3) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n this.setPositionRotationScaleAt(index, position);\n }\n\n getPositionAt(index: number, vector: Vector3 = new Vector3()): Vector3 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const matrix = this.getMatrixAt(index)\n vector.setFromMatrixPosition(matrix);\n return vector;\n }\n\n setRotationAt(index: number, rotation: Euler) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n this.setPositionRotationScaleAt(index, undefined, rotation, undefined);\n }\n\n getRotationAt(index: number, euler: Euler = new Euler()): Euler {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const rotation = new Quaternion();\n this.getMatrixAt(index).decompose(new Vector3(), rotation, new Vector3());\n return euler.setFromQuaternion(rotation);\n }\n\n setScaleAt(index: number, scale: Vector3) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n this.setPositionRotationScaleAt(index, undefined, undefined, scale);\n }\n\n getScaleAt(index: number, vector: Vector3 = new Vector3()): Vector3 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const matrix = this.getMatrixAt(index)\n vector.setFromMatrixScale(matrix);\n return vector;\n }\n\n /** Updates supplied transform components. For a shared model, affects every live instance. */\n setPositionRotationScale(position?: Vector3, rotation?: Euler, scale?: Vector3): void {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, position, rotation, scale);\n }\n } else {\n if (position) {\n this.position.set(position.x, position.y, position.z);\n }\n if (rotation) {\n this.rotation.set(rotation.x, rotation.y, rotation.z);\n }\n if (scale) {\n this.scale.set(scale.x, scale.y, scale.z);\n }\n }\n this.notifyDirty();\n }\n\n /** Sets position in scene units. For a shared model, updates every live instance. */\n setPosition(position: Vector3) {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, position);\n }\n } else {\n this.position.set(position.x, position.y, position.z);\n }\n this.notifyDirty();\n }\n\n getPosition(): Vector3 {\n if (this.isInstanced) {\n return this.getPositionAt(this.instanceReferences.keys().next().value ?? 0);\n } else {\n return this.position;\n }\n }\n\n /** Sets rotation in radians. For a shared model, updates every live instance. */\n setRotation(rotation: Euler) {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, undefined, rotation);\n }\n } else {\n this.rotation.set(rotation.x, rotation.y, rotation.z);\n }\n this.notifyDirty();\n }\n\n getRotation(): Euler {\n if (this.isInstanced) {\n return this.getRotationAt(this.instanceReferences.keys().next().value ?? 0);\n } else {\n return this.rotation;\n }\n }\n\n /** Sets scale factors. For a shared model, updates every live instance. */\n setScale(scale: Vector3) {\n if (this.isInstanced) {\n for (const i of this.activeInstanceIndices()) {\n this.setPositionRotationScaleAt(i, undefined, undefined, scale);\n }\n } else {\n this.scale.set(scale.x, scale.y, scale.z);\n }\n this.notifyDirty();\n }\n\n getScale(): Vector3 {\n if (this.isInstanced) {\n return this.getScaleAt(this.instanceReferences.keys().next().value ?? 0);\n } else {\n return this.scale;\n }\n }\n\n //</editor-fold>\n\n protected toggleObjectVisibility(object?: Object3D, visible?: boolean): boolean {\n if (object) {\n if (typeof visible !== \"undefined\") {\n object.visible = visible;\n } else {\n object.visible = !object.visible;\n }\n this.notifyDirty();\n return object.visible;\n }\n this.notifyDirty();\n return false;\n }\n\n //<editor-fold desc=\"CLEANUP\">\n\n public dispose() {\n this.disposeAndRemoveAllChildren();\n this.notifyDirty();\n super.dispose();\n }\n\n /** Releases instance slots and removes children, disposing children that implement Disposable. */\n public disposeAndRemoveAllChildren() {\n if (this.instanceMesh) {\n if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;\n this.instanceReferences.clear();\n this.freeInstanceIndices.length = 0;\n this.hiddenInstanceMatrices.clear();\n this._instanceCounter = 0;\n this.instanceMesh.count = 0;\n this.instanceMesh.dispose();\n this.instanceMesh.removeFromParent();\n this.instanceMesh = undefined;\n this._isInstanced = false;\n }\n while (this.children.length > 0) {\n let c = this.children[0];\n if (isDisposable(c)) {\n c.dispose();\n }\n this.remove(c);\n }\n this.notifyDirty();\n }\n\n /** Detaches the object from its parent and requests a redraw. */\n public removeFromScene() {\n this.notifyDirty();\n this.removeFromParent();\n }\n\n //</editor-fold>\n\n}\n\nexport function isSceneObject(obj: any): obj is SceneObject {\n return (<SceneObject>obj).isSceneObject;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/request/Requests.ts
|
|
2
2
|
import { JobCancelledError, JobQueue } from "jobqu";
|
|
3
|
-
import {
|
|
4
|
-
var
|
|
3
|
+
import { logger } from "../util/log.mjs";
|
|
4
|
+
var log = logger("Requests");
|
|
5
5
|
var RequestError = class extends Error {
|
|
6
6
|
constructor(message, response, cause) {
|
|
7
7
|
super(message);
|
|
@@ -80,7 +80,7 @@ var RequestQueue = class {
|
|
|
80
80
|
try {
|
|
81
81
|
return await abortable(this.queue.add(request), signal);
|
|
82
82
|
} catch (error) {
|
|
83
|
-
|
|
83
|
+
log.debug("Request failed", error);
|
|
84
84
|
const delay = this.retryDelay(error, request, retries);
|
|
85
85
|
if (delay === void 0) {
|
|
86
86
|
throw error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/request/Requests.ts"],"sourcesContent":["import { JobCancelledError, JobQueue } from \"jobqu\";\nimport { prefix } from \"../util/log\";\n\nconst p = prefix(\"Requests\");\n\n/** Fetch settings passed to {@link Requests.genericRequest} or {@link Requests.mcAssetRequest}. */\nexport interface RequestConfig extends RequestInit {\n url: string;\n /** Prepended to relative URLs, preserving any path in the base URL. */\n baseURL?: string;\n /** Timeout per attempt in milliseconds, including body reading. Defaults to 5000; 0 disables it. */\n timeout?: number;\n /** Response-body decoding. Defaults to `json`. */\n responseType?: \"json\" | \"arraybuffer\";\n}\n\n/** A decoded response body with the HTTP status, native headers, and final URL. */\nexport interface RequestResponse<T = any> {\n data: T;\n status: number;\n statusText: string;\n headers: Headers;\n /** Final URL after redirects. */\n url: string;\n}\n\n/** An HTTP or network failure, with response details or an underlying cause when available. */\nexport class RequestError extends Error {\n constructor(message: string, readonly response?: RequestResponse<undefined>, readonly cause?: unknown) {\n super(message);\n this.name = \"RequestError\";\n }\n}\n\nasync function fetchRequest(config: RequestConfig, defaultBaseURL?: string): Promise<RequestResponse> {\n const { url, baseURL = defaultBaseURL, timeout = 5000, responseType = \"json\", signal, ...options } = config;\n const target = baseURL && !/^([a-z][a-z\\d+.-]*:|\\/\\/)/i.test(url)\n ? `${baseURL.replace(/\\/+$/, \"\")}/${url.replace(/^\\/+/, \"\")}` : url;\n const headers = new Headers(options.headers);\n if (typeof window === \"undefined\" && !headers.has(\"User-Agent\")) {\n headers.set(\"User-Agent\", \"MineRender\");\n }\n const attemptSignal = AbortSignal.any([\n ...(signal ? [signal] : []), ...(timeout === 0 ? [] : [AbortSignal.timeout(timeout)])\n ]);\n // Validate configuration before classifying Fetch TypeErrors as network failures.\n const request = new Request(target, { ...options, headers, signal: attemptSignal });\n attemptSignal.throwIfAborted();\n try {\n const response = await fetch(request);\n const result: RequestResponse<undefined> = {\n data: undefined,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url\n };\n if (!response.ok) {\n // Release error bodies without letting cleanup hide the HTTP status.\n await response.body?.cancel().catch(() => {});\n throw new RequestError(`Request failed with status ${response.status}`, result);\n }\n const emptyBody = request.method === \"HEAD\" || response.status === 204 || response.status === 205;\n const data = responseType === \"arraybuffer\" ? await response.arrayBuffer()\n : emptyBody || response.body === null ? undefined : await response.json();\n return { ...result, data };\n } catch (error) {\n attemptSignal.throwIfAborted();\n if (/^https?:/.test(request.url) && request.redirect !== \"error\" && error instanceof TypeError) {\n throw new RequestError(\"Network request failed\", undefined, error);\n }\n throw error;\n }\n}\n\nasync function abortable<T>(promise: Promise<T>, signal?: AbortSignal | null): Promise<T> {\n if (!signal) return promise;\n let abort: () => void;\n const cancelled = new Promise<never>((_, reject) => {\n abort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", abort, { once: true });\n if (signal.aborted) abort();\n });\n try {\n return await Promise.race([promise, cancelled]);\n } finally {\n signal.removeEventListener(\"abort\", abort!);\n }\n}\n\nclass RequestQueue {\n\n public baseURL?: string;\n private pendingRequests = 0;\n private readonly stopped = new AbortController();\n private readonly queue = new JobQueue<RequestConfig, RequestResponse>(\n request => fetchRequest(request, this.baseURL), { interval: 10, maxPerRun: 1, maxActive: 8 });\n\n public async request(request: RequestConfig): Promise<RequestResponse> {\n this.pendingRequests++;\n const signal = request.signal;\n try {\n for (let retries = 0; ; retries++) {\n signal?.throwIfAborted();\n try {\n return await abortable(this.queue.add(request), signal);\n } catch (error) {\n console.debug(p, \"Request failed\", error);\n const delay = this.retryDelay(error, request, retries);\n if (delay === undefined) {\n throw error;\n }\n await this.waitForRetry(delay, signal);\n }\n }\n } finally {\n if (signal?.aborted) {\n this.queue.remove(request);\n }\n this.pendingRequests--;\n }\n }\n\n private retryDelay(error: unknown, request: RequestConfig, retries: number): number | undefined {\n if (this.stopped.signal.aborted || retries >= 3 ||\n (request.method ?? \"get\").toLowerCase() !== \"get\" || request.signal?.aborted) {\n return undefined;\n }\n if (error instanceof RequestError) {\n const status = error.response?.status;\n if (status !== undefined && status !== 408 && status !== 429 && !(status >= 500 && status < 600)) return undefined;\n } else if (!(error instanceof DOMException && error.name === \"TimeoutError\")) {\n return undefined;\n }\n\n let delay = 100 * (2 ** retries);\n const retryAfter = error instanceof RequestError ? error.response?.headers.get(\"Retry-After\") : undefined;\n if (retryAfter !== undefined && retryAfter !== null) {\n const seconds = Number(retryAfter);\n if (!retryAfter.trim() || !Number.isFinite(seconds) || seconds < 0) {\n return undefined;\n }\n delay = Math.max(delay, seconds * 1000);\n }\n return delay;\n }\n\n private async waitForRetry(delay: number, signal?: AbortSignal | null): Promise<void> {\n let timer: ReturnType<typeof setTimeout>;\n const waiting = new Promise<void>(resolve => { timer = setTimeout(resolve, delay); });\n try {\n await abortable(waiting, AbortSignal.any([this.stopped.signal, ...(signal ? [signal] : [])]));\n } finally {\n clearTimeout(timer!);\n }\n }\n\n public get pendingSize(): number {\n return this.pendingRequests;\n }\n\n public end(): void {\n this.queue.end();\n this.stopped.abort(new JobCancelledError(\"ended\"));\n }\n}\n\n/** Shared Fetch queues with concurrency limits, cancellation, timeouts, and bounded retries for GET requests. */\nexport class Requests {\n\n private static genericQueue = new RequestQueue();\n private static mcAssetRequestQueue = new RequestQueue();\n\n /** Queues a general request. Set `request.signal` to cancel it and `request.timeout` to limit each attempt. */\n public static genericRequest(request: RequestConfig): Promise<RequestResponse> {\n return this.genericQueue.request(request);\n }\n\n /** Queues a request separately from general traffic, using the configured asset base URL for relative paths. */\n public static mcAssetRequest(request: RequestConfig): Promise<RequestResponse> {\n return this.mcAssetRequestQueue.request(request);\n }\n\n /** Sets the base URL for relative asset requests. Use {@link AssetLoader.setVersion} to change Minecraft versions. */\n public static setMcAssetRoot(root: string) {\n this.mcAssetRequestQueue.baseURL = root;\n }\n\n /** Counts unsettled calls, including retry delays and requests still running after shutdown. */\n public static get queueSizes() {\n return {\n generic: this.genericQueue.pendingSize,\n mcAsset: this.mcAssetRequestQueue.pendingSize\n }\n }\n\n /**\n * Permanently stops both queues and rejects waiting, retrying, and future requests.\n * Requests already running can finish. Idle queues hold no timer, so Node can exit without\n * this cleanup. See {@link shutdown}.\n */\n public static end() {\n this.genericQueue.end();\n this.mcAssetRequestQueue.end();\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/request/Requests.ts"],"sourcesContent":["import { JobCancelledError, JobQueue } from \"jobqu\";\nimport { logger } from \"../util/log\";\n\nconst log = logger(\"Requests\");\n\n/** Fetch settings passed to {@link Requests.genericRequest} or {@link Requests.mcAssetRequest}. */\nexport interface RequestConfig extends RequestInit {\n url: string;\n /** Prepended to relative URLs, preserving any path in the base URL. */\n baseURL?: string;\n /** Timeout per attempt in milliseconds, including body reading. Defaults to 5000; 0 disables it. */\n timeout?: number;\n /** Response-body decoding. Defaults to `json`. */\n responseType?: \"json\" | \"arraybuffer\";\n}\n\n/** A decoded response body with the HTTP status, native headers, and final URL. */\nexport interface RequestResponse<T = any> {\n data: T;\n status: number;\n statusText: string;\n headers: Headers;\n /** Final URL after redirects. */\n url: string;\n}\n\n/** An HTTP or network failure, with response details or an underlying cause when available. */\nexport class RequestError extends Error {\n constructor(message: string, readonly response?: RequestResponse<undefined>, readonly cause?: unknown) {\n super(message);\n this.name = \"RequestError\";\n }\n}\n\nasync function fetchRequest(config: RequestConfig, defaultBaseURL?: string): Promise<RequestResponse> {\n const { url, baseURL = defaultBaseURL, timeout = 5000, responseType = \"json\", signal, ...options } = config;\n const target = baseURL && !/^([a-z][a-z\\d+.-]*:|\\/\\/)/i.test(url)\n ? `${baseURL.replace(/\\/+$/, \"\")}/${url.replace(/^\\/+/, \"\")}` : url;\n const headers = new Headers(options.headers);\n if (typeof window === \"undefined\" && !headers.has(\"User-Agent\")) {\n headers.set(\"User-Agent\", \"MineRender\");\n }\n const attemptSignal = AbortSignal.any([\n ...(signal ? [signal] : []), ...(timeout === 0 ? [] : [AbortSignal.timeout(timeout)])\n ]);\n // Validate configuration before classifying Fetch TypeErrors as network failures.\n const request = new Request(target, { ...options, headers, signal: attemptSignal });\n attemptSignal.throwIfAborted();\n try {\n const response = await fetch(request);\n const result: RequestResponse<undefined> = {\n data: undefined,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url\n };\n if (!response.ok) {\n // Release error bodies without letting cleanup hide the HTTP status.\n await response.body?.cancel().catch(() => {});\n throw new RequestError(`Request failed with status ${response.status}`, result);\n }\n const emptyBody = request.method === \"HEAD\" || response.status === 204 || response.status === 205;\n const data = responseType === \"arraybuffer\" ? await response.arrayBuffer()\n : emptyBody || response.body === null ? undefined : await response.json();\n return { ...result, data };\n } catch (error) {\n attemptSignal.throwIfAborted();\n if (/^https?:/.test(request.url) && request.redirect !== \"error\" && error instanceof TypeError) {\n throw new RequestError(\"Network request failed\", undefined, error);\n }\n throw error;\n }\n}\n\nasync function abortable<T>(promise: Promise<T>, signal?: AbortSignal | null): Promise<T> {\n if (!signal) return promise;\n let abort: () => void;\n const cancelled = new Promise<never>((_, reject) => {\n abort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", abort, { once: true });\n if (signal.aborted) abort();\n });\n try {\n return await Promise.race([promise, cancelled]);\n } finally {\n signal.removeEventListener(\"abort\", abort!);\n }\n}\n\nclass RequestQueue {\n\n public baseURL?: string;\n private pendingRequests = 0;\n private readonly stopped = new AbortController();\n private readonly queue = new JobQueue<RequestConfig, RequestResponse>(\n request => fetchRequest(request, this.baseURL), { interval: 10, maxPerRun: 1, maxActive: 8 });\n\n public async request(request: RequestConfig): Promise<RequestResponse> {\n this.pendingRequests++;\n const signal = request.signal;\n try {\n for (let retries = 0; ; retries++) {\n signal?.throwIfAborted();\n try {\n return await abortable(this.queue.add(request), signal);\n } catch (error) {\n log.debug(\"Request failed\", error);\n const delay = this.retryDelay(error, request, retries);\n if (delay === undefined) {\n throw error;\n }\n await this.waitForRetry(delay, signal);\n }\n }\n } finally {\n if (signal?.aborted) {\n this.queue.remove(request);\n }\n this.pendingRequests--;\n }\n }\n\n private retryDelay(error: unknown, request: RequestConfig, retries: number): number | undefined {\n if (this.stopped.signal.aborted || retries >= 3 ||\n (request.method ?? \"get\").toLowerCase() !== \"get\" || request.signal?.aborted) {\n return undefined;\n }\n if (error instanceof RequestError) {\n const status = error.response?.status;\n if (status !== undefined && status !== 408 && status !== 429 && !(status >= 500 && status < 600)) return undefined;\n } else if (!(error instanceof DOMException && error.name === \"TimeoutError\")) {\n return undefined;\n }\n\n let delay = 100 * (2 ** retries);\n const retryAfter = error instanceof RequestError ? error.response?.headers.get(\"Retry-After\") : undefined;\n if (retryAfter !== undefined && retryAfter !== null) {\n const seconds = Number(retryAfter);\n if (!retryAfter.trim() || !Number.isFinite(seconds) || seconds < 0) {\n return undefined;\n }\n delay = Math.max(delay, seconds * 1000);\n }\n return delay;\n }\n\n private async waitForRetry(delay: number, signal?: AbortSignal | null): Promise<void> {\n let timer: ReturnType<typeof setTimeout>;\n const waiting = new Promise<void>(resolve => { timer = setTimeout(resolve, delay); });\n try {\n await abortable(waiting, AbortSignal.any([this.stopped.signal, ...(signal ? [signal] : [])]));\n } finally {\n clearTimeout(timer!);\n }\n }\n\n public get pendingSize(): number {\n return this.pendingRequests;\n }\n\n public end(): void {\n this.queue.end();\n this.stopped.abort(new JobCancelledError(\"ended\"));\n }\n}\n\n/** Shared Fetch queues with concurrency limits, cancellation, timeouts, and bounded retries for GET requests. */\nexport class Requests {\n\n private static genericQueue = new RequestQueue();\n private static mcAssetRequestQueue = new RequestQueue();\n\n /** Queues a general request. Set `request.signal` to cancel it and `request.timeout` to limit each attempt. */\n public static genericRequest(request: RequestConfig): Promise<RequestResponse> {\n return this.genericQueue.request(request);\n }\n\n /** Queues a request separately from general traffic, using the configured asset base URL for relative paths. */\n public static mcAssetRequest(request: RequestConfig): Promise<RequestResponse> {\n return this.mcAssetRequestQueue.request(request);\n }\n\n /** Sets the base URL for relative asset requests. Use {@link AssetLoader.setVersion} to change Minecraft versions. */\n public static setMcAssetRoot(root: string) {\n this.mcAssetRequestQueue.baseURL = root;\n }\n\n /** Counts unsettled calls, including retry delays and requests still running after shutdown. */\n public static get queueSizes() {\n return {\n generic: this.genericQueue.pendingSize,\n mcAsset: this.mcAssetRequestQueue.pendingSize\n }\n }\n\n /**\n * Permanently stops both queues and rejects waiting, retrying, and future requests.\n * Requests already running can finish. Idle queues hold no timer, so Node can exit without\n * this cleanup. See {@link shutdown}.\n */\n public static end() {\n this.genericQueue.end();\n this.mcAssetRequestQueue.end();\n }\n\n}\n"],"mappings":"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","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);
|