UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

801 lines (799 loc) 28.8 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); exports.BlockStateType = void 0; const BlockRenderType_1 = require("./BlockRenderType"); const MinecraftUtilities_1 = require("./MinecraftUtilities"); const Database_1 = require("./Database"); const Utilities_1 = require("../core/Utilities"); const ste_events_1 = require("ste-events"); const Log_1 = require("../core/Log"); const ManagedComponent_1 = require("./ManagedComponent"); const StorageUtilities_1 = require("../storage/StorageUtilities"); const ManagedPermutation_1 = require("./ManagedPermutation"); const IProjectItemData_1 = require("../app/IProjectItemData"); const ModelGeometryDefinition_1 = require("./ModelGeometryDefinition"); const BlocksCatalogDefinition_1 = require("./BlocksCatalogDefinition"); const TerrainTextureCatalogDefinition_1 = require("./TerrainTextureCatalogDefinition"); const TypeScriptDefinition_1 = require("./TypeScriptDefinition"); var BlockStateType; (function (BlockStateType) { BlockStateType[BlockStateType["string"] = 0] = "string"; BlockStateType[BlockStateType["boolean"] = 1] = "boolean"; BlockStateType[BlockStateType["number"] = 2] = "number"; })(BlockStateType = exports.BlockStateType || (exports.BlockStateType = {})); class BlockTypeDefinition { get data() { return this._data; } get numericId() { return this._typeData.id; } get baseTypeId() { return this._baseTypeId; } get mapColor() { return this._typeData.mapColor; } get isCustom() { return this._isCustom; } get baseType() { if (this._baseType !== undefined) { return this._baseType; } return Database_1.default.defaultBlockBaseType; } async getFormatVersionIsCurrent() { const fv = this.getFormatVersion(); if (fv === undefined || fv.length !== 3) { return false; } return await Database_1.default.isRecentVersionFromVersionArray(fv); } getMissingPermutations() { this.ensurePermutations(); const unspecifiedConditions = []; for (const state of this.getExpandedStateList()) { let isUsedInConditionalExpression = false; for (const perm of this.getPermutations()) { if (perm.condition.indexOf(state) >= 0 && (perm.condition.indexOf("!=") >= 0 || perm.condition.indexOf(">=") >= 0 || perm.condition.indexOf("<=") >= 0)) { isUsedInConditionalExpression = true; break; } } if (!isUsedInConditionalExpression) { unspecifiedConditions.push(state); } } const stateIds = []; const vals = []; for (const state of unspecifiedConditions) { const stateValues = this.getStateValues(state); if (stateValues) { vals.push(stateValues); stateIds.push(state); } } let stateList = []; let idx = 0; for (const valArrs of vals) { let newStateList = []; for (let i = 0; i < valArrs.length; i++) { let strVal = valArrs[i]; if (typeof strVal === "string") { strVal = "'" + strVal + "'"; } if (stateList.length === 0) { let condition = "q.block_state('" + stateIds[idx] + "') == " + strVal; if (!this.getPermutationByCondition(condition)) { newStateList.push(condition); } } else { for (let j = 0; j < stateList.length; j++) { let condition = stateList[j] && " && q.block_state('" + stateIds[idx] + "') == " + strVal; if (!this.getPermutationByCondition(condition)) { newStateList.push(stateList[j] && " && q.block_state('" + stateIds[idx] + "') == " + strVal); } } } } idx++; stateList = newStateList; } return stateList; } addNextPermutation() { this.ensurePermutations(); let missingConditions = this.getMissingPermutations(); const cond = missingConditions.length > 0 ? missingConditions[0] : "q.block_state() == ''"; this.addPermutation(cond); } addPermutation(condition) { this.ensurePermutations(); if (!this._data || !this._data.permutations) { return; } this._data.permutations.push({ condition: condition, components: {}, }); } ensurePermutations() { if (!this._data) { this._data = { description: { identifier: this._typeId, }, components: {}, permutations: [], events: {}, }; } if (!this._data.description) { this._data.description = { identifier: this._typeId, }; } if (!this._data.permutations) { this._data.permutations = []; } } hasCustomPermutationConditions() { if (!this._data || !this._data.permutations) { return false; } for (const perm of this._data.permutations) { if (perm.condition && (perm.condition.indexOf(">=") >= 0 || perm.condition.indexOf("<=") >= 0 || perm.condition.indexOf("!=") >= 0)) { return true; } } return false; } ensureDescription() { if (!this._data) { this._data = { description: { identifier: this._typeId, }, components: {}, events: {}, }; } if (!this._data.description) { this._data.description = { identifier: this._typeId, }; } } getManagedPermutations() { const permData = this.getPermutations(); if (!permData) { return undefined; } const managedPerms = []; for (const permDataItem of permData) { managedPerms.push(new ManagedPermutation_1.default(permDataItem)); } return managedPerms; } getPermutations() { if (!this._data || !this.data?.permutations) { return []; } return this.data.permutations; } getPlacementDirectionTrait() { if (!this._data || !this._data.description || !this._data.description.traits) { return undefined; } const traits = this._data?.description.traits; return traits["minecraft:placement_direction"]; } getPlacementPositionTrait() { if (!this._data || !this._data.description || !this._data.description.traits) { return undefined; } const traits = this._data?.description.traits; return traits["minecraft:placement_position"]; } ensurePlacementDirectionTrait() { this.ensureBlockTraits(); const traits = this._data?.description.traits; if (traits) { if (!traits["minecraft:placement_direction"]) { traits["minecraft:placement_direction"] = { enabled_states: ["minecraft:cardinal_direction", "minecraft:facing_direction"], }; } } } removePlacementDirectionTrait() { const traits = this._data?.description.traits; if (traits) { if (traits["minecraft:placement_direction"]) { traits["minecraft:placement_direction"] = undefined; } } } ensurePlacementPositionTrait() { this.ensureBlockTraits(); const traits = this._data?.description.traits; if (traits) { if (!traits["minecraft:placement_position"]) { traits["minecraft:placement_position"] = { enabled_states: ["minecraft:block_face", "minecraft:vertical_half"], }; } } } removePlacementPositionTrait() { const traits = this._data?.description.traits; if (traits) { if (traits["minecraft:placement_position"]) { traits["minecraft:placement_position"] = undefined; } } } ensureBlockTraits() { this.ensureDescription(); if (this._data?.description && !this._data?.description.traits) { this._data.description.traits = {}; } } removeState(stateName) { if (this._data?.description?.states) { this._data.description.states[stateName] = undefined; } if (this._data?.description?.properties) { this._data.description.properties[stateName] = undefined; } } getFormatVersion() { if (!this._wrapper) { return undefined; } return MinecraftUtilities_1.default.getVersionArrayFrom(this._wrapper.format_version); } getStateValues(stateId) { if (stateId === "minecraft:block_face" || stateId === "minecraft:facing_direction") { return ["north", "south", "east", "west", "up", "down"]; } else if (stateId === "minecraft:vertical_half") { return ["bottom", "top"]; } else if (stateId === "minecraft:cardinal_direction") { return ["north", "south", "east", "west"]; } const states = this.getStates(); if (!states || !states[stateId]) { return undefined; } return states[stateId]; } getStates() { if (!this._wrapper || !this._data || !this._data?.description) { return undefined; } if (!this._data.description.states && this._data.description.properties) { return this._data.description.properties; } return this._data.description.states; } addState(stateName, stateType) { if (!this._data || !this._data.description) { return; } let dataArr = []; if (stateType === BlockStateType.boolean) { dataArr = [false, true]; } else if (stateType === BlockStateType.number) { dataArr = [0, 1, 2]; } else if (stateType === BlockStateType.string) { dataArr = ["value1", "value2"]; } if (!this._data.description.states) { this._data.description.states = {}; } this._data.description.states[stateName] = dataArr; } getExpandedStateList() { const stateList = this.getStateList(); let placementDir = this.getPlacementDirectionTrait(); if (placementDir) { if (placementDir.enabled_states) { stateList.push(...placementDir.enabled_states); } } let placementPos = this.getPlacementPositionTrait(); if (placementPos) { if (placementPos.enabled_states) { stateList.push(...placementPos.enabled_states); } } return stateList; } getStateList() { const states = this.getStates(); if (!states) { return []; } const stateList = []; for (const state in states) { if (states[state] !== undefined) { stateList.push(state); } } return stateList; } set baseType(baseType) { this._baseType = baseType; this._baseTypeId = baseType.name; } get material() { return this._material; } get icon() { let val = this._typeData.icon; if (val === undefined && this.baseType !== undefined) { val = this.baseType.icon; } return val; } get typeId() { return this._typeId; } get shortTypeName() { let name = this._typeId; const colonIndex = name.indexOf(":"); if (colonIndex >= 0) { name = name.substring(colonIndex + 1, name.length); } return name; } get title() { const id = this.shortTypeName; return Utilities_1.default.humanifyMinecraftName(id); } constructor(name) { this._typeId = ""; this._baseTypeId = ""; this._material = ""; this._isCustom = false; this._wrapper = null; this._isLoaded = false; this._managed = {}; this._onLoaded = new ste_events_1.EventDispatcher(); this._onComponentAdded = new ste_events_1.EventDispatcher(); this._onComponentRemoved = new ste_events_1.EventDispatcher(); this._onComponentChanged = new ste_events_1.EventDispatcher(); this.renderType = BlockRenderType_1.BlockRenderType.Custom; this._typeId = name; this._typeData = { name: name, }; if (name.indexOf(":") >= 0 && !name.startsWith("minecraft:")) { this._isCustom = true; } } get id() { if (this._data && this._data.description) { return this._data.description.identifier; } return this._id; } set id(newId) { this._id = newId; if (this._data && this._data.description && newId) { this._data.description.identifier = newId; } } get onComponentAdded() { return this._onComponentAdded.asEvent(); } get onComponentRemoved() { return this._onComponentRemoved.asEvent(); } get onComponentChanged() { return this._onComponentChanged.asEvent(); } get isLoaded() { return this._isLoaded; } get behaviorPackFile() { return this._file; } get onLoaded() { return this._onLoaded.asEvent(); } set behaviorPackFile(newFile) { this._file = newFile; } get shortId() { if (this._id !== undefined) { if (this._id.startsWith("minecraft:")) { return this._id.substring(10, this._id.length); } return this._id; } return undefined; } getPermutationByCondition(permutationCondition) { if (!this._data || !this.data?.permutations) { return undefined; } for (const perm of this.data.permutations) { if (permutationCondition === perm.condition) { return perm; } } return undefined; } ensureComponent(id, defaultData) { const comp = this.getComponent(id); if (comp) { return comp; } return this.addComponent(id, defaultData); } getComponent(id) { if (this._data === undefined) { return undefined; } if (!this._managed[id]) { const comp = this._data.components[id]; if (comp) { this._managed[id] = new ManagedComponent_1.ManagedComponent(this._data.components, id, comp); } } return this._managed[id]; } getComponentsInBaseAndPermutations(id) { if (this._data === undefined) { return []; } let results = []; let comp = this.getComponent(id); if (comp) { results.push(comp); } const perms = this.getManagedPermutations(); if (perms) { for (const perm of perms) { if (perm) { comp = perm.getComponent(id); if (comp) { results.push(comp); } } } } return results; } notifyComponentUpdated(id) { const component = this.getComponent(id); if (component === undefined) { Log_1.default.unexpectedUndefined("BTNCU"); } else { this._onComponentChanged.dispatch(this, component); } } getAllComponents() { return this.getComponents(); } getComponents() { const componentSet = []; if (this._data !== undefined) { for (const componentName in this._data.components) { const component = this.getComponent(componentName); if (component !== undefined) { componentSet.push(component); } } } return componentSet; } addComponent(id, componentOrData) { this._ensureBehaviorPackDataInitialized(); const bpData = this._data; const mc = componentOrData instanceof ManagedComponent_1.ManagedComponent ? componentOrData : new ManagedComponent_1.ManagedComponent(bpData.components, id, componentOrData); bpData.components[id] = mc.getData(); this._managed[id] = mc; this._onComponentAdded.dispatch(this, mc); return mc; } removeComponent(id) { if (this._data === undefined) { return; } const newBehaviorPacks = {}; const newComponents = {}; for (const name in this._data.components) { if (name !== id) { const component = this._data.components[name]; newBehaviorPacks[name] = component; } } for (const name in this._managed) { if (name !== id) { newComponents[name] = this._managed[name]; } } this._data.components = newBehaviorPacks; this._managed = newComponents; } async getTextureItems(blockTypeProjectItem) { if (!this._data || !blockTypeProjectItem.childItems) { return undefined; } const textureList = this.getTextureList(); const results = {}; for (const childItem of blockTypeProjectItem.childItems) { let candItem = childItem.childItem; if (candItem.itemType === IProjectItemData_1.ProjectItemType.terrainTextureCatalogResourceJson) { await candItem.ensureStorage(); if (candItem.file && candItem.childItems) { const blockTextureCatalog = await TerrainTextureCatalogDefinition_1.default.ensureOnFile(candItem.file); if (blockTextureCatalog && textureList) { for (const textureId of textureList) { const texPaths = blockTextureCatalog.getAllTexturePaths(textureId); if (texPaths) { for (const texPath of texPaths) { for (const catalogChildItem of candItem.childItems) { let path = catalogChildItem.childItem.projectPath; if (path) { const lastPeriod = path.lastIndexOf("."); if (lastPeriod >= 0) { path = path.substring(0, lastPeriod); } if (path.endsWith(texPath)) { results[texPath] = catalogChildItem.childItem; } } } } } } } } } } return results; } getGeometryList() { if (!this._data) { return undefined; } const comps = this.getComponentsInBaseAndPermutations("minecraft:geometry"); if (!comps) { return undefined; } const geometryList = []; for (const comp of comps) { const compData = comp.getData(); if (typeof compData === "string") { geometryList.push(compData); } else { const id = comp.getProperty("identifier"); if (id) { geometryList.push(id); } } } return geometryList; } getTextureList() { if (!this._data) { return undefined; } const comps = this.getComponentsInBaseAndPermutations("minecraft:material_instances"); if (!comps) { return undefined; } const textureList = []; for (const comp of comps) { const compData = comp.getData(); if (typeof compData === "object") { for (const materialName in compData) { const material = compData[materialName]; if (material && material.texture) { textureList.push(material.texture); } } } } return textureList; } _ensureBehaviorPackDataInitialized() { if (this._data === undefined) { this._data = { description: { identifier: "unknown", }, components: {}, events: {}, }; } } getPackRootFolder() { let packRootFolder = undefined; if (this._file && this._file.parentFolder) { let parentFolder = this._file.parentFolder; packRootFolder = StorageUtilities_1.default.getParentOfParentFolderNamed("blocks", parentFolder); } return packRootFolder; } getCustomComponentIds() { let customComponentIds = []; const customComponents = this.getComponentsInBaseAndPermutations("minecraft:custom_components"); for (const comp of customComponents) { let compData = comp.getData(); if (compData && Array.isArray(compData)) { for (const str of compData) { if (typeof str === "string") { customComponentIds.push(str); } } } } return customComponentIds; } getLootTablePaths() { let lootTablePaths = []; const lootComps = this.getComponentsInBaseAndPermutations("minecraft:loot"); for (const comp of lootComps) { let compData = comp.getData(); if (typeof compData === "string") { lootTablePaths.push(compData); } else { let lootTablePath = comp.getProperty("table"); if (lootTablePath) { lootTablePaths.push(lootTablePath); } } } return lootTablePaths; } async addChildItems(project, item) { let lootTablePaths = this.getLootTablePaths(); let customComponentIds = this.getCustomComponentIds(); let textureList = this.getTextureList(); let geometryList = this.getGeometryList(); const itemsCopy = project.getItemsCopy(); for (const candItem of itemsCopy) { if (candItem.itemType === IProjectItemData_1.ProjectItemType.ts) { await candItem.ensureStorage(); if (candItem.file) { await candItem.load(); const tsd = await TypeScriptDefinition_1.default.ensureOnFile(candItem.file); if (tsd && tsd.data && customComponentIds) { let doAddTs = false; for (const customCompId of customComponentIds) { if (tsd.data.indexOf(customCompId) >= 0) { doAddTs = true; break; } } if (doAddTs) { item.addChildItem(candItem); } } } } else if (candItem.itemType === IProjectItemData_1.ProjectItemType.terrainTextureCatalogResourceJson) { await candItem.ensureStorage(); if (candItem.file) { const blockTextureCatalog = await TerrainTextureCatalogDefinition_1.default.ensureOnFile(candItem.file); if (blockTextureCatalog && textureList) { let doAddTextureCatalog = false; for (const textureId of textureList) { const blockResource = blockTextureCatalog.getTexture(textureId); if (blockResource) { doAddTextureCatalog = true; break; } } if (doAddTextureCatalog) { item.addChildItem(candItem); } } } } else if (candItem.itemType === IProjectItemData_1.ProjectItemType.blocksCatalogResourceJson) { await candItem.ensureStorage(); if (candItem.file) { const blockCatalog = await BlocksCatalogDefinition_1.default.ensureOnFile(candItem.file); if (blockCatalog && this.id) { const blockResource = blockCatalog.getBlockDefinition(this.id); if (blockResource) { item.addChildItem(candItem); } } } } else if (candItem.itemType === IProjectItemData_1.ProjectItemType.modelGeometryJson && geometryList) { await candItem.ensureStorage(); if (candItem.file) { const model = await ModelGeometryDefinition_1.default.ensureOnFile(candItem.file); 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); } } } } else if (candItem.itemType === IProjectItemData_1.ProjectItemType.lootTableBehavior) { for (const lootTablePath of lootTablePaths) { if (candItem.projectPath?.endsWith(lootTablePath)) { item.addChildItem(candItem); } } } } } static async ensureOnFile(file, loadHandler) { let bt; if (file.manager === undefined) { bt = new BlockTypeDefinition("custom:" + file.name); bt.behaviorPackFile = file; file.manager = bt; } if (file.manager !== undefined && file.manager instanceof BlockTypeDefinition) { bt = file.manager; if (!bt.isLoaded && loadHandler) { bt.onLoaded.subscribe(loadHandler); } await bt.load(); } return bt; } persist() { if (this._file === undefined) { return; } const bpString = JSON.stringify(this._wrapper, null, 2); this._file.setContent(bpString); } async load() { if (this._file === undefined || this._isLoaded) { return; } await this._file.loadContent(); if (!this._file.content || this._file.content instanceof Uint8Array) { return; } let data = {}; let result = StorageUtilities_1.default.getJsonObject(this._file); if (result) { data = result; } this._wrapper = data; const block = data["minecraft:block"]; if (block && block.description) { this.id = block.description.identifier; } this._data = block; this._onLoaded.dispatch(this, this); this._isLoaded = true; } } exports.default = BlockTypeDefinition; //# sourceMappingURL=../maps/minecraft/BlockTypeDefinition.js.map