minerender 2.1.0-alpha.146 → 2.1.0-alpha.147
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/dist/browser/esm/assets/Entities.mjs +9 -8
- package/dist/browser/esm/assets/Entities.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/cache/Caching.mjs +2 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +5 -2
- package/dist/browser/esm/model/block/scene/BlockObject.mjs +16 -5
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/index.d.ts +5 -2
- package/dist/browser/index.js +44 -20
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +44 -20
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +5 -2
- package/dist/node/index.d.ts +5 -2
- package/dist/node/index.js +46 -20
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +46 -20
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -118,26 +118,27 @@ var Entities = class {
|
|
|
118
118
|
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
119
119
|
const root = isAssetKey(modelKey) ? modelKey.root : void 0;
|
|
120
120
|
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", root);
|
|
121
|
-
|
|
121
|
+
const texture = await Caching.entityTextureCache.get(key.serialize(), async () => {
|
|
122
122
|
const name = path.split("/").pop();
|
|
123
123
|
for (const candidate of [path, `${path}/${name}`]) {
|
|
124
|
-
const
|
|
125
|
-
if (await ModelTextures.get(
|
|
124
|
+
const texture3 = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png", root);
|
|
125
|
+
if (await ModelTextures.get(texture3)) return texture3;
|
|
126
126
|
}
|
|
127
127
|
const listKey = new AssetKey(modelKey.namespace, "_list", `${name}_variant`, void 0, "data", ".json", root);
|
|
128
128
|
const list = await AssetLoader.get(listKey, AssetParser.LIST);
|
|
129
129
|
const files = list?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
|
|
130
130
|
const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
|
|
131
|
-
if (!file) return
|
|
131
|
+
if (!file) return Caching.MISSING;
|
|
132
132
|
const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, void 0, "data", ".json", root);
|
|
133
133
|
const variant = await AssetLoader.get(variantKey, AssetParser.JSON);
|
|
134
134
|
const assets = variant?.assets;
|
|
135
135
|
const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
|
|
136
|
-
if (typeof textureId !== "string") return
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
return
|
|
136
|
+
if (typeof textureId !== "string") return Caching.MISSING;
|
|
137
|
+
const texture2 = AssetKey.parse("textures", textureId);
|
|
138
|
+
texture2.root = root;
|
|
139
|
+
return texture2;
|
|
140
140
|
});
|
|
141
|
+
return texture === Caching.MISSING ? void 0 : texture;
|
|
141
142
|
}
|
|
142
143
|
/** @deprecated Use getEntityList(); block entities share the entity dataset. */
|
|
143
144
|
static getBlockList() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/assets/Entities.ts"],"sourcesContent":["import { AssetKey, BasicAssetKey, isAssetKey } from \"./AssetKey\";\nimport type { EntityLayer, EntityModel, EntityModelFile, EntityModelPass } from \"../entity/EntityModel\";\nimport type { EntityAnimation, EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport { parseRelease, nearestRelease } from \"./_versions/DatasetVersions\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { AssetParser } from \"./source\";\nimport { Maybe } from \"../util\";\nimport { Caching } from \"../cache/Caching\";\nimport { DEFAULT_NAMESPACE } from \"./AssetDefaults\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { ModelTextures } from \"./ModelTextures\";\nimport type { MinecraftAsset } from \"../MinecraftAsset\";\n\n/** Loads entity and block-entity geometry, texture selections, and animation clips from the dataset. */\nexport class Entities {\n\n /**\n * Resolves `root` (default: the active version). Uses the exact dataset when published or when the\n * version is not a release; otherwise selects the nearest published release, like {@link MineRenderData.resolve}.\n * Textures keep the requested root.\n */\n public static async getDatasetRoot(root?: string): Promise<Maybe<string>> {\n const requestRoot = (root ?? AssetLoader.ROOT).replace(/\\/+$/, \"\");\n const requestedVersion = requestRoot.slice(requestRoot.lastIndexOf(\"/\") + 1);\n const base = requestRoot.slice(0, requestRoot.lastIndexOf(\"/\"));\n const selected = await Caching.entityDatasetVersionCache.get(root ?? `sources:${AssetLoader.ROOT}`, async () => {\n const key = new AssetKey(\"entity-models\", \"version\", undefined, undefined, undefined, \".json\", root);\n key.rootType = undefined!;\n if (!parseRelease(requestedVersion) || await AssetLoader.get(key, AssetParser.JSON) !== undefined) return requestedVersion;\n const indexKey = new AssetKey(\"entity-models\", \"versions\", undefined, undefined, undefined, \".json\", base);\n indexKey.rootType = undefined!;\n const index = await AssetLoader.get<MinecraftAsset & { versions: { name: string }[] }>(indexKey, AssetParser.JSON);\n if (index === undefined) return requestedVersion;\n if (!index || typeof index !== \"object\" || Array.isArray(index) || !Array.isArray(index.versions)\n || !index.versions.every(entry => entry && typeof entry === \"object\" && !Array.isArray(entry) && typeof entry.name === \"string\")) {\n throw new MineRenderError(`Invalid entity model version index at ${base}/entity-models/versions.json`);\n }\n return nearestRelease(requestedVersion, index.versions.map(entry => entry.name)) ?? requestedVersion;\n });\n return selected === requestedVersion ? root : `${base}/${selected}`;\n }\n\n /** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */\n public static async getEntityList(): Promise<string[]> {\n const root = await this.getDatasetRoot();\n const collect = async (path: string): Promise<string[]> => {\n const prefix = path ? `${path}/` : \"\";\n const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix}_list`, undefined, undefined, \"entity-models\", \".json\", root);\n const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get<ListAsset>(key, AssetParser.LIST));\n if (!list) return [];\n const files = list.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\")\n .map(file => `${prefix}${file.slice(0, -5)}`);\n const children = await Promise.all(list.directories.map(directory => collect(`${prefix}${directory}`)));\n return [...files, ...children.flat()];\n };\n return collect(\"\");\n }\n\n private static async getModelFile(modelKey: BasicAssetKey): Promise<Maybe<EntityModelFile>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : undefined));\n return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get<EntityModelFile>(key, AssetParser.JSON));\n }\n\n /** Returns selectable geometry-layer names, or an empty list when the model is missing. */\n public static async getLayerList(modelKey: BasicAssetKey): Promise<string[]> {\n return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});\n }\n\n /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */\n public static async getPassList(modelKey: BasicAssetKey): Promise<EntityModelPass[]> {\n return (await this.getModelFile(modelKey))?.passes ?? [];\n }\n\n /**\n * Loads the layers and textures to pass to {@link MineRenderScene.addEntity}.\n * By default, selects `main`, unconditional passes, and passes enabled by `options.when`.\n *\n * @param modelKey - Dataset model, such as `new BasicAssetKey(\"minecraft\", \"zombie\")`.\n * @param textureKey - Texture override for the first selected layer.\n * @param options - Layer selection, conditional passes, and per-layer texture overrides.\n * @returns The selected model, or `undefined` when its dataset file is missing.\n */\n public static async getEntity(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n const model = await this.getModelFile(modelKey);\n if (!model) return undefined;\n // Without an explicit selection, draw what vanilla draws: main, then the passes enabled for the requested state.\n const passes = options?.layers || options?.layer !== undefined ? [] :\n (model.passes ?? []).filter(pass => pass.when === undefined || options?.when?.includes(pass.when));\n const draws: EntityModelPass[] = [...new Set(options?.layers ?? [options?.layer ?? \"main\"])].map(layer => ({ layer }));\n if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);\n draws.push(...passes);\n const names: string[] = [];\n const selected = draws.map(pass => {\n const layer = model.layers[pass.layer];\n if (!layer) {\n throw new MineRenderError(`Entity ${model.id} has no layer \"${pass.layer}\". Available layers: ${Object.keys(model.layers).join(\", \")}`);\n }\n // A pass may draw geometry that is already selected with another texture.\n let name = pass.layer;\n for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;\n names.push(name);\n return { name, layer, pass };\n });\n const layers: Record<string, EntityLayer> = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {\n const override = options?.textures?.[name] ?? (index === 0 ? textureKey : undefined);\n const textureLocation = pass.textureLocation ?? layer.textureLocation;\n let texture: Maybe<AssetKey>;\n if (override) {\n const path = isAssetKey(override) ? override.getFullPath() : override.path;\n texture = isAssetKey(override) && override.assetType === \"textures\" && path.startsWith(\"entity/\")\n ? override\n : new AssetKey(override.namespace, path, \"textures\", \"entity\", \"assets\", \".png\", isAssetKey(override) ? override.root : undefined);\n } else if (textureLocation !== undefined) {\n texture = AssetKey.parse(\"textures\", textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (isAssetKey(modelKey)) texture.root = modelKey.root;\n } else {\n texture = await this.resolveTexture(modelKey);\n }\n const render = pass.render ?? layer.render;\n return [name, { key: override ?? modelKey, texture, layer, ...(render && { render }), ...(pass.tint && { tint: pass.tint }) }];\n })));\n return { ...layers[names[0]], id: model.id, layers, ...(model.transform && { transform: model.transform }) };\n }\n\n /**\n * Native and sampled vanilla clips by name, or undefined when the model or selected version has none.\n */\n public static async getAnimations(modelKey: BasicAssetKey): Promise<Maybe<Record<string, EntityAnimation>>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models/animations\", \".json\", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : undefined));\n const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get<EntityAnimationFile>(key, AssetParser.JSON));\n return file?.animations;\n }\n\n /** Finds a fallback texture using the model path, its directory, and vanilla variant data. */\n public static async resolveTexture(modelKey: BasicAssetKey): Promise<Maybe<AssetKey>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const root = isAssetKey(modelKey) ? modelKey.root : undefined;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", root);\n return Caching.entityTextureCache.get(key.serialize(), async () => {\n const name = path.split(\"/\").pop()!;\n for (const candidate of [path, `${path}/${name}`]) {\n const texture = new AssetKey(modelKey.namespace, candidate, \"textures\", \"entity\", \"assets\", \".png\", root);\n if (await ModelTextures.get(texture)) return texture;\n }\n const listKey = new AssetKey(modelKey.namespace, \"_list\", `${name}_variant`, undefined, \"data\", \".json\", root);\n const list = await AssetLoader.get<ListAsset>(listKey, AssetParser.LIST);\n const files = list?.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\");\n const file = files?.find(file => file === \"temperate.json\") ?? files?.[0];\n if (!file) return undefined;\n const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, undefined, \"data\", \".json\", root);\n const variant = await AssetLoader.get<EntityVariant>(variantKey, AssetParser.JSON);\n const assets = variant?.assets;\n const textureId = variant?.asset_id ?? (typeof assets?.wild === \"string\" ? assets.wild :\n Object.values(assets ?? {}).find(value => typeof value === \"string\"));\n if (typeof textureId !== \"string\") return undefined;\n const texture = AssetKey.parse(\"textures\", textureId);\n texture.root = root;\n return texture;\n });\n }\n\n /** @deprecated Use getEntityList(); block entities share the entity dataset. */\n public static getBlockList(): Promise<string[]> {\n return this.getEntityList();\n }\n\n /** @deprecated Use getEntity(); block entities share the entity dataset. */\n public static getBlock(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n return this.getEntity(modelKey, textureKey, options);\n }\n\n}\n\n/** Selection settings passed as the third argument to {@link Entities.getEntity}. */\nexport interface EntityModelOptions {\n /** Selects one geometry layer without dataset passes. `layers` takes precedence when supplied. */\n layer?: string;\n /** Layer names in draw order; an explicit selection draws exactly these layers and no dataset passes. */\n layers?: string[];\n /**\n * Entity states that enable the dataset's conditional passes, e.g. `[\"powered\"]` for a charged creeper.\n * Without `layer`/`layers`, `main` and every unconditional pass are always drawn.\n */\n when?: string[];\n /** Per-layer texture overrides, keyed like `EntityModel.layers`. The positional texture key applies to the first selected layer. */\n textures?: Record<string, BasicAssetKey>;\n}\n\ninterface EntityVariant extends MinecraftAsset {\n asset_id?: string;\n assets?: Record<string, unknown>;\n}\n"],"mappings":"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","names":["texture","file"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/assets/Entities.ts"],"sourcesContent":["import { AssetKey, BasicAssetKey, isAssetKey } from \"./AssetKey\";\nimport type { EntityLayer, EntityModel, EntityModelFile, EntityModelPass } from \"../entity/EntityModel\";\nimport type { EntityAnimation, EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport { parseRelease, nearestRelease } from \"./_versions/DatasetVersions\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { AssetParser } from \"./source\";\nimport { Maybe } from \"../util\";\nimport { Caching } from \"../cache/Caching\";\nimport { DEFAULT_NAMESPACE } from \"./AssetDefaults\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { ModelTextures } from \"./ModelTextures\";\nimport type { MinecraftAsset } from \"../MinecraftAsset\";\n\n/** Loads entity and block-entity geometry, texture selections, and animation clips from the dataset. */\nexport class Entities {\n\n /**\n * Resolves `root` (default: the active version). Uses the exact dataset when published or when the\n * version is not a release; otherwise selects the nearest published release, like {@link MineRenderData.resolve}.\n * Textures keep the requested root.\n */\n public static async getDatasetRoot(root?: string): Promise<Maybe<string>> {\n const requestRoot = (root ?? AssetLoader.ROOT).replace(/\\/+$/, \"\");\n const requestedVersion = requestRoot.slice(requestRoot.lastIndexOf(\"/\") + 1);\n const base = requestRoot.slice(0, requestRoot.lastIndexOf(\"/\"));\n const selected = await Caching.entityDatasetVersionCache.get(root ?? `sources:${AssetLoader.ROOT}`, async () => {\n const key = new AssetKey(\"entity-models\", \"version\", undefined, undefined, undefined, \".json\", root);\n key.rootType = undefined!;\n if (!parseRelease(requestedVersion) || await AssetLoader.get(key, AssetParser.JSON) !== undefined) return requestedVersion;\n const indexKey = new AssetKey(\"entity-models\", \"versions\", undefined, undefined, undefined, \".json\", base);\n indexKey.rootType = undefined!;\n const index = await AssetLoader.get<MinecraftAsset & { versions: { name: string }[] }>(indexKey, AssetParser.JSON);\n if (index === undefined) return requestedVersion;\n if (!index || typeof index !== \"object\" || Array.isArray(index) || !Array.isArray(index.versions)\n || !index.versions.every(entry => entry && typeof entry === \"object\" && !Array.isArray(entry) && typeof entry.name === \"string\")) {\n throw new MineRenderError(`Invalid entity model version index at ${base}/entity-models/versions.json`);\n }\n return nearestRelease(requestedVersion, index.versions.map(entry => entry.name)) ?? requestedVersion;\n });\n return selected === requestedVersion ? root : `${base}/${selected}`;\n }\n\n /** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */\n public static async getEntityList(): Promise<string[]> {\n const root = await this.getDatasetRoot();\n const collect = async (path: string): Promise<string[]> => {\n const prefix = path ? `${path}/` : \"\";\n const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix}_list`, undefined, undefined, \"entity-models\", \".json\", root);\n const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get<ListAsset>(key, AssetParser.LIST));\n if (!list) return [];\n const files = list.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\")\n .map(file => `${prefix}${file.slice(0, -5)}`);\n const children = await Promise.all(list.directories.map(directory => collect(`${prefix}${directory}`)));\n return [...files, ...children.flat()];\n };\n return collect(\"\");\n }\n\n private static async getModelFile(modelKey: BasicAssetKey): Promise<Maybe<EntityModelFile>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : undefined));\n return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get<EntityModelFile>(key, AssetParser.JSON));\n }\n\n /** Returns selectable geometry-layer names, or an empty list when the model is missing. */\n public static async getLayerList(modelKey: BasicAssetKey): Promise<string[]> {\n return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});\n }\n\n /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */\n public static async getPassList(modelKey: BasicAssetKey): Promise<EntityModelPass[]> {\n return (await this.getModelFile(modelKey))?.passes ?? [];\n }\n\n /**\n * Loads the layers and textures to pass to {@link MineRenderScene.addEntity}.\n * By default, selects `main`, unconditional passes, and passes enabled by `options.when`.\n *\n * @param modelKey - Dataset model, such as `new BasicAssetKey(\"minecraft\", \"zombie\")`.\n * @param textureKey - Texture override for the first selected layer.\n * @param options - Layer selection, conditional passes, and per-layer texture overrides.\n * @returns The selected model, or `undefined` when its dataset file is missing.\n */\n public static async getEntity(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n const model = await this.getModelFile(modelKey);\n if (!model) return undefined;\n // Without an explicit selection, draw what vanilla draws: main, then the passes enabled for the requested state.\n const passes = options?.layers || options?.layer !== undefined ? [] :\n (model.passes ?? []).filter(pass => pass.when === undefined || options?.when?.includes(pass.when));\n const draws: EntityModelPass[] = [...new Set(options?.layers ?? [options?.layer ?? \"main\"])].map(layer => ({ layer }));\n if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);\n draws.push(...passes);\n const names: string[] = [];\n const selected = draws.map(pass => {\n const layer = model.layers[pass.layer];\n if (!layer) {\n throw new MineRenderError(`Entity ${model.id} has no layer \"${pass.layer}\". Available layers: ${Object.keys(model.layers).join(\", \")}`);\n }\n // A pass may draw geometry that is already selected with another texture.\n let name = pass.layer;\n for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;\n names.push(name);\n return { name, layer, pass };\n });\n const layers: Record<string, EntityLayer> = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {\n const override = options?.textures?.[name] ?? (index === 0 ? textureKey : undefined);\n const textureLocation = pass.textureLocation ?? layer.textureLocation;\n let texture: Maybe<AssetKey>;\n if (override) {\n const path = isAssetKey(override) ? override.getFullPath() : override.path;\n texture = isAssetKey(override) && override.assetType === \"textures\" && path.startsWith(\"entity/\")\n ? override\n : new AssetKey(override.namespace, path, \"textures\", \"entity\", \"assets\", \".png\", isAssetKey(override) ? override.root : undefined);\n } else if (textureLocation !== undefined) {\n texture = AssetKey.parse(\"textures\", textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (isAssetKey(modelKey)) texture.root = modelKey.root;\n } else {\n texture = await this.resolveTexture(modelKey);\n }\n const render = pass.render ?? layer.render;\n return [name, { key: override ?? modelKey, texture, layer, ...(render && { render }), ...(pass.tint && { tint: pass.tint }) }];\n })));\n return { ...layers[names[0]], id: model.id, layers, ...(model.transform && { transform: model.transform }) };\n }\n\n /**\n * Native and sampled vanilla clips by name, or undefined when the model or selected version has none.\n */\n public static async getAnimations(modelKey: BasicAssetKey): Promise<Maybe<Record<string, EntityAnimation>>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models/animations\", \".json\", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : undefined));\n const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get<EntityAnimationFile>(key, AssetParser.JSON));\n return file?.animations;\n }\n\n /** Finds a fallback texture using the model path, its directory, and vanilla variant data. */\n public static async resolveTexture(modelKey: BasicAssetKey): Promise<Maybe<AssetKey>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const root = isAssetKey(modelKey) ? modelKey.root : undefined;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", root);\n const texture = await Caching.entityTextureCache.get(key.serialize(), async () => {\n const name = path.split(\"/\").pop()!;\n for (const candidate of [path, `${path}/${name}`]) {\n const texture = new AssetKey(modelKey.namespace, candidate, \"textures\", \"entity\", \"assets\", \".png\", root);\n if (await ModelTextures.get(texture)) return texture;\n }\n const listKey = new AssetKey(modelKey.namespace, \"_list\", `${name}_variant`, undefined, \"data\", \".json\", root);\n const list = await AssetLoader.get<ListAsset>(listKey, AssetParser.LIST);\n const files = list?.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\");\n const file = files?.find(file => file === \"temperate.json\") ?? files?.[0];\n if (!file) return Caching.MISSING;\n const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, undefined, \"data\", \".json\", root);\n const variant = await AssetLoader.get<EntityVariant>(variantKey, AssetParser.JSON);\n const assets = variant?.assets;\n const textureId = variant?.asset_id ?? (typeof assets?.wild === \"string\" ? assets.wild :\n Object.values(assets ?? {}).find(value => typeof value === \"string\"));\n if (typeof textureId !== \"string\") return Caching.MISSING;\n const texture = AssetKey.parse(\"textures\", textureId);\n texture.root = root;\n return texture;\n });\n return texture === Caching.MISSING ? undefined : texture;\n }\n\n /** @deprecated Use getEntityList(); block entities share the entity dataset. */\n public static getBlockList(): Promise<string[]> {\n return this.getEntityList();\n }\n\n /** @deprecated Use getEntity(); block entities share the entity dataset. */\n public static getBlock(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n return this.getEntity(modelKey, textureKey, options);\n }\n\n}\n\n/** Selection settings passed as the third argument to {@link Entities.getEntity}. */\nexport interface EntityModelOptions {\n /** Selects one geometry layer without dataset passes. `layers` takes precedence when supplied. */\n layer?: string;\n /** Layer names in draw order; an explicit selection draws exactly these layers and no dataset passes. */\n layers?: string[];\n /**\n * Entity states that enable the dataset's conditional passes, e.g. `[\"powered\"]` for a charged creeper.\n * Without `layer`/`layers`, `main` and every unconditional pass are always drawn.\n */\n when?: string[];\n /** Per-layer texture overrides, keyed like `EntityModel.layers`. The positional texture key applies to the first selected layer. */\n textures?: Record<string, BasicAssetKey>;\n}\n\ninterface EntityVariant extends MinecraftAsset {\n asset_id?: string;\n assets?: Record<string, unknown>;\n}\n"],"mappings":"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","names":["texture","file"]}
|
|
@@ -45,15 +45,21 @@ var ModelTextures = class {
|
|
|
45
45
|
key.extension += ".mcmeta";
|
|
46
46
|
}
|
|
47
47
|
const keyStr = key.serialize();
|
|
48
|
-
|
|
49
|
-
return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
const meta = await Caching.textureMetaCache.get(keyStr, (k) => {
|
|
49
|
+
return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), async (k1) => {
|
|
50
|
+
if (AssetLoader.persistentScope === "") {
|
|
51
|
+
const path = key.getFullPath();
|
|
52
|
+
const slash = path.lastIndexOf("/");
|
|
53
|
+
const listKey = new AssetKey(key.namespace, `${path.slice(0, slash + 1)}_list`, "textures", void 0, "assets", ".json", key.root);
|
|
54
|
+
const list = await Caching.listAssetCache.get(listKey.serialize(), () => AssetLoader.get(listKey, AssetParser.LIST)).catch(() => void 0);
|
|
55
|
+
if (list && !list.files.includes(`${path.slice(slash + 1)}${key.extension}`)) return Caching.MISSING;
|
|
56
|
+
}
|
|
57
|
+
const asset = await AssetLoader.get(key, AssetParser.META);
|
|
58
|
+
if (asset) asset.key = key;
|
|
59
|
+
return asset ?? Caching.MISSING;
|
|
55
60
|
});
|
|
56
61
|
});
|
|
62
|
+
return meta === Caching.MISSING ? void 0 : meta;
|
|
57
63
|
}
|
|
58
64
|
/** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */
|
|
59
65
|
static async clearCache() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/assets/ModelTextures.ts"],"sourcesContent":["import { Maybe } from \"../util/util\";\nimport { TextureAsset } from \"../model/Model\";\nimport { Caching } from \"../cache/Caching\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { ImageLoader } from \"../image/ImageLoader\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetKey } from \"./AssetKey\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\n\n/** Loads texture pixels and `.mcmeta` files through the active asset sources. */\nexport class ModelTextures {\n\n private static _persistentMetaCache: PersistentCache | undefined;\n\n private static get PERSISTENT_META_CACHE(): PersistentCache {\n return this._persistentMetaCache ??= PersistentCache.open(\"minerender-texturemeta\");\n }\n\n /** Loads and decodes a texture into a readable canvas, or returns `undefined` when missing. */\n public static async get(key: AssetKey): Promise<Maybe<ExtractableImageData>> {\n const keyStr = key.serialize();\n const pending = this.preload(key);\n const cached = Caching.textureAssetCache.getIfPresent(keyStr);\n try {\n const asset = await pending;\n if (asset) {\n return await ImageLoader.infoToCanvasData(asset);\n }\n return undefined;\n } catch (err) {\n // Discard corrupt encoded bytes, but preserve any newer load for this key.\n if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {\n Caching.textureAssetCache.invalidate(keyStr);\n }\n throw err;\n }\n }\n\n /** Fetches and caches encoded texture bytes without decoding the pixels. */\n public static async preload(key: AssetKey): Promise<Maybe<TextureAsset>> {\n const keyStr = key.serialize();\n return Caching.textureAssetCache.get(keyStr, k => {\n return AssetLoader.get<TextureAsset>(key, AssetParser.IMAGE).then(asset => {\n if (asset)\n asset.key = key;\n return asset;\n })\n })\n }\n\n /** Loads a texture's `.mcmeta` file, or returns `undefined` when no metadata file exists. */\n public static async getMeta(key: AssetKey): Promise<Maybe<MinecraftTextureMeta>> {\n if (!key.extension || !key.extension.endsWith(\".mcmeta\")) {\n key = Object.assign(new AssetKey(\"\", \"\"), key);\n key.extension += \".mcmeta\";\n }\n const keyStr = key.serialize();\n\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/assets/ModelTextures.ts"],"sourcesContent":["import { Maybe } from \"../util/util\";\nimport { TextureAsset } from \"../model/Model\";\nimport { Caching } from \"../cache/Caching\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { ImageLoader } from \"../image/ImageLoader\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetKey } from \"./AssetKey\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport type { ListAsset } from \"../ListAsset\";\n\n/** Loads texture pixels and `.mcmeta` files through the active asset sources. */\nexport class ModelTextures {\n\n private static _persistentMetaCache: PersistentCache | undefined;\n\n private static get PERSISTENT_META_CACHE(): PersistentCache {\n return this._persistentMetaCache ??= PersistentCache.open(\"minerender-texturemeta\");\n }\n\n /** Loads and decodes a texture into a readable canvas, or returns `undefined` when missing. */\n public static async get(key: AssetKey): Promise<Maybe<ExtractableImageData>> {\n const keyStr = key.serialize();\n const pending = this.preload(key);\n const cached = Caching.textureAssetCache.getIfPresent(keyStr);\n try {\n const asset = await pending;\n if (asset) {\n return await ImageLoader.infoToCanvasData(asset);\n }\n return undefined;\n } catch (err) {\n // Discard corrupt encoded bytes, but preserve any newer load for this key.\n if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {\n Caching.textureAssetCache.invalidate(keyStr);\n }\n throw err;\n }\n }\n\n /** Fetches and caches encoded texture bytes without decoding the pixels. */\n public static async preload(key: AssetKey): Promise<Maybe<TextureAsset>> {\n const keyStr = key.serialize();\n return Caching.textureAssetCache.get(keyStr, k => {\n return AssetLoader.get<TextureAsset>(key, AssetParser.IMAGE).then(asset => {\n if (asset)\n asset.key = key;\n return asset;\n })\n })\n }\n\n /** Loads a texture's `.mcmeta` file, or returns `undefined` when no metadata file exists. */\n public static async getMeta(key: AssetKey): Promise<Maybe<MinecraftTextureMeta>> {\n if (!key.extension || !key.extension.endsWith(\".mcmeta\")) {\n key = Object.assign(new AssetKey(\"\", \"\"), key);\n key.extension += \".mcmeta\";\n }\n const keyStr = key.serialize();\n\n const meta = await Caching.textureMetaCache.get(keyStr, k => {\n return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), async k1 => {\n if (AssetLoader.persistentScope === \"\") {\n const path = key.getFullPath();\n const slash = path.lastIndexOf(\"/\");\n const listKey = new AssetKey(key.namespace, `${path.slice(0, slash + 1)}_list`, \"textures\", undefined, \"assets\", \".json\", key.root);\n const list = await Caching.listAssetCache.get(listKey.serialize(), () => AssetLoader.get<ListAsset>(listKey, AssetParser.LIST)).catch(() => undefined);\n if (list && !list.files.includes(`${path.slice(slash + 1)}${key.extension}`)) return Caching.MISSING;\n }\n const asset = await AssetLoader.get<MinecraftTextureMeta>(key, AssetParser.META);\n if (asset) asset.key = key;\n return asset ?? Caching.MISSING;\n })\n });\n return meta === Caching.MISSING ? undefined : meta;\n }\n\n /** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */\n public static async clearCache() {\n await this.PERSISTENT_META_CACHE.clear();\n }\n\n}\n"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAG5B,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAIrB,IAAM,gBAAN,MAAoB;AAAA,EAIvB,WAAmB,wBAAyC;AACxD,WAAO,KAAK,yBAAL,KAAK,uBAAyB,gBAAgB,KAAK,wBAAwB;AAAA,EACtF;AAAA;AAAA,EAGA,aAAoB,IAAI,KAAqD;AACzE,UAAM,SAAS,IAAI,UAAU;AAC7B,UAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,UAAM,SAAS,QAAQ,kBAAkB,aAAa,MAAM;AAC5D,QAAI;AACA,YAAM,QAAQ,MAAM;AACpB,UAAI,OAAO;AACP,eAAO,MAAM,YAAY,iBAAiB,KAAK;AAAA,MACnD;AACA,aAAO;AAAA,IACX,SAAS,KAAK;AAEV,UAAI,UAAU,QAAQ,kBAAkB,aAAa,MAAM,MAAM,QAAQ;AACrE,gBAAQ,kBAAkB,WAAW,MAAM;AAAA,MAC/C;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA,EAGA,aAAoB,QAAQ,KAA6C;AACrE,UAAM,SAAS,IAAI,UAAU;AAC7B,WAAO,QAAQ,kBAAkB,IAAI,QAAQ,OAAK;AAC9C,aAAO,YAAY,IAAkB,KAAK,YAAY,KAAK,EAAE,KAAK,WAAS;AACvE,YAAI;AACA,gBAAM,MAAM;AAChB,eAAO;AAAA,MACX,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,aAAoB,QAAQ,KAAqD;AAC7E,QAAI,CAAC,IAAI,aAAa,CAAC,IAAI,UAAU,SAAS,SAAS,GAAG;AACtD,YAAM,OAAO,OAAO,IAAI,SAAS,IAAI,EAAE,GAAG,GAAG;AAC7C,UAAI,aAAa;AAAA,IACrB;AACA,UAAM,SAAS,IAAI,UAAU;AAE7B,UAAM,OAAO,MAAM,QAAQ,iBAAiB,IAAI,QAAQ,OAAK;AACzD,aAAO,KAAK,sBAAsB,UAAU,YAAY,cAAc,MAAM,GAAG,OAAM,OAAM;AACvF,YAAI,YAAY,oBAAoB,IAAI;AACpC,gBAAM,OAAO,IAAI,YAAY;AAC7B,gBAAM,QAAQ,KAAK,YAAY,GAAG;AAClC,gBAAM,UAAU,IAAI,SAAS,IAAI,WAAW,GAAG,KAAK,MAAM,GAAG,QAAQ,CAAC,CAAC,SAAS,YAAY,QAAW,UAAU,SAAS,IAAI,IAAI;AAClI,gBAAM,OAAO,MAAM,QAAQ,eAAe,IAAI,QAAQ,UAAU,GAAG,MAAM,YAAY,IAAe,SAAS,YAAY,IAAI,CAAC,EAAE,MAAM,MAAM,MAAS;AACrJ,cAAI,QAAQ,CAAC,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,EAAG,QAAO,QAAQ;AAAA,QACjG;AACA,cAAM,QAAQ,MAAM,YAAY,IAA0B,KAAK,YAAY,IAAI;AAC/E,YAAI,MAAO,OAAM,MAAM;AACvB,eAAO,SAAS,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACL,CAAC;AACD,WAAO,SAAS,QAAQ,UAAU,SAAY;AAAA,EAClD;AAAA;AAAA,EAGA,aAAoB,aAAa;AAC7B,UAAM,KAAK,sBAAsB,MAAM;AAAA,EAC3C;AAEJ;","names":[]}
|
|
@@ -67,6 +67,8 @@ var _Caching = class _Caching {
|
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
|
+
/** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */
|
|
71
|
+
_Caching.MISSING = false;
|
|
70
72
|
_Caching._generation = 0;
|
|
71
73
|
_Caching.rawImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(5)).buildAsync();
|
|
72
74
|
_Caching.imageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/cache/Caching.ts"],"sourcesContent":["import { AsyncLoadingCache, Caches, Loader, LoadingCache, SimpleCache } from \"@inventivetalent/loading-cache\";\nimport { BoxGeometryKey, CacheKey, serializeBoxGeometryKey, serializeImageKey, TextureKey } from \"./CacheKey\";\nimport { Time } from \"@inventivetalent/time\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { BoxGeometry, Material, Mesh, PixelFormat, RGBAFormat, Texture } from \"three\";\nimport { Materials } from \"../Materials\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { Model, TextureAsset } from \"../model/Model\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport type { EntityModelFile } from \"../entity/EntityModel\";\nimport type { EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport type { BlockEntityIndex } from \"../assets/BlockEntities\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport type { AssetKey } from \"../assets/AssetKey\";\nimport type { UnihexFile } from \"../assets/_fonts/Unihex\";\nimport type { BitmapFont } from \"../assets/Fonts\";\nimport type { BannerPattern } from \"../assets/BannerPatterns\";\nimport type { Biome } from \"../assets/Biomes\";\n\n/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */\nexport class Caching {\n\n private static _generation = 0;\n\n /** Changes when shared assets are cleared, so derived caches can discard their old values. */\n public static get generation(): number { return this._generation; }\n\n static readonly rawImageCache: AsyncLoadingCache<CacheKey, ImageInfo> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(5))\n .buildAsync<CacheKey, ImageInfo>();\n static readonly imageDataCache: AsyncLoadingCache<CacheKey, ImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ImageData>();\n static readonly canvasImageDataCache: AsyncLoadingCache<CacheKey, ExtractableImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ExtractableImageData>();\n static readonly wrappedImageCache: AsyncLoadingCache<CacheKey, WrappedImage> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, WrappedImage>();\n\n static readonly boxGeometryCache: SimpleCache<CacheKey, BoxGeometry> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(20))\n .build<CacheKey, BoxGeometry>();\n\n static readonly textureCache: SimpleCache<CacheKey, Texture> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Texture>();\n\n static readonly materialCache: SimpleCache<CacheKey, Material> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Material>();\n\n static readonly boxMeshCache: SimpleCache<CacheKey, Mesh> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Mesh>();\n\n static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAsset>();\n static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, MinecraftTextureMeta>();\n\n static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAtlas>();\n\n static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, BlockState>();\n\n static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset> = Caching.createAssetCache<ListAsset>();\n\n static readonly blockTintCache: AsyncLoadingCache<CacheKey, number> = Caching.createAssetCache<number>();\n\n static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile> = Caching.createAssetCache<EntityModelFile>();\n\n static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey> = Caching.createAssetCache<AssetKey>();\n\n static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile> = Caching.createAssetCache<EntityAnimationFile>();\n static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex> = Caching.createAssetCache<BlockEntityIndex>();\n static readonly entityDatasetVersionCache: AsyncLoadingCache<CacheKey, string> = Caching.createAssetCache<string>();\n static readonly unihexCache: AsyncLoadingCache<CacheKey, UnihexFile> = Caching.createAssetCache<UnihexFile>();\n static readonly fontCache: AsyncLoadingCache<CacheKey, BitmapFont> = Caching.createAssetCache<BitmapFont>();\n static readonly bannerPatternCache: AsyncLoadingCache<CacheKey, BannerPattern> = Caching.createAssetCache<BannerPattern>();\n static readonly mineRenderDataCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly usernameUuidCache: AsyncLoadingCache<CacheKey, string> = Caches.builder()\n .expireAfterWrite(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, string>();\n static readonly biomeCache: AsyncLoadingCache<CacheKey, Biome> = Caching.createAssetCache<Biome>();\n\n private static createAssetCache<T>(): AsyncLoadingCache<CacheKey, T> {\n return Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, T>();\n }\n\n\n /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */\n private static get all(): { invalidateAll(): void; end(): void }[] {\n return [\n this.rawImageCache,\n this.imageDataCache,\n this.canvasImageDataCache,\n this.wrappedImageCache,\n this.boxGeometryCache,\n this.textureCache,\n this.materialCache,\n this.boxMeshCache,\n this.textureAssetCache,\n this.textureMetaCache,\n this.rawModelCache,\n this.mergedModelCache,\n this.modelTextureAtlasCache,\n this.blockStateCache,\n this.listAssetCache,\n this.blockTintCache,\n this.entityModelCache,\n this.entityTextureCache,\n this.entityAnimationCache,\n this.blockEntityIndexCache,\n this.entityDatasetVersionCache,\n this.fontCache,\n this.unihexCache,\n this.bannerPatternCache,\n this.mineRenderDataCache,\n this.usernameUuidCache,\n this.biomeCache\n ];\n }\n\n /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */\n public static clear() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n }\n }\n\n /**\n * Clears every cache and stops its expiry timer.\n *\n * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.\n * Use {@link shutdown} to also stop requests and the shared Ticker.\n */\n public static end() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n cache.end();\n }\n }\n\n public static get cacheSizes() {\n return {\n //TODO\n }\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/cache/Caching.ts"],"sourcesContent":["import { AsyncLoadingCache, Caches, Loader, LoadingCache, SimpleCache } from \"@inventivetalent/loading-cache\";\nimport { BoxGeometryKey, CacheKey, serializeBoxGeometryKey, serializeImageKey, TextureKey } from \"./CacheKey\";\nimport { Time } from \"@inventivetalent/time\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { BoxGeometry, Material, Mesh, PixelFormat, RGBAFormat, Texture } from \"three\";\nimport { Materials } from \"../Materials\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { Model, TextureAsset } from \"../model/Model\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport type { EntityModelFile } from \"../entity/EntityModel\";\nimport type { EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport type { BlockEntityIndex } from \"../assets/BlockEntities\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport type { AssetKey } from \"../assets/AssetKey\";\nimport type { UnihexFile } from \"../assets/_fonts/Unihex\";\nimport type { BitmapFont } from \"../assets/Fonts\";\nimport type { BannerPattern } from \"../assets/BannerPatterns\";\nimport type { Biome } from \"../assets/Biomes\";\n\n/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */\nexport class Caching {\n\n /** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */\n public static readonly MISSING = false as const;\n\n private static _generation = 0;\n\n /** Changes when shared assets are cleared, so derived caches can discard their old values. */\n public static get generation(): number { return this._generation; }\n\n static readonly rawImageCache: AsyncLoadingCache<CacheKey, ImageInfo> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(5))\n .buildAsync<CacheKey, ImageInfo>();\n static readonly imageDataCache: AsyncLoadingCache<CacheKey, ImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ImageData>();\n static readonly canvasImageDataCache: AsyncLoadingCache<CacheKey, ExtractableImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ExtractableImageData>();\n static readonly wrappedImageCache: AsyncLoadingCache<CacheKey, WrappedImage> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, WrappedImage>();\n\n static readonly boxGeometryCache: SimpleCache<CacheKey, BoxGeometry> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(20))\n .build<CacheKey, BoxGeometry>();\n\n static readonly textureCache: SimpleCache<CacheKey, Texture> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Texture>();\n\n static readonly materialCache: SimpleCache<CacheKey, Material> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Material>();\n\n static readonly boxMeshCache: SimpleCache<CacheKey, Mesh> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Mesh>();\n\n static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAsset>();\n static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta | typeof Caching.MISSING> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, MinecraftTextureMeta | typeof Caching.MISSING>();\n\n static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAtlas>();\n\n static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, BlockState>();\n\n static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset> = Caching.createAssetCache<ListAsset>();\n\n static readonly blockTintCache: AsyncLoadingCache<CacheKey, number> = Caching.createAssetCache<number>();\n\n static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile> = Caching.createAssetCache<EntityModelFile>();\n\n static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey | typeof Caching.MISSING> = Caching.createAssetCache<AssetKey | typeof Caching.MISSING>();\n\n static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile> = Caching.createAssetCache<EntityAnimationFile>();\n static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex> = Caching.createAssetCache<BlockEntityIndex>();\n static readonly entityDatasetVersionCache: AsyncLoadingCache<CacheKey, string> = Caching.createAssetCache<string>();\n static readonly unihexCache: AsyncLoadingCache<CacheKey, UnihexFile> = Caching.createAssetCache<UnihexFile>();\n static readonly fontCache: AsyncLoadingCache<CacheKey, BitmapFont> = Caching.createAssetCache<BitmapFont>();\n static readonly bannerPatternCache: AsyncLoadingCache<CacheKey, BannerPattern> = Caching.createAssetCache<BannerPattern>();\n static readonly mineRenderDataCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly usernameUuidCache: AsyncLoadingCache<CacheKey, string> = Caches.builder()\n .expireAfterWrite(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, string>();\n static readonly biomeCache: AsyncLoadingCache<CacheKey, Biome> = Caching.createAssetCache<Biome>();\n\n private static createAssetCache<T>(): AsyncLoadingCache<CacheKey, T> {\n return Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, T>();\n }\n\n\n /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */\n private static get all(): { invalidateAll(): void; end(): void }[] {\n return [\n this.rawImageCache,\n this.imageDataCache,\n this.canvasImageDataCache,\n this.wrappedImageCache,\n this.boxGeometryCache,\n this.textureCache,\n this.materialCache,\n this.boxMeshCache,\n this.textureAssetCache,\n this.textureMetaCache,\n this.rawModelCache,\n this.mergedModelCache,\n this.modelTextureAtlasCache,\n this.blockStateCache,\n this.listAssetCache,\n this.blockTintCache,\n this.entityModelCache,\n this.entityTextureCache,\n this.entityAnimationCache,\n this.blockEntityIndexCache,\n this.entityDatasetVersionCache,\n this.fontCache,\n this.unihexCache,\n this.bannerPatternCache,\n this.mineRenderDataCache,\n this.usernameUuidCache,\n this.biomeCache\n ];\n }\n\n /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */\n public static clear() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n }\n }\n\n /**\n * Clears every cache and stops its expiry timer.\n *\n * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.\n * Use {@link shutdown} to also stop requests and the shared Ticker.\n */\n public static end() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n cache.end();\n }\n }\n\n public static get cacheSizes() {\n return {\n //TODO\n }\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1792,6 +1792,7 @@ declare class BlockObject extends SceneObject {
|
|
|
1792
1792
|
*/
|
|
1793
1793
|
private createBlockEntities;
|
|
1794
1794
|
private placeEntities;
|
|
1795
|
+
private placeEntity;
|
|
1795
1796
|
get isOccluding(): boolean;
|
|
1796
1797
|
private getModelMatrix;
|
|
1797
1798
|
private getModelCullMask;
|
|
@@ -2742,6 +2743,8 @@ interface UnihexFile {
|
|
|
2742
2743
|
|
|
2743
2744
|
/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */
|
|
2744
2745
|
declare class Caching {
|
|
2746
|
+
/** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */
|
|
2747
|
+
static readonly MISSING: false;
|
|
2745
2748
|
private static _generation;
|
|
2746
2749
|
/** Changes when shared assets are cleared, so derived caches can discard their old values. */
|
|
2747
2750
|
static get generation(): number;
|
|
@@ -2754,7 +2757,7 @@ declare class Caching {
|
|
|
2754
2757
|
static readonly materialCache: SimpleCache<CacheKey, Material>;
|
|
2755
2758
|
static readonly boxMeshCache: SimpleCache<CacheKey, Mesh>;
|
|
2756
2759
|
static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset>;
|
|
2757
|
-
static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta>;
|
|
2760
|
+
static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta | typeof Caching.MISSING>;
|
|
2758
2761
|
static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model>;
|
|
2759
2762
|
static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model>;
|
|
2760
2763
|
static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas>;
|
|
@@ -2762,7 +2765,7 @@ declare class Caching {
|
|
|
2762
2765
|
static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset>;
|
|
2763
2766
|
static readonly blockTintCache: AsyncLoadingCache<CacheKey, number>;
|
|
2764
2767
|
static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile>;
|
|
2765
|
-
static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey>;
|
|
2768
|
+
static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey | typeof Caching.MISSING>;
|
|
2766
2769
|
static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile>;
|
|
2767
2770
|
static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex>;
|
|
2768
2771
|
static readonly entityDatasetVersionCache: AsyncLoadingCache<CacheKey, string>;
|
|
@@ -108,17 +108,25 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
108
108
|
if (!key || this.options.displayPosition) return false;
|
|
109
109
|
const generation = this._entityGeneration;
|
|
110
110
|
const created = [];
|
|
111
|
+
const placement = new Matrix4();
|
|
111
112
|
let resolved;
|
|
112
113
|
try {
|
|
113
114
|
resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);
|
|
114
115
|
if (!resolved) return false;
|
|
116
|
+
BlockEntities.matrix(resolved, placement);
|
|
115
117
|
for (const part of resolved.parts) {
|
|
116
118
|
const [namespace, path] = part.model.includes(":") ? part.model.split(":") : [key.namespace, part.model];
|
|
117
|
-
|
|
119
|
+
let texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
|
|
120
|
+
if (part.textureLocation === void 0 && namespace === "minecraft" && path === "player_head") {
|
|
121
|
+
const { PlayerHeadTextures } = await import("../../../skin/PlayerHeadTextures.mjs");
|
|
122
|
+
texture = (await PlayerHeadTextures.get(void 0, key.root)).texture;
|
|
123
|
+
}
|
|
118
124
|
if (texture) texture.root = key.root;
|
|
119
125
|
const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });
|
|
120
126
|
if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);
|
|
121
|
-
|
|
127
|
+
const object = await this.scene.addEntity(entity, { wireframe: this.options.wireframe });
|
|
128
|
+
this.placeEntity(object, placement);
|
|
129
|
+
created.push(object);
|
|
122
130
|
}
|
|
123
131
|
} catch (error) {
|
|
124
132
|
log.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);
|
|
@@ -129,18 +137,21 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
129
137
|
this.removeEntities(created);
|
|
130
138
|
return true;
|
|
131
139
|
}
|
|
132
|
-
|
|
140
|
+
this._entityPlacement.copy(placement);
|
|
133
141
|
this._entities = created;
|
|
134
142
|
this.placeEntities();
|
|
135
143
|
this.setVisible(this.visible);
|
|
136
144
|
return true;
|
|
137
145
|
}
|
|
138
146
|
placeEntities() {
|
|
139
|
-
const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
|
|
140
147
|
for (const entity of this._entities) {
|
|
141
|
-
|
|
148
|
+
this.placeEntity(entity, this._entityPlacement);
|
|
142
149
|
}
|
|
143
150
|
}
|
|
151
|
+
placeEntity(entity, placement) {
|
|
152
|
+
const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(placement);
|
|
153
|
+
matrix.decompose(entity.position, entity.quaternion, entity.scale);
|
|
154
|
+
}
|
|
144
155
|
get isOccluding() {
|
|
145
156
|
if (!this.visible) {
|
|
146
157
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/model/block/scene/BlockObject.ts"],"sourcesContent":["import { SceneObject } from \"../../../renderer/SceneObject\";\nimport { BlockState, BlockStateVariant } from \"../BlockState\";\nimport { SceneObjectOptions } from \"../../../renderer/SceneObjectOptions\";\nimport { isModelObject, ModelObject, ModelObjectOptions } from \"../../scene/ModelObject\";\nimport { Caching } from \"../../../cache/Caching\";\nimport { Models } from \"../../../assets/Models\";\nimport { merge } from \"../../../util/_internal/merge\";\nimport { Euler, Matrix4, Quaternion, Vector3 } from \"three\";\nimport { Maybe } from \"../../../util/util\";\nimport { MineRenderError } from \"../../../error/MineRenderError\";\nimport { BlockStateProperties, BlockStatePropertyDefaults } from \"../BlockStateProperties\";\nimport { InstanceReference, isInstanceReference } from \"../../../instance/InstanceReference\";\nimport { AssetKey, BasicAssetKey } from \"../../../assets/AssetKey\";\nimport { BlockTints } from \"../BlockTints\";\nimport { ModelCulling } from \"../../ModelCulling\";\nimport { BlockStateResolver } from \"../BlockStateResolver\";\nimport { FluidKind, FluidRules, FluidSampler, resolveBlockFluidState } from \"../../fluid/FluidGeometry\";\nimport { MineRenderData } from \"../../../assets/MineRenderData\";\nimport { BlockEntities, ResolvedBlockEntity } from \"../../../assets/BlockEntities\";\nimport { Entities } from \"../../../assets/Entities\";\nimport type { EntityObject } from \"../../../entity/scene/EntityObject\";\nimport { Biomes } from \"../../../assets/Biomes\";\nimport type { TripleArray } from \"../../Model\";\nimport { logger } from \"../../../util/log\";\n\nconst log = logger(\"BlockObject\");\n\n/** Controls the model parts selected by a blockstate. Create it through {@link MineRenderScene.addBlock}. */\nexport class BlockObject extends SceneObject {\n\n public readonly isBlockObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: BlockObjectOptions = merge({}, ModelObject.DEFAULT_OPTIONS, <BlockObjectOptions>{\n applyDefaultState: true\n });\n public readonly options: BlockObjectOptions;\n private readonly variantPosition?: TripleArray;\n\n private _previousState: BlockStateProperties = {};\n private _state: BlockStateProperties = {};\n private _variant: Maybe<BlockStateVariant> = undefined;\n\n private _instanceState: BlockStateProperties[] = [];\n private _instanceVariant: BlockStateVariant[][] = [];\n private _instanceModel: (ModelObject | InstanceReference<ModelObject>)[] = [];\n\n private _variants: BlockStateVariant[] = [];\n private _models: (ModelObject | InstanceReference<ModelObject>)[] = [];\n private _cullMask = 0;\n private _fluidKey?: string;\n private _fluidRules: FluidRules = {};\n private _fluidSampler?: FluidSampler;\n private readonly biomePosition?: TripleArray;\n private waterTint?: number;\n private _fluidModel?: ModelObject | InstanceReference<ModelObject>;\n private _entities: EntityObject[] = [];\n private _entityPlacement = new Matrix4();\n private _entityGeneration = 0;\n\n constructor(readonly blockState: BlockState, options?: Partial<BlockObjectOptions>) {\n super(options);\n this.options = merge({}, BlockObject.DEFAULT_OPTIONS, options ?? {});\n this.variantPosition = options?.variantPosition ? [...options.variantPosition] : undefined;\n this.biomePosition = options?.biomePosition ? [...options.biomePosition] : undefined;\n //TODO\n }\n\n async init(): Promise<void> {\n this._fluidRules = await MineRenderData.get(\"fluids\", this.blockState.key?.root);\n if (this.options.applyDefaultState) {\n this._setState(await BlockStateResolver.defaults(this.blockState));\n }\n if (this.options.initialState !== undefined) this._setState(this.options.initialState);\n await this.recreateModels();\n //TODO\n }\n\n dispose() {\n this.clearModels();\n super.dispose();\n }\n\n removeFromScene() {\n this.clearModels();\n super.removeFromScene();\n }\n\n private clearModels() {\n this.removeModels(this._models.splice(0));\n this._entityGeneration++;\n this.removeEntities(this._entities.splice(0));\n this._fluidKey = undefined;\n this._fluidModel = undefined;\n this._isInstanced = false;\n this._instanceCounter = 0;\n }\n\n private removeModels(models: (ModelObject | InstanceReference<ModelObject>)[]) {\n for (const model of models) {\n model.removeFromScene();\n if (!isInstanceReference(model)) model.dispose();\n }\n }\n\n private removeEntities(entities: EntityObject[]) {\n for (const entity of entities) {\n entity.removeFromScene();\n entity.dispose();\n }\n }\n\n /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */\n public get blockEntities(): readonly EntityObject[] {\n return this._entities;\n }\n\n /** Model placements drawn for this block, including its fluid surface. */\n public get models(): readonly (ModelObject | InstanceReference<ModelObject>)[] {\n return this._models;\n }\n\n /** Sets visibility for this block's model instances and block entities. */\n public setVisible(visible: boolean): void {\n this.visible = visible;\n for (const model of this._models) {\n if (isInstanceReference(model)) {\n model.setVisible(visible);\n } else {\n model.visible = visible;\n }\n }\n for (const entity of this._entities) {\n entity.visible = visible;\n }\n this.notifyDirty();\n }\n\n /**\n * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,\n * when the block is not listed or one of its models cannot be loaded.\n */\n private async createBlockEntities(): Promise<boolean> {\n const key = this.blockState.key;\n if (!key || this.options.displayPosition) return false;\n const generation = this._entityGeneration;\n const created: EntityObject[] = [];\n let resolved: Maybe<ResolvedBlockEntity>;\n try {\n resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);\n if (!resolved) return false;\n for (const part of resolved.parts) {\n const [namespace, path] = part.model.includes(\":\") ? part.model.split(\":\") : [key.namespace, part.model];\n const texture = part.textureLocation === undefined ? undefined\n : AssetKey.parse(\"textures\", part.textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (texture) texture.root = key.root;\n const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });\n if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);\n created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }) as EntityObject);\n }\n } catch (error) {\n log.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);\n this.removeEntities(created);\n return false;\n }\n // The block was cleared while the models loaded.\n if (generation !== this._entityGeneration) {\n this.removeEntities(created);\n return true;\n }\n BlockEntities.matrix(resolved, this._entityPlacement);\n this._entities = created;\n this.placeEntities();\n this.setVisible(this.visible);\n return true;\n }\n\n private placeEntities() {\n // Block models are centred on the block position; entity transforms use the block's 0..16 space.\n const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);\n for (const entity of this._entities) {\n matrix.decompose(entity.position, entity.quaternion, entity.scale);\n }\n }\n\n public get isOccluding(): boolean {\n if (!this.visible) {\n return false;\n }\n return this._models.some(model => {\n const object = isInstanceReference(model) ? model.instanceable : model;\n return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;\n });\n }\n\n private getModelMatrix(model: ModelObject | InstanceReference<ModelObject>): Matrix4 {\n if (isInstanceReference(model)) return model.getMatrix();\n if (model.matrixAutoUpdate) model.updateMatrix();\n return model.matrix.clone();\n }\n\n private getModelCullMask(model: ModelObject | InstanceReference<ModelObject>, worldMask: number): number {\n const object = isInstanceReference(model) ? model.instanceable : model;\n if (object.options.displayPosition) return 0;\n const position = new Vector3();\n const rotation = new Quaternion();\n const scale = new Vector3();\n this.getModelMatrix(model).decompose(position, rotation, scale);\n if (position.distanceToSquared(this.position) > 1e-10\n || scale.distanceToSquared(new Vector3(1, 1, 1)) > 1e-10) return 0;\n return ModelCulling.toLocalMask(worldMask, new Euler().setFromQuaternion(rotation));\n }\n\n /** World-space face mask currently applied to this block. */\n public get cullMask(): number {\n return this._cullMask;\n }\n\n public async setCullMask(worldMask: number): Promise<void> {\n worldMask &= 63;\n const replacements: (ModelObject | InstanceReference<ModelObject>)[] = [];\n try {\n for (const model of this._models) {\n if (model === this._fluidModel) {\n replacements.push(model);\n continue;\n }\n const object = isInstanceReference(model) ? model.instanceable : model;\n const cullMask = this.getModelCullMask(model, worldMask);\n if (cullMask === (object.options.cullMask ?? 0)) {\n replacements.push(model);\n continue;\n }\n const matrix = this.getModelMatrix(model);\n const replacement = await this.scene.addModel(object.originalModel, { ...object.options, cullMask });\n replacements.push(replacement);\n if (isInstanceReference(replacement)) {\n replacement.setMatrix(matrix);\n } else {\n replacement.matrix.copy(matrix);\n replacement.matrixWorldNeedsUpdate = true;\n matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n replacement.matrixAutoUpdate = object.matrixAutoUpdate;\n replacement.visible = object.visible;\n }\n }\n } catch (error) {\n this.removeModels(replacements.filter(model => !this._models.includes(model)));\n throw error;\n }\n const previous = this._models;\n this._models = replacements;\n this._cullMask = worldMask;\n this.removeModels(previous.filter(model => !replacements.includes(model)));\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n /** Selected property values. Use {@link setState} to change properties and rebuild the rendered models. */\n public get state(): { [key: string]: string; } {\n return this._state;\n }\n\n public get fluidKind(): FluidKind | undefined {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.kind;\n }\n\n public get fluidLevel(): number {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.level ?? 0;\n }\n\n /** Refreshes fluid surfaces from relative neighbors; standalone previews use air around the block. */\n public async updateFluid(sample?: FluidSampler): Promise<void> {\n const kind = this.fluidKind;\n if (!kind) return;\n const { FluidModelObject, sampleFluid } = await import(\"../../fluid/FluidModelObject\");\n this._fluidSampler = sample;\n const surface = sampleFluid(kind, (x, y, z) => x === 0 && y === 0 && z === 0\n ? { fluid: kind, level: this.fluidLevel } : sample?.(x, y, z) ?? {});\n const tint = this.options.tints?.[0] ?? this.waterTint;\n const fluidKey = `${surface.key}|${tint ?? \"default\"}`;\n if (this._fluidKey === fluidKey) return;\n const key = new AssetKey(\"minecraft\", `${kind}/${surface.key}`, \"models\", \"fluid\", \"assets\", \".json\", this.blockState.key?.root);\n const replacement = await this.scene.addSceneObject({ key },\n () => new FluidModelObject(kind, surface.sample, this.blockState.key, {\n ...this.options, tints: tint === undefined ? this.options.tints : { ...this.options.tints, 0: tint }\n }));\n const previous = this._fluidModel;\n const matrix = previous ? this.getModelMatrix(previous) : new Matrix4().makeTranslation(...this.position.toArray());\n if (isInstanceReference(replacement)) replacement.setMatrix(matrix);\n else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n this._models = this._models.filter(model => model !== previous);\n this._models.push(replacement);\n this._fluidModel = replacement;\n this._fluidKey = fluidKey;\n this._isInstanced ||= isInstanceReference(replacement);\n this._instanceCounter = this._isInstanced ? 1 : 0;\n if (previous) this.removeModels([previous]);\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n nextInstance(): InstanceReference<SceneObject> {\n\n const ref = super.nextInstance();\n for (let child of this.children) {\n if (isModelObject(child)) {\n child._instanceCounter = this.instanceCounter;\n }\n }\n return ref;\n }\n\n protected async mapStateToVariant(state: BlockStateProperties): Promise<BlockStateVariant[]> {\n return BlockStateResolver.select(this.blockState, state, variants => this.getSingleVariant(variants));\n }\n\n public async recreateModels(): Promise<void> {\n //TODO: change this to create models once, and then modify rotations when updating the state\n\n // Remove all children\n // this.disposeAndRemoveAllChildren(); //TODO: just removes all children of all instances atm...\n\n // TODO: try to reuse models instead of just removing them and creating new ones\n this.clearModels();\n\n this.waterTint = this.fluidKind === \"water\" && this.options.biome && this.options.tints?.[0] === undefined\n ? await Biomes.getColor(this.options.biome, \"water\", this.blockState.key) : undefined;\n\n if (resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.renderModel === false) {\n await this.updateFluid(this._fluidSampler);\n return;\n }\n\n\n //TODO: might want to preload all possible states & cache their data\n //TODO: make sure to only instance stuff with different rotations together; i.e. not those with different multipart settings, or different models\n\n /*\n if (this.isInstanced) {\n //TODO: only map once per state\n for (let i = 0; i < this.instanceCounter; i++) {\n this._instanceVariant[i] = await this.mapStateToVariant(this._instanceState[i]);\n for (let variant of this._instanceVariant[i]) {\n this._instanceModel[i] = await this.createVariant(variant);\n }\n }\n //TODO: actually create\n //TODO: group by model\n this._isInstanced = true;\n } else {\n */\n const hasEntities = await this.createBlockEntities();\n const variantsToCreate = await this.mapStateToVariant(this.state);\n this._variants = variantsToCreate;\n for (let blockStateVariant of variantsToCreate) {\n // A block entity replaces only block models without geometry (a chest); a bell keeps its frame.\n if (hasEntities && !await this.hasGeometry(blockStateVariant)) continue;\n this._models.push(await this.createVariant(blockStateVariant));\n }\n await this.updateFluid(this._fluidSampler);\n this.setVisible(this.visible);\n /*\n }\n\n */\n\n }\n\n private async hasGeometry(variant: BlockStateVariant): Promise<boolean> {\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n return !!(await Models.getMerged(modelKey))?.elements?.length;\n }\n\n protected getSingleVariant(variants: BlockStateVariant | BlockStateVariant[]): BlockStateVariant {\n return BlockStateResolver.choose(variants, this.variantPosition);\n }\n\n // @deprecated\n protected async createAVariant(variants: BlockStateVariant | BlockStateVariant[], instanceInfo: Matrix4[]) {\n const variant = this.getSingleVariant(variants);\n await this.createVariant(variant);\n }\n\n protected async createVariant(variant: BlockStateVariant): Promise<ModelObject | InstanceReference<ModelObject>> {\n const rotation = BlockStateResolver.rotation(variant);\n\n // The model and its textures must come from the same asset root as the blockstate.\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n const model = await Models.getMerged(modelKey);\n const options: Partial<ModelObjectOptions> = {\n ...this.options,\n tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints,\n () => BlockTints.getBiomeColor(this.blockState.key, this.options.biome, this.biomePosition)) : this.options.tints,\n uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0)\n ? [rotation.x, rotation.y, rotation.z] : undefined,\n cullMask: this.options.displayPosition ? 0 : ModelCulling.toLocalMask(this._cullMask, rotation)\n };\n const obj = await this.scene.addModel(model!, options);\n if (isInstanceReference(obj) || (<ModelObject>obj).isInstanced) {\n this._isInstanced = true;\n this._instanceCounter = 1;//TODO: BlockObject itself isn't technically instanced, but needs the id for the get/setMatrix calls to work properly\n }\n obj.setRotation(rotation);\n obj.setPosition(this.position);\n return obj;\n }\n\n /** Clears selected properties and rebuilds models without reapplying property defaults. */\n public async resetState() {\n this._previousState = this._state;\n this._state = {};\n await this.recreateModels();\n }\n\n // TODO: support state per instance\n /**\n * Updates properties and rebuilds the selected models.\n * Accepts `\"facing=north,open=true\"`, a property object, or a key and value.\n * Properties omitted from the call keep their current values.\n */\n public async setState(string: string);\n public async setState(state: BlockStateProperties);\n public async setState(key: string, value: string);\n public async setState(stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setState(stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setState(stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n this._previousState = this._state;\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setState(k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._state[k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._state[stringOrKeyOrState as string] = value;\n }\n }\n\n /*\n public async setStateAt(index: number, string: string);\n public async setStateAt(index: number, state: BlockStateProperties);\n public async setStateAt(index: number, key: string, value: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setStateAt(index, stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n if (!this._instanceState[index]) this._instanceState[index] = {};\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setStateAt(index, k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._instanceState[index][k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._instanceState[index][stringOrKeyOrState as string] = value;\n }\n }\n\n _getStateAt(index: number): BlockStateProperties {\n return this._instanceState[index];\n }\n\n */\n\n setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3) {\n super.setPositionRotationScaleAt(index, position, rotation, scale);\n }\n\n getMatrixAt(index: number, matrix: Matrix4 = new Matrix4()): Matrix4 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const child = this._models[0];\n if (child && isModelObject(child)) {\n child.getMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.getMatrix(matrix);\n }\n /*\n const child = this.children[0];\n if (child && isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.getMatrixAt(index, matrix);\n }\n return matrix;\n */\n // return super.getMatrixAt(0, matrix);\n return matrix;\n }\n\n setMatrixAt(index: number, matrix: Matrix4) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n // const child = this._models[0];\n for(let child of this._models) {\n if (child && isModelObject(child)) {\n child.setMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.setMatrix(matrix);\n }\n }\n /*\n for (let child of this.children) {\n if (isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.setMatrixAt(index, matrix);\n }\n }\n */\n }\n\n setPosition(position: Vector3) {\n this.position.copy(position);\n // Each part keeps its own variant rotation when the block moves.\n for (let model of this._models) {\n model.setPosition(position);\n }\n this.placeEntities();\n this.notifyDirty();\n }\n\n //TODO: should override rotation + scale methods\n\n //TODO\n\n}\n\n/** Block settings passed to `scene.addBlock(blockState, options)` or the BlockObject constructor. */\nexport interface BlockObjectOptions extends ModelObjectOptions {\n /** Loads vanilla property defaults before applying `initialState`. Defaults to `true`. */\n applyDefaultState: boolean;\n /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */\n initialState?: BlockStateProperties;\n /** Absolute block coordinates for repeatable variants, copied at construction. Omit for random previews. */\n variantPosition?: TripleArray;\n /** Saved biome ID used for automatic grass, foliage, and water colors. */\n biome?: string;\n /** World block coordinates used by biome grass modifiers. Copied at construction; defaults to the origin. */\n biomePosition?: TripleArray;\n}\n\nexport function isBlockObject(obj: any): obj is BlockObject {\n return (<BlockObject>obj).isBlockObject;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/model/block/scene/BlockObject.ts"],"sourcesContent":["import { SceneObject } from \"../../../renderer/SceneObject\";\nimport { BlockState, BlockStateVariant } from \"../BlockState\";\nimport { SceneObjectOptions } from \"../../../renderer/SceneObjectOptions\";\nimport { isModelObject, ModelObject, ModelObjectOptions } from \"../../scene/ModelObject\";\nimport { Caching } from \"../../../cache/Caching\";\nimport { Models } from \"../../../assets/Models\";\nimport { merge } from \"../../../util/_internal/merge\";\nimport { Euler, Matrix4, Quaternion, Vector3 } from \"three\";\nimport { Maybe } from \"../../../util/util\";\nimport { MineRenderError } from \"../../../error/MineRenderError\";\nimport { BlockStateProperties, BlockStatePropertyDefaults } from \"../BlockStateProperties\";\nimport { InstanceReference, isInstanceReference } from \"../../../instance/InstanceReference\";\nimport { AssetKey, BasicAssetKey } from \"../../../assets/AssetKey\";\nimport { BlockTints } from \"../BlockTints\";\nimport { ModelCulling } from \"../../ModelCulling\";\nimport { BlockStateResolver } from \"../BlockStateResolver\";\nimport { FluidKind, FluidRules, FluidSampler, resolveBlockFluidState } from \"../../fluid/FluidGeometry\";\nimport { MineRenderData } from \"../../../assets/MineRenderData\";\nimport { BlockEntities, ResolvedBlockEntity } from \"../../../assets/BlockEntities\";\nimport { Entities } from \"../../../assets/Entities\";\nimport type { EntityObject } from \"../../../entity/scene/EntityObject\";\nimport { Biomes } from \"../../../assets/Biomes\";\nimport type { TripleArray } from \"../../Model\";\nimport { logger } from \"../../../util/log\";\n\nconst log = logger(\"BlockObject\");\n\n/** Controls the model parts selected by a blockstate. Create it through {@link MineRenderScene.addBlock}. */\nexport class BlockObject extends SceneObject {\n\n public readonly isBlockObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: BlockObjectOptions = merge({}, ModelObject.DEFAULT_OPTIONS, <BlockObjectOptions>{\n applyDefaultState: true\n });\n public readonly options: BlockObjectOptions;\n private readonly variantPosition?: TripleArray;\n\n private _previousState: BlockStateProperties = {};\n private _state: BlockStateProperties = {};\n private _variant: Maybe<BlockStateVariant> = undefined;\n\n private _instanceState: BlockStateProperties[] = [];\n private _instanceVariant: BlockStateVariant[][] = [];\n private _instanceModel: (ModelObject | InstanceReference<ModelObject>)[] = [];\n\n private _variants: BlockStateVariant[] = [];\n private _models: (ModelObject | InstanceReference<ModelObject>)[] = [];\n private _cullMask = 0;\n private _fluidKey?: string;\n private _fluidRules: FluidRules = {};\n private _fluidSampler?: FluidSampler;\n private readonly biomePosition?: TripleArray;\n private waterTint?: number;\n private _fluidModel?: ModelObject | InstanceReference<ModelObject>;\n private _entities: EntityObject[] = [];\n private _entityPlacement = new Matrix4();\n private _entityGeneration = 0;\n\n constructor(readonly blockState: BlockState, options?: Partial<BlockObjectOptions>) {\n super(options);\n this.options = merge({}, BlockObject.DEFAULT_OPTIONS, options ?? {});\n this.variantPosition = options?.variantPosition ? [...options.variantPosition] : undefined;\n this.biomePosition = options?.biomePosition ? [...options.biomePosition] : undefined;\n //TODO\n }\n\n async init(): Promise<void> {\n this._fluidRules = await MineRenderData.get(\"fluids\", this.blockState.key?.root);\n if (this.options.applyDefaultState) {\n this._setState(await BlockStateResolver.defaults(this.blockState));\n }\n if (this.options.initialState !== undefined) this._setState(this.options.initialState);\n await this.recreateModels();\n //TODO\n }\n\n dispose() {\n this.clearModels();\n super.dispose();\n }\n\n removeFromScene() {\n this.clearModels();\n super.removeFromScene();\n }\n\n private clearModels() {\n this.removeModels(this._models.splice(0));\n this._entityGeneration++;\n this.removeEntities(this._entities.splice(0));\n this._fluidKey = undefined;\n this._fluidModel = undefined;\n this._isInstanced = false;\n this._instanceCounter = 0;\n }\n\n private removeModels(models: (ModelObject | InstanceReference<ModelObject>)[]) {\n for (const model of models) {\n model.removeFromScene();\n if (!isInstanceReference(model)) model.dispose();\n }\n }\n\n private removeEntities(entities: EntityObject[]) {\n for (const entity of entities) {\n entity.removeFromScene();\n entity.dispose();\n }\n }\n\n /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */\n public get blockEntities(): readonly EntityObject[] {\n return this._entities;\n }\n\n /** Model placements drawn for this block, including its fluid surface. */\n public get models(): readonly (ModelObject | InstanceReference<ModelObject>)[] {\n return this._models;\n }\n\n /** Sets visibility for this block's model instances and block entities. */\n public setVisible(visible: boolean): void {\n this.visible = visible;\n for (const model of this._models) {\n if (isInstanceReference(model)) {\n model.setVisible(visible);\n } else {\n model.visible = visible;\n }\n }\n for (const entity of this._entities) {\n entity.visible = visible;\n }\n this.notifyDirty();\n }\n\n /**\n * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,\n * when the block is not listed or one of its models cannot be loaded.\n */\n private async createBlockEntities(): Promise<boolean> {\n const key = this.blockState.key;\n if (!key || this.options.displayPosition) return false;\n const generation = this._entityGeneration;\n const created: EntityObject[] = [];\n const placement = new Matrix4();\n let resolved: Maybe<ResolvedBlockEntity>;\n try {\n resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);\n if (!resolved) return false;\n BlockEntities.matrix(resolved, placement);\n for (const part of resolved.parts) {\n const [namespace, path] = part.model.includes(\":\") ? part.model.split(\":\") : [key.namespace, part.model];\n let texture = part.textureLocation === undefined ? undefined\n : AssetKey.parse(\"textures\", part.textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (part.textureLocation === undefined && namespace === \"minecraft\" && path === \"player_head\") {\n const { PlayerHeadTextures } = await import(\"../../../skin/PlayerHeadTextures\");\n texture = (await PlayerHeadTextures.get(undefined, key.root)).texture;\n }\n if (texture) texture.root = key.root;\n const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });\n if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);\n const object = await this.scene.addEntity(entity, { wireframe: this.options.wireframe }) as EntityObject;\n this.placeEntity(object, placement);\n created.push(object);\n }\n } catch (error) {\n log.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);\n this.removeEntities(created);\n return false;\n }\n // The block was cleared while the models loaded.\n if (generation !== this._entityGeneration) {\n this.removeEntities(created);\n return true;\n }\n this._entityPlacement.copy(placement);\n this._entities = created;\n this.placeEntities();\n this.setVisible(this.visible);\n return true;\n }\n\n private placeEntities() {\n for (const entity of this._entities) {\n this.placeEntity(entity, this._entityPlacement);\n }\n }\n\n private placeEntity(entity: EntityObject, placement: Matrix4) {\n // Block models are centred on the block position; entity transforms use the block's 0..16 space.\n const matrix = new Matrix4().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(placement);\n matrix.decompose(entity.position, entity.quaternion, entity.scale);\n }\n\n public get isOccluding(): boolean {\n if (!this.visible) {\n return false;\n }\n return this._models.some(model => {\n const object = isInstanceReference(model) ? model.instanceable : model;\n return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;\n });\n }\n\n private getModelMatrix(model: ModelObject | InstanceReference<ModelObject>): Matrix4 {\n if (isInstanceReference(model)) return model.getMatrix();\n if (model.matrixAutoUpdate) model.updateMatrix();\n return model.matrix.clone();\n }\n\n private getModelCullMask(model: ModelObject | InstanceReference<ModelObject>, worldMask: number): number {\n const object = isInstanceReference(model) ? model.instanceable : model;\n if (object.options.displayPosition) return 0;\n const position = new Vector3();\n const rotation = new Quaternion();\n const scale = new Vector3();\n this.getModelMatrix(model).decompose(position, rotation, scale);\n if (position.distanceToSquared(this.position) > 1e-10\n || scale.distanceToSquared(new Vector3(1, 1, 1)) > 1e-10) return 0;\n return ModelCulling.toLocalMask(worldMask, new Euler().setFromQuaternion(rotation));\n }\n\n /** World-space face mask currently applied to this block. */\n public get cullMask(): number {\n return this._cullMask;\n }\n\n public async setCullMask(worldMask: number): Promise<void> {\n worldMask &= 63;\n const replacements: (ModelObject | InstanceReference<ModelObject>)[] = [];\n try {\n for (const model of this._models) {\n if (model === this._fluidModel) {\n replacements.push(model);\n continue;\n }\n const object = isInstanceReference(model) ? model.instanceable : model;\n const cullMask = this.getModelCullMask(model, worldMask);\n if (cullMask === (object.options.cullMask ?? 0)) {\n replacements.push(model);\n continue;\n }\n const matrix = this.getModelMatrix(model);\n const replacement = await this.scene.addModel(object.originalModel, { ...object.options, cullMask });\n replacements.push(replacement);\n if (isInstanceReference(replacement)) {\n replacement.setMatrix(matrix);\n } else {\n replacement.matrix.copy(matrix);\n replacement.matrixWorldNeedsUpdate = true;\n matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n replacement.matrixAutoUpdate = object.matrixAutoUpdate;\n replacement.visible = object.visible;\n }\n }\n } catch (error) {\n this.removeModels(replacements.filter(model => !this._models.includes(model)));\n throw error;\n }\n const previous = this._models;\n this._models = replacements;\n this._cullMask = worldMask;\n this.removeModels(previous.filter(model => !replacements.includes(model)));\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n /** Selected property values. Use {@link setState} to change properties and rebuild the rendered models. */\n public get state(): { [key: string]: string; } {\n return this._state;\n }\n\n public get fluidKind(): FluidKind | undefined {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.kind;\n }\n\n public get fluidLevel(): number {\n return resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.level ?? 0;\n }\n\n /** Refreshes fluid surfaces from relative neighbors; standalone previews use air around the block. */\n public async updateFluid(sample?: FluidSampler): Promise<void> {\n const kind = this.fluidKind;\n if (!kind) return;\n const { FluidModelObject, sampleFluid } = await import(\"../../fluid/FluidModelObject\");\n this._fluidSampler = sample;\n const surface = sampleFluid(kind, (x, y, z) => x === 0 && y === 0 && z === 0\n ? { fluid: kind, level: this.fluidLevel } : sample?.(x, y, z) ?? {});\n const tint = this.options.tints?.[0] ?? this.waterTint;\n const fluidKey = `${surface.key}|${tint ?? \"default\"}`;\n if (this._fluidKey === fluidKey) return;\n const key = new AssetKey(\"minecraft\", `${kind}/${surface.key}`, \"models\", \"fluid\", \"assets\", \".json\", this.blockState.key?.root);\n const replacement = await this.scene.addSceneObject({ key },\n () => new FluidModelObject(kind, surface.sample, this.blockState.key, {\n ...this.options, tints: tint === undefined ? this.options.tints : { ...this.options.tints, 0: tint }\n }));\n const previous = this._fluidModel;\n const matrix = previous ? this.getModelMatrix(previous) : new Matrix4().makeTranslation(...this.position.toArray());\n if (isInstanceReference(replacement)) replacement.setMatrix(matrix);\n else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);\n this._models = this._models.filter(model => model !== previous);\n this._models.push(replacement);\n this._fluidModel = replacement;\n this._fluidKey = fluidKey;\n this._isInstanced ||= isInstanceReference(replacement);\n this._instanceCounter = this._isInstanced ? 1 : 0;\n if (previous) this.removeModels([previous]);\n if (!this.visible) {\n this.setVisible(false);\n }\n this.notifyDirty();\n }\n\n nextInstance(): InstanceReference<SceneObject> {\n\n const ref = super.nextInstance();\n for (let child of this.children) {\n if (isModelObject(child)) {\n child._instanceCounter = this.instanceCounter;\n }\n }\n return ref;\n }\n\n protected async mapStateToVariant(state: BlockStateProperties): Promise<BlockStateVariant[]> {\n return BlockStateResolver.select(this.blockState, state, variants => this.getSingleVariant(variants));\n }\n\n public async recreateModels(): Promise<void> {\n //TODO: change this to create models once, and then modify rotations when updating the state\n\n // Remove all children\n // this.disposeAndRemoveAllChildren(); //TODO: just removes all children of all instances atm...\n\n // TODO: try to reuse models instead of just removing them and creating new ones\n this.clearModels();\n\n this.waterTint = this.fluidKind === \"water\" && this.options.biome && this.options.tints?.[0] === undefined\n ? await Biomes.getColor(this.options.biome, \"water\", this.blockState.key) : undefined;\n\n if (resolveBlockFluidState(this.blockState.key, this.state, this._fluidRules)?.renderModel === false) {\n await this.updateFluid(this._fluidSampler);\n return;\n }\n\n\n //TODO: might want to preload all possible states & cache their data\n //TODO: make sure to only instance stuff with different rotations together; i.e. not those with different multipart settings, or different models\n\n /*\n if (this.isInstanced) {\n //TODO: only map once per state\n for (let i = 0; i < this.instanceCounter; i++) {\n this._instanceVariant[i] = await this.mapStateToVariant(this._instanceState[i]);\n for (let variant of this._instanceVariant[i]) {\n this._instanceModel[i] = await this.createVariant(variant);\n }\n }\n //TODO: actually create\n //TODO: group by model\n this._isInstanced = true;\n } else {\n */\n const hasEntities = await this.createBlockEntities();\n const variantsToCreate = await this.mapStateToVariant(this.state);\n this._variants = variantsToCreate;\n for (let blockStateVariant of variantsToCreate) {\n // A block entity replaces only block models without geometry (a chest); a bell keeps its frame.\n if (hasEntities && !await this.hasGeometry(blockStateVariant)) continue;\n this._models.push(await this.createVariant(blockStateVariant));\n }\n await this.updateFluid(this._fluidSampler);\n this.setVisible(this.visible);\n /*\n }\n\n */\n\n }\n\n private async hasGeometry(variant: BlockStateVariant): Promise<boolean> {\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n return !!(await Models.getMerged(modelKey))?.elements?.length;\n }\n\n protected getSingleVariant(variants: BlockStateVariant | BlockStateVariant[]): BlockStateVariant {\n return BlockStateResolver.choose(variants, this.variantPosition);\n }\n\n // @deprecated\n protected async createAVariant(variants: BlockStateVariant | BlockStateVariant[], instanceInfo: Matrix4[]) {\n const variant = this.getSingleVariant(variants);\n await this.createVariant(variant);\n }\n\n protected async createVariant(variant: BlockStateVariant): Promise<ModelObject | InstanceReference<ModelObject>> {\n const rotation = BlockStateResolver.rotation(variant);\n\n // The model and its textures must come from the same asset root as the blockstate.\n const modelKey = AssetKey.parse(\"models\", variant.model!);\n modelKey.root = this.blockState.key?.root;\n const model = await Models.getMerged(modelKey);\n const options: Partial<ModelObjectOptions> = {\n ...this.options,\n tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints,\n () => BlockTints.getBiomeColor(this.blockState.key, this.options.biome, this.biomePosition)) : this.options.tints,\n uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0)\n ? [rotation.x, rotation.y, rotation.z] : undefined,\n cullMask: this.options.displayPosition ? 0 : ModelCulling.toLocalMask(this._cullMask, rotation)\n };\n const obj = await this.scene.addModel(model!, options);\n if (isInstanceReference(obj) || (<ModelObject>obj).isInstanced) {\n this._isInstanced = true;\n this._instanceCounter = 1;//TODO: BlockObject itself isn't technically instanced, but needs the id for the get/setMatrix calls to work properly\n }\n obj.setRotation(rotation);\n obj.setPosition(this.position);\n return obj;\n }\n\n /** Clears selected properties and rebuilds models without reapplying property defaults. */\n public async resetState() {\n this._previousState = this._state;\n this._state = {};\n await this.recreateModels();\n }\n\n // TODO: support state per instance\n /**\n * Updates properties and rebuilds the selected models.\n * Accepts `\"facing=north,open=true\"`, a property object, or a key and value.\n * Properties omitted from the call keep their current values.\n */\n public async setState(string: string);\n public async setState(state: BlockStateProperties);\n public async setState(key: string, value: string);\n public async setState(stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setState(stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setState(stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n this._previousState = this._state;\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setState(k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._state[k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._state[stringOrKeyOrState as string] = value;\n }\n }\n\n /*\n public async setStateAt(index: number, string: string);\n public async setStateAt(index: number, state: BlockStateProperties);\n public async setStateAt(index: number, key: string, value: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string);\n public async setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string) {\n this._setStateAt(index, stringOrKeyOrState, value);\n await this.recreateModels();\n }\n\n protected _setStateAt(index: number, stringOrKeyOrState: string | BlockStateProperties, value?: string): void {\n if (!this._instanceState[index]) this._instanceState[index] = {};\n if (typeof value === \"undefined\") { // a=b,c=d,... or state object\n if (typeof stringOrKeyOrState === \"string\") {\n if (stringOrKeyOrState === \"\") return;\n const split = stringOrKeyOrState.split(\",\");\n for (let s of split) {\n let [k, v] = s.split(\"=\");\n this._setStateAt(index, k, v);\n }\n } else if (typeof stringOrKeyOrState === \"object\") {\n for (let k in stringOrKeyOrState) {\n this._instanceState[index][k] = stringOrKeyOrState[k];\n }\n }\n } else {\n this._instanceState[index][stringOrKeyOrState as string] = value;\n }\n }\n\n _getStateAt(index: number): BlockStateProperties {\n return this._instanceState[index];\n }\n\n */\n\n setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3) {\n super.setPositionRotationScaleAt(index, position, rotation, scale);\n }\n\n getMatrixAt(index: number, matrix: Matrix4 = new Matrix4()): Matrix4 {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n const child = this._models[0];\n if (child && isModelObject(child)) {\n child.getMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.getMatrix(matrix);\n }\n /*\n const child = this.children[0];\n if (child && isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.getMatrixAt(index, matrix);\n }\n return matrix;\n */\n // return super.getMatrixAt(0, matrix);\n return matrix;\n }\n\n setMatrixAt(index: number, matrix: Matrix4) {\n if (!this.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n // const child = this._models[0];\n for(let child of this._models) {\n if (child && isModelObject(child)) {\n child.setMatrixAt(index, matrix);\n } else if (child && isInstanceReference(child)) {\n child.setMatrix(matrix);\n }\n }\n /*\n for (let child of this.children) {\n if (isModelObject(child)) {\n if (!child.isInstanced) throw new MineRenderError(\"Object is not instanced\");\n child.setMatrixAt(index, matrix);\n }\n }\n */\n }\n\n setPosition(position: Vector3) {\n this.position.copy(position);\n // Each part keeps its own variant rotation when the block moves.\n for (let model of this._models) {\n model.setPosition(position);\n }\n this.placeEntities();\n this.notifyDirty();\n }\n\n //TODO: should override rotation + scale methods\n\n //TODO\n\n}\n\n/** Block settings passed to `scene.addBlock(blockState, options)` or the BlockObject constructor. */\nexport interface BlockObjectOptions extends ModelObjectOptions {\n /** Loads vanilla property defaults before applying `initialState`. Defaults to `true`. */\n applyDefaultState: boolean;\n /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */\n initialState?: BlockStateProperties;\n /** Absolute block coordinates for repeatable variants, copied at construction. Omit for random previews. */\n variantPosition?: TripleArray;\n /** Saved biome ID used for automatic grass, foliage, and water colors. */\n biome?: string;\n /** World block coordinates used by biome grass modifiers. Copied at construction; defaults to the origin. */\n biomePosition?: TripleArray;\n}\n\nexport function isBlockObject(obj: any): obj is BlockObject {\n return (<BlockObject>obj).isBlockObject;\n}\n"],"mappings":"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","names":[]}
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1792,6 +1792,7 @@ declare class BlockObject extends SceneObject {
|
|
|
1792
1792
|
*/
|
|
1793
1793
|
private createBlockEntities;
|
|
1794
1794
|
private placeEntities;
|
|
1795
|
+
private placeEntity;
|
|
1795
1796
|
get isOccluding(): boolean;
|
|
1796
1797
|
private getModelMatrix;
|
|
1797
1798
|
private getModelCullMask;
|
|
@@ -2742,6 +2743,8 @@ interface UnihexFile {
|
|
|
2742
2743
|
|
|
2743
2744
|
/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */
|
|
2744
2745
|
declare class Caching {
|
|
2746
|
+
/** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */
|
|
2747
|
+
static readonly MISSING: false;
|
|
2745
2748
|
private static _generation;
|
|
2746
2749
|
/** Changes when shared assets are cleared, so derived caches can discard their old values. */
|
|
2747
2750
|
static get generation(): number;
|
|
@@ -2754,7 +2757,7 @@ declare class Caching {
|
|
|
2754
2757
|
static readonly materialCache: SimpleCache<CacheKey, Material>;
|
|
2755
2758
|
static readonly boxMeshCache: SimpleCache<CacheKey, Mesh>;
|
|
2756
2759
|
static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset>;
|
|
2757
|
-
static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta>;
|
|
2760
|
+
static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta | typeof Caching.MISSING>;
|
|
2758
2761
|
static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model>;
|
|
2759
2762
|
static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model>;
|
|
2760
2763
|
static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas>;
|
|
@@ -2762,7 +2765,7 @@ declare class Caching {
|
|
|
2762
2765
|
static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset>;
|
|
2763
2766
|
static readonly blockTintCache: AsyncLoadingCache<CacheKey, number>;
|
|
2764
2767
|
static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile>;
|
|
2765
|
-
static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey>;
|
|
2768
|
+
static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey | typeof Caching.MISSING>;
|
|
2766
2769
|
static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile>;
|
|
2767
2770
|
static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex>;
|
|
2768
2771
|
static readonly entityDatasetVersionCache: AsyncLoadingCache<CacheKey, string>;
|