@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
105 lines (104 loc) • 4.23 kB
JavaScript
;
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const MolangEvaluator_1 = __importDefault(require("./MolangEvaluator"));
class RenderControllerResolver {
_evaluator;
constructor() {
this._evaluator = new MolangEvaluator_1.default();
}
/**
* Resolve a render controller to concrete geometry/texture/material values.
*
* @param rc The render controller data from the .render_controllers.json file
* @param textureMap Entity's texture key map: {"default": "textures/entity/sheep/sheep", "baby": "..."}
* @param geometryMap Entity's geometry key map: {"default": "geometry.sheep.v1.8", "sheared": "..."}
* @param context Molang evaluation context (entity state)
* @returns Resolved geometry ID, texture layers, and optional tint
*/
resolve(rc, textureMap, geometryMap, context) {
const arrays = this._buildArrayMap(rc.arrays);
// Resolve geometry
let geometryId;
if (rc.geometry) {
const geoRef = this._evaluator.evaluateString(rc.geometry, context, arrays);
geometryId = this._resolveReference(geoRef, "Geometry", geometryMap);
}
// Resolve texture layers
const textureLayers = [];
if (rc.textures) {
for (const texExpr of rc.textures) {
const texRef = this._evaluator.evaluateString(texExpr, context, arrays);
const texPath = this._resolveReference(texRef, "Texture", textureMap);
if (texPath) {
textureLayers.push({ texturePath: texPath });
}
}
}
// If no layers resolved, try fallback to "default" texture
if (textureLayers.length === 0 && textureMap["default"]) {
textureLayers.push({ texturePath: textureMap["default"] });
}
return {
geometryId,
textureLayers,
};
}
/**
* Resolve a reference like "Texture.default" or "Geometry.baby" to the actual
* path/ID using the entity's key maps.
*/
_resolveReference(ref, prefix, keyMap) {
if (!ref)
return undefined;
// Check if it's a prefixed reference: "Texture.default" → key "default"
const prefixDot = prefix + ".";
if (ref.startsWith(prefixDot)) {
const key = ref.substring(prefixDot.length);
return keyMap[key] ?? keyMap["default"];
}
// Check case-insensitive prefix match
const lowerRef = ref.toLowerCase();
const lowerPrefix = prefix.toLowerCase() + ".";
if (lowerRef.startsWith(lowerPrefix)) {
const key = ref.substring(lowerPrefix.length);
return keyMap[key] ?? keyMap["default"];
}
// It might already be a direct path (e.g., "textures/entity/sheep/sheep")
if (ref.includes("/")) {
return ref;
}
// Try as a key directly
if (keyMap[ref]) {
return keyMap[ref];
}
return keyMap["default"];
}
/**
* Build a flat Map<string, string[]> from the render controller's nested array definitions.
* Converts: { textures: { "Array.skins": ["Texture.a", "Texture.b"] }, geometries: {...} }
* To: Map { "Array.skins" → ["Texture.a", "Texture.b"], "Array.geos" → [...] }
*/
_buildArrayMap(arrays) {
if (!arrays)
return undefined;
const map = new Map();
for (const category of ["textures", "geometries", "materials"]) {
const categoryArrays = arrays[category];
if (categoryArrays) {
for (const arrayName in categoryArrays) {
const entries = categoryArrays[arrayName];
if (entries) {
map.set(arrayName, entries);
}
}
}
}
return map.size > 0 ? map : undefined;
}
}
exports.default = RenderControllerResolver;