@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
419 lines (418 loc) • 16.9 kB
JavaScript
"use strict";
// 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 Log_1 = __importDefault(require("../core/Log"));
const ste_events_1 = require("ste-events");
const StorageUtilities_1 = __importDefault(require("../storage/StorageUtilities"));
const IProjectItemData_1 = require("../app/IProjectItemData");
const AnimationResourceDefinition_1 = __importDefault(require("./AnimationResourceDefinition"));
const RenderControllerSetDefinition_1 = __importDefault(require("./RenderControllerSetDefinition"));
const Utilities_1 = __importDefault(require("../core/Utilities"));
const ModelGeometryDefinition_1 = __importDefault(require("./ModelGeometryDefinition"));
const Database_1 = __importDefault(require("./Database"));
const MinecraftDefinitions_1 = __importDefault(require("./MinecraftDefinitions"));
const TextureDefinition_1 = __importDefault(require("./TextureDefinition"));
class AttachableResourceDefinition {
_dataWrapper;
_data;
_file;
_isLoaded = false;
_loadedWithComments = false;
_onLoaded = new ste_events_1.EventDispatcher();
get isLoaded() {
return this._isLoaded;
}
get file() {
return this._file;
}
get data() {
return this._data;
}
get onLoaded() {
return this._onLoaded.asEvent();
}
set file(newFile) {
this._file = newFile;
}
get id() {
if (!this._data) {
return undefined;
}
return this._data.identifier;
}
get textures() {
if (!this._data) {
return undefined;
}
if (this._data.textures === undefined) {
this._data.textures = {};
}
return this._data.textures;
}
getCanonicalizedTexturesList() {
if (!this._data || !this._data.textures) {
return undefined;
}
const textureList = [];
for (const key in this._data.textures) {
const texturePath = TextureDefinition_1.default.canonicalizeTexturePath(this._data.textures[key]);
if (texturePath) {
textureList.push(texturePath);
}
}
return textureList;
}
get texturesIdList() {
if (!this._data || !this._data.textures) {
return undefined;
}
const textureIdList = [];
for (const key in this._data.textures) {
textureIdList.push(key);
}
return textureIdList;
}
get renderControllerIdList() {
if (!this._data || !this._data.render_controllers) {
return undefined;
}
return this._data.render_controllers;
}
get animationIdList() {
if (!this._data || !this._data.animations) {
return undefined;
}
const animationIdList = [];
for (const key in this._data.animations) {
animationIdList.push(key);
}
return animationIdList;
}
get animationList() {
if (!this._data || !this._data.animations) {
return undefined;
}
const animationList = [];
for (const key in this._data.animations) {
const val = this._data.animations[key];
if (val) {
animationList.push(val);
}
}
return animationList;
}
get geometry() {
if (!this._data) {
return undefined;
}
return this._data.geometry;
}
get geometryList() {
if (!this._data || !this._data.geometry) {
return undefined;
}
const geometryList = [];
for (const key in this._data.geometry) {
const geometryPath = this._data.geometry[key];
if (geometryPath) {
geometryList.push(geometryPath);
}
}
return geometryList;
}
getTextureItems(entityTypeResourceProjectItem) {
if (!this._data || !this._data.geometry || !entityTypeResourceProjectItem.childItems) {
return undefined;
}
const results = {};
for (const key in this._data.textures) {
let texturePath = this._data.textures[key];
if (texturePath) {
texturePath = StorageUtilities_1.default.canonicalizePath(texturePath);
for (const projectItemRel of entityTypeResourceProjectItem.childItems) {
if (projectItemRel.childItem.itemType === IProjectItemData_1.ProjectItemType.texture && projectItemRel.childItem.projectPath) {
let texturePathCand = StorageUtilities_1.default.canonicalizePath(projectItemRel.childItem.projectPath);
const lastPeriod = texturePathCand.lastIndexOf(".");
if (lastPeriod >= 0) {
texturePathCand = texturePathCand.substring(0, lastPeriod).toLowerCase();
}
if (texturePathCand.endsWith(texturePath)) {
results[key] = projectItemRel.childItem;
}
}
}
}
}
return results;
}
getFormatVersion() {
if (!this._dataWrapper) {
return undefined;
}
const fv = this._dataWrapper.format_version;
if (typeof fv === "number") {
return [fv];
}
if (typeof fv === "string") {
let fvarr = this._dataWrapper.format_version.split(".");
let fvarrInt = [];
for (let i = 0; i < fvarr.length; i++) {
try {
fvarrInt.push(parseInt(fvarr[i]));
}
catch (e) { }
}
return fvarrInt;
}
return undefined;
}
get formatVersion() {
if (!this._dataWrapper || !this._dataWrapper.format_version) {
return undefined;
}
return this._dataWrapper.format_version;
}
static async ensureOnFile(file, loadHandler) {
let attachable;
if (file.manager === undefined) {
attachable = new AttachableResourceDefinition();
attachable.file = file;
file.manager = attachable;
}
if (file.manager !== undefined && file.manager instanceof AttachableResourceDefinition) {
attachable = file.manager;
if (!attachable.isLoaded) {
if (loadHandler) {
attachable.onLoaded.subscribe(loadHandler);
}
await attachable.load();
}
}
return attachable;
}
persist() {
if (this._file === undefined) {
return false;
}
return this._file.setObjectContentIfSemanticallyDifferent(this._dataWrapper);
}
/**
* Loads the definition from the file.
* @param preserveComments If true, uses comment-preserving JSON parsing for edit/save cycles.
* If false (default), uses efficient standard JSON parsing.
* Can be called again with true to "upgrade" a read-only load to read/write.
*/
async load(preserveComments = false) {
// If already loaded with comments, we have the "best" version - nothing more to do
if (this._isLoaded && this._loadedWithComments) {
return;
}
// If already loaded without comments and caller doesn't need comments, we're done
if (this._isLoaded && !preserveComments) {
return;
}
if (this._file === undefined) {
Log_1.default.unexpectedUndefined("ATTRPF");
return;
}
if (!this._file.isContentLoaded) {
await this._file.loadContent();
}
if (!this._file.content || this._file.content instanceof Uint8Array) {
this._isLoaded = true;
this._loadedWithComments = preserveComments;
this._onLoaded.dispatch(this, this);
return;
}
let data = {};
// Use comment-preserving parser only when needed for editing
let result = preserveComments
? StorageUtilities_1.default.getJsonObjectWithComments(this._file)
: StorageUtilities_1.default.getJsonObject(this._file);
if (result) {
data = result;
}
this._dataWrapper = data;
if (this._dataWrapper && this._dataWrapper["minecraft:attachable"]) {
this._data = this._dataWrapper["minecraft:attachable"].description;
}
this._isLoaded = true;
this._loadedWithComments = preserveComments;
this._onLoaded.dispatch(this, this);
}
ensureData() {
if (this._data) {
return this._data;
}
const newDef = {
identifier: "",
materials: {},
textures: {},
geometry: {},
particle_effects: {},
animations: {},
render_controllers: [],
scripts: {},
};
if (!this._dataWrapper) {
this._dataWrapper = { format_version: "1.10.0", "minecraft:attachable": { description: newDef } };
this._data = this._dataWrapper["minecraft:attachable"].description;
return this._data;
}
if (this._dataWrapper["minecraft:attachable"] === undefined ||
this._dataWrapper["minecraft:attachable"].description === undefined) {
this._dataWrapper["minecraft:attachable"] = { description: newDef };
}
this._data = this._dataWrapper["minecraft:attachable"].description;
return this._data;
}
async deleteLinkToChild(rel) {
let packRootFolder = this.getPackRootFolder();
if (this._data === undefined) {
await this.load();
}
const etrChildItems = rel.parentItem.childItems;
if (rel.childItem.itemType === IProjectItemData_1.ProjectItemType.texture && this._data && this._data.textures) {
if (!rel.childItem.isContentLoaded) {
await rel.childItem.loadContent();
}
if (rel.childItem.primaryFile && packRootFolder) {
let relativePath = StorageUtilities_1.default.getBaseRelativePath(rel.childItem.primaryFile, packRootFolder);
if (relativePath) {
for (const key in this._data.textures) {
if (Utilities_1.default.isUsableAsObjectKey(key)) {
const texturePath = this._data.textures[key];
if (texturePath === relativePath) {
this._data.textures[key] = undefined;
if (etrChildItems) {
for (const otherChild of etrChildItems) {
if (otherChild.childItem.itemType === IProjectItemData_1.ProjectItemType.renderControllerJson) {
const renderController = (await MinecraftDefinitions_1.default.get(otherChild.childItem));
renderController.removeTexture(key);
}
}
}
}
}
}
}
}
}
this.persist();
}
getPackRootFolder() {
let packRootFolder = undefined;
if (this.file && this.file.parentFolder) {
let parentFolder = this.file.parentFolder;
packRootFolder = StorageUtilities_1.default.getParentOfParentFolderNamed("attachables", parentFolder);
}
return packRootFolder;
}
async addChildItems(project, item) {
let packRootFolder = this.getPackRootFolder();
let textureList = this.getCanonicalizedTexturesList();
let geometryList = this.geometryList;
let renderControllerIdList = this.renderControllerIdList;
let animationIdList = this.animationIdList;
// Process animations
if (animationIdList) {
const animItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.animationResourceJson);
for (const candItem of animItems) {
if (!candItem.isContentLoaded) {
await candItem.loadContent();
}
if (candItem.primaryFile) {
const animationDef = await AnimationResourceDefinition_1.default.ensureOnFile(candItem.primaryFile);
const animIds = animationDef?.idList;
if (animIds) {
for (const animId of animationIdList) {
if (animIds.has(animId)) {
item.addChildItem(candItem);
continue;
}
}
}
}
}
}
// Process render controllers
if (renderControllerIdList) {
const rcItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.renderControllerJson);
for (const candItem of rcItems) {
if (!candItem.isContentLoaded) {
await candItem.loadContent();
}
if (candItem.primaryFile) {
const renderControllerDef = await RenderControllerSetDefinition_1.default.ensureOnFile(candItem.primaryFile);
const renderIds = renderControllerDef?.idList;
if (renderIds) {
for (const rcId of renderControllerIdList) {
if (renderIds.has(rcId)) {
item.addChildItem(candItem);
continue;
}
}
}
}
}
}
// Process textures
if (packRootFolder && textureList) {
const texItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.texture);
for (const candItem of texItems) {
if (!candItem.isContentLoaded) {
await candItem.loadContent();
}
if (candItem.primaryFile) {
let relativePath = TextureDefinition_1.default.canonicalizeTexturePath(StorageUtilities_1.default.getBaseRelativePath(candItem.primaryFile, packRootFolder));
if (relativePath) {
if (textureList && textureList.includes(relativePath)) {
item.addChildItem(candItem);
textureList = Utilities_1.default.removeItemInArray(relativePath, textureList);
}
}
}
}
}
// Process models
if (geometryList) {
const modelItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.modelGeometryJson);
for (const candItem of modelItems) {
if (!candItem.isContentLoaded) {
await candItem.loadContent();
}
if (candItem.primaryFile) {
const model = await ModelGeometryDefinition_1.default.ensureOnFile(candItem.primaryFile);
if (model) {
let doAddModel = false;
for (const modelId of model.identifiers) {
if (geometryList && geometryList.includes(modelId)) {
doAddModel = true;
geometryList = Utilities_1.default.removeItemInArray(modelId, geometryList);
}
}
if (doAddModel) {
item.addChildItem(candItem);
}
}
}
}
}
if (textureList) {
for (const texturePath of textureList) {
const isVanilla = await Database_1.default.isVanillaToken(texturePath);
item.addUnfulfilledRelationship(texturePath, IProjectItemData_1.ProjectItemType.texture, isVanilla);
}
}
if (geometryList) {
for (const geoId of geometryList) {
item.addUnfulfilledRelationship(geoId, IProjectItemData_1.ProjectItemType.modelGeometryJson, await Database_1.default.isVanillaToken(geoId));
}
}
}
}
exports.default = AttachableResourceDefinition;