UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

966 lines (965 loc) 49.1 kB
"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 Project_1 = require("./Project"); const ProjectContent_1 = __importDefault(require("./ProjectContent")); const IProjectData_1 = require("./IProjectData"); const IProjectItemData_1 = require("./IProjectItemData"); const StorageUtilities_1 = __importDefault(require("./../storage/StorageUtilities")); const ZipStorage_1 = __importDefault(require("../storage/ZipStorage")); const ProjectItemUtilities_1 = __importDefault(require("./ProjectItemUtilities")); const ProjectAutogeneration_1 = __importDefault(require("./ProjectAutogeneration")); const Database_1 = __importDefault(require("../minecraft/Database")); const Log_1 = __importDefault(require("../core/Log")); const SoundDefinitionCatalogDefinition_1 = __importDefault(require("../minecraft/SoundDefinitionCatalogDefinition")); const SoundCatalogDefinition_1 = __importDefault(require("../minecraft/SoundCatalogDefinition")); const MinecraftUtilities_1 = __importDefault(require("../minecraft/MinecraftUtilities")); const IGalleryItem_1 = require("./IGalleryItem"); const ProjectUtilities_1 = require("./ProjectUtilities"); const ImageEditsDefinition_1 = __importDefault(require("../design/ImageEditsDefinition")); const ProjectCreateManager_1 = __importDefault(require("./ProjectCreateManager")); /// Does create operations for project items. class ProjectItemCreateManager { static async _getDefaultBehaviorPackPath(project) { const bpFolder = await project.ensureDefaultBehaviorPackFolder(); if (project.projectFolder === null) { return undefined; } const defaultPath = bpFolder.getFolderRelativePath(project.projectFolder); return defaultPath; } static async _getDefaultBehaviorPackFolderPath(project, name) { const bpFolder = await project.ensureDefaultBehaviorPackFolder(); if (project.projectFolder === null) { return undefined; } const subfolder = bpFolder.ensureFolder(name); await subfolder.ensureExists(); const defaultPath = subfolder.getFolderRelativePath(project.projectFolder); return defaultPath; } static async _getDefaultDesignPackFolderPath(project, name) { const dpFolder = await project.ensureDefaultDesignPackFolder(); if (project.projectFolder === null) { return undefined; } const subfolder = dpFolder.ensureFolder(name); await subfolder.ensureExists(); const defaultPath = subfolder.getFolderRelativePath(project.projectFolder); return defaultPath; } static async _getDefaultResourcePackPath(project) { const rpFolder = await project.ensureDefaultResourcePackFolder(); if (project.projectFolder === null) { return undefined; } const defaultPath = rpFolder.getFolderRelativePath(project.projectFolder); return defaultPath; } static async _getDefaultResourcePackFolderPath(project, name) { const rpFolder = await project.ensureDefaultResourcePackFolder(); if (project.projectFolder === null) { return undefined; } const subfolder = rpFolder.ensureFolder(name); await subfolder.ensureExists(); const defaultPath = subfolder.getFolderRelativePath(project.projectFolder); return defaultPath; } static async _getDefaultScriptsFolderPath(project) { const scriptsFolder = await project.ensureMainScriptsFolder(); if (project.projectFolder === null) { return undefined; } const defaultPath = scriptsFolder.getFolderRelativePath(project.projectFolder); return defaultPath; } static async createNewItem(project, itemSeed) { if (itemSeed.name === "" || itemSeed.name === undefined) { itemSeed.name = ProjectItemUtilities_1.default.getNewItemName(itemSeed.itemType); } let creationData = itemSeed.creationData; if (creationData) { creationData = ProjectCreateManager_1.default.getReplacedCreationDataInObject(project, creationData, itemSeed.name); } if (itemSeed.itemType) { switch (itemSeed.itemType) { case IProjectItemData_1.ProjectItemType.js: case IProjectItemData_1.ProjectItemType.ts: return ProjectItemCreateManager.createNewScript(project, itemSeed.itemType, itemSeed.name, itemSeed.folder); case IProjectItemData_1.ProjectItemType.dataForm: return ProjectItemCreateManager.createNewForm(project, itemSeed.name, itemSeed.folder); case IProjectItemData_1.ProjectItemType.audio: return ProjectItemCreateManager.createNewAudio(project, itemSeed.name, itemSeed.folder); case IProjectItemData_1.ProjectItemType.texture: return ProjectItemCreateManager.createNewTexture(project, itemSeed.name, itemSeed.folder); case IProjectItemData_1.ProjectItemType.designTexture: return ProjectItemCreateManager.createNewDesignTexture(project, itemSeed.name, itemSeed.folder, creationData); } } if (ProjectItemUtilities_1.default.isBehaviorRelated(itemSeed.itemType)) { return await ProjectItemCreateManager.createBehaviorPackJsonItem(project, itemSeed); } else if (ProjectItemUtilities_1.default.isResourceRelated(itemSeed.itemType)) { return await ProjectItemCreateManager.createResourcePackJsonItem(project, itemSeed); } else if (ProjectItemUtilities_1.default.isDesignRelated(itemSeed.itemType)) { return await ProjectItemCreateManager.createDesignPackJsonItem(project, itemSeed); } Log_1.default.error("No creation handler for item type: " + itemSeed.itemType); return undefined; } static async createNewScript(project, itemType, name, folder) { let defaultPath = undefined; if (folder && project.projectFolder) { defaultPath = folder.getFolderRelativePath(project.projectFolder); } else { defaultPath = await ProjectItemCreateManager._getDefaultScriptsFolderPath(project); } if (defaultPath === undefined) { return; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, defaultPath, name, itemType === IProjectItemData_1.ProjectItemType.js ? "js" : "ts"); if (candidateFilePath === undefined) { return; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), itemType === IProjectItemData_1.ProjectItemType.js ? IProjectItemData_1.ProjectItemType.js : IProjectItemData_1.ProjectItemType.ts, Project_1.FolderContext.behaviorPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { const baseName = StorageUtilities_1.default.getBaseFromName(file.name); if (project.preferredScriptLanguage === IProjectData_1.ProjectScriptLanguage.typeScript) { file.setContent(ProjectContent_1.default.getEmptyTypeScript(project.name, baseName)); } else { file.setContent(ProjectContent_1.default.getEmptyJavaScript(project.name, baseName)); } } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return pi; } static async _generateFolderNameForNewItem(project, basePath, baseName) { if (project.projectFolder === null) { return undefined; } let index = 0; let candidateFolderPath = ""; let finalPathPrefix = ""; const projectFolder = project.projectFolder; let candidateFolder = null; let hash = basePath.indexOf("#"); let targetFolder = projectFolder; while (hash > 0) { // dig into container files if needed. let containerFilePath = basePath.substring(0, hash); basePath = basePath.substring(hash + 1); hash = basePath.indexOf("#"); if (containerFilePath.startsWith(targetFolder.fullPath)) { containerFilePath = containerFilePath.substring(targetFolder.fullPath.length); } finalPathPrefix += containerFilePath + "#"; const containerFile = await targetFolder.getFileFromRelativePath(containerFilePath); if (!containerFile) { return undefined; } const extension = containerFile.type; if (extension !== "zip" && extension !== "mcworld" && extension !== "mctemplate") { return undefined; } if (!containerFile.fileContainerStorage) { const zipStorage = new ZipStorage_1.default(); if (!containerFile.isContentLoaded) { await containerFile.loadContent(); } if (!containerFile.content || !(containerFile.content instanceof Uint8Array)) { return undefined; } await zipStorage.loadFromUint8Array(containerFile.content, containerFile.name); zipStorage.containerFile = containerFile; containerFile.fileContainerStorage = zipStorage; containerFile.fileContainerStorage.storagePath = containerFilePath + "#"; } targetFolder = containerFile.fileContainerStorage.rootFolder; } await targetFolder.ensureFolderFromRelativePath(basePath); await targetFolder.ensureExists(); // find a folder name not in use do { index++; candidateFolderPath = basePath + baseName + index; candidateFolder = await targetFolder.getFolderFromRelativePath(candidateFolderPath); } while (candidateFolder !== null && candidateFolder !== undefined); return finalPathPrefix + candidateFolderPath; } static async _generateFileNameForNewItem(project, basePath, baseName, extension) { if (project.projectFolder === null) { return undefined; } let index = 0; let candidateFilePath = ""; let finalPathPrefix = ""; const projectFolder = project.projectFolder; let candidateFile = null; let hash = basePath.indexOf("#"); let targetFolder = projectFolder; while (hash > 0) { // dig into container files if needed. let containerFilePath = basePath.substring(0, hash); basePath = basePath.substring(hash + 1); hash = basePath.indexOf("#"); if (containerFilePath.startsWith(targetFolder.fullPath)) { containerFilePath = containerFilePath.substring(targetFolder.fullPath.length); } finalPathPrefix += containerFilePath + "#"; const containerFile = await targetFolder.getFileFromRelativePath(containerFilePath); if (!containerFile) { return undefined; } const extension = containerFile.type; if (extension !== "zip" && extension !== "mcworld" && extension !== "mctemplate") { return undefined; } if (!containerFile.fileContainerStorage) { const zipStorage = new ZipStorage_1.default(); if (!containerFile.isContentLoaded) { await containerFile.loadContent(); } if (!containerFile.content || !(containerFile.content instanceof Uint8Array)) { return undefined; } await zipStorage.loadFromUint8Array(containerFile.content); zipStorage.containerFile = containerFile; containerFile.fileContainerStorage = zipStorage; containerFile.fileContainerStorage.storagePath = containerFilePath + "#"; } targetFolder = containerFile.fileContainerStorage.rootFolder; } await targetFolder.ensureFolderFromRelativePath(basePath); await targetFolder.ensureExists(); candidateFilePath = basePath + baseName + "." + extension; candidateFile = await targetFolder.getFileFromRelativePath(candidateFilePath); if (candidateFile) { // find a filename not in use do { index++; candidateFilePath = basePath + baseName + index + "." + extension; candidateFile = await targetFolder.getFileFromRelativePath(candidateFilePath); } while (candidateFile !== null && candidateFile !== undefined); } return finalPathPrefix + candidateFilePath; } static async createNewGameTestScript(project) { const defaultPath = await ProjectItemCreateManager._getDefaultBehaviorPackFolderPath(project, "scripts"); if (defaultPath === undefined) { return; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, defaultPath, "test", "js"); if (candidateFilePath === undefined) { return; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.testJs, Project_1.FolderContext.behaviorPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { const baseName = StorageUtilities_1.default.getBaseFromName(file.name); if (project.preferredScriptLanguage === IProjectData_1.ProjectScriptLanguage.typeScript) { const tsFile = file.parentFolder.ensureFile(baseName + ".ts"); if (tsFile !== null) { const content = ProjectContent_1.default.getEmptyTestTypeScript(project.name, baseName); tsFile.setContent(content); } } const content = ProjectContent_1.default.getEmptyTestJavaScript(project.name, baseName); file.setContent(content); } await project.save(); } static async createNewFunction(project) { const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "functions"); if (defaultPath === undefined) { return; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, defaultPath, "action", "mcfunction"); if (candidateFilePath === undefined) { return; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.MCFunction, Project_1.FolderContext.behaviorPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { const content = "say hello"; file.setContent(content); } await project.save(); } static async createNewStructure(project) { const defaultPath = await ProjectItemCreateManager._getDefaultBehaviorPackFolderPath(project, "structures"); if (defaultPath === undefined) { return; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, defaultPath, "structure", "mcstructure"); if (candidateFilePath === undefined) { return; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.structure, Project_1.FolderContext.behaviorPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { const structureBytes = ProjectContent_1.default.generateDefaultStructure(); if (structureBytes !== undefined) { file.setContent(structureBytes); } } await project.save(); } /** * "Empty file" / "Open as Raw" companion: drops a minimally-valid stub at the * conventional sub-folder for `contentType` under the project's default * behavior or resource pack. Used by the Add dialog's "Empty File (advanced)" * path so power users can author files that don't fit an existing wizard. * * If `desiredName` is omitted or already taken, a numeric suffix is appended * (handled by `_generateFileNameForNewItem`). Returns the created * `ProjectItem` so callers can select/open it. */ static async createNewEmptyStubFile(project, contentType, desiredName) { const config = ProjectItemCreateManager._getEmptyStubConfig(contentType); if (!config) { Log_1.default.error("createNewEmptyStubFile: unsupported contentType " + contentType); return undefined; } const baseFileName = (desiredName && desiredName.trim()) || config.defaultBaseName; let defaultPath; if (config.folderContext === Project_1.FolderContext.resourcePack) { defaultPath = await ProjectItemCreateManager._getDefaultResourcePackFolderPath(project, config.subfolder); } else { defaultPath = await ProjectItemCreateManager._getDefaultBehaviorPackFolderPath(project, config.subfolder); } if (defaultPath === undefined) { return undefined; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, defaultPath, baseFileName, config.extension); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), contentType, config.folderContext, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null && config.stubContent !== undefined) { file.setContent(config.stubContent); } await project.save(); return pi; } /** * Map a content type to the sub-folder, default file name, extension, and * minimally-valid stub content used by `createNewEmptyStubFile`. Stubs are * intentionally tiny — the goal is to land an editable file at the right * path, not to template a fully-valid definition (the wizards do that). * * TODO: the `format_version` in JSON stubs is hardcoded to `STUB_FORMAT_VERSION` * below. The rest of the codebase resolves the latest format version * dynamically (see `FormatVersionManager` and `Database.getLatestVersionInfo`). * When this method becomes async-friendly, pull the version from there so * stubs don't go stale. */ static STUB_FORMAT_VERSION = "1.21.0"; // Lazily built on first access. Building this eagerly via a static IIFE caused // a "Cannot read properties of undefined (reading 'behaviorPack')" crash at // module load when this file ended up earlier in a circular import chain than // ./Project (which exports FolderContext). static _emptyStubConfigsCache; static get EMPTY_STUB_CONFIGS() { if (ProjectItemCreateManager._emptyStubConfigsCache) { return ProjectItemCreateManager._emptyStubConfigsCache; } const v = ProjectItemCreateManager.STUB_FORMAT_VERSION; const json = (body) => body; const bp = Project_1.FolderContext.behaviorPack; ProjectItemCreateManager._emptyStubConfigsCache = { [IProjectItemData_1.ProjectItemType.entityTypeBehavior]: { subfolder: "entities", defaultBaseName: "entity", extension: "json", folderContext: bp, body: json(`{\n "format_version": "${v}",\n "minecraft:entity": {\n "description": {},\n "components": {}\n }\n}\n`), }, [IProjectItemData_1.ProjectItemType.blockTypeBehavior]: { subfolder: "blocks", defaultBaseName: "block", extension: "json", folderContext: bp, body: json(`{\n "format_version": "${v}",\n "minecraft:block": {\n "description": {},\n "components": {}\n }\n}\n`), }, [IProjectItemData_1.ProjectItemType.itemTypeBehavior]: { subfolder: "items", defaultBaseName: "item", extension: "json", folderContext: bp, body: json(`{\n "format_version": "${v}",\n "minecraft:item": {\n "description": {},\n "components": {}\n }\n}\n`), }, [IProjectItemData_1.ProjectItemType.lootTableBehavior]: { subfolder: "loot_tables", defaultBaseName: "loot_table", extension: "json", folderContext: bp, body: '{\n "pools": []\n}\n', }, [IProjectItemData_1.ProjectItemType.recipeBehavior]: { subfolder: "recipes", defaultBaseName: "recipe", extension: "json", folderContext: bp, body: json(`{\n "format_version": "${v}",\n "minecraft:recipe_shapeless": {\n "description": {},\n "tags": [],\n "ingredients": [],\n "result": {}\n }\n}\n`), }, [IProjectItemData_1.ProjectItemType.spawnRuleBehavior]: { subfolder: "spawn_rules", defaultBaseName: "spawn_rule", extension: "json", folderContext: bp, body: json(`{\n "format_version": "${v}",\n "minecraft:spawn_rules": {\n "description": {},\n "conditions": []\n }\n}\n`), }, [IProjectItemData_1.ProjectItemType.MCFunction]: { subfolder: "functions", defaultBaseName: "action", extension: "mcfunction", folderContext: bp, body: "# New function — add commands below\n", }, [IProjectItemData_1.ProjectItemType.unknownJson]: { subfolder: "", defaultBaseName: "untitled", extension: "json", folderContext: bp, body: "{}\n", }, }; return ProjectItemCreateManager._emptyStubConfigsCache; } static _getEmptyStubConfig(contentType) { const entry = ProjectItemCreateManager.EMPTY_STUB_CONFIGS[contentType]; if (!entry) { return undefined; } return { subfolder: entry.subfolder, defaultBaseName: entry.defaultBaseName, extension: entry.extension, folderContext: entry.folderContext, stubContent: entry.body, }; } static async createNewActionSet(project) { const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "actions"); if (defaultPath === undefined) { return; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, defaultPath, "actionset", "json"); if (candidateFilePath === undefined) { return; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.actionSet, Project_1.FolderContext.behaviorPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { const baseName = StorageUtilities_1.default.getBaseFromName(file.name); const content = ProjectContent_1.default.getEmptyActionSet(project.name, baseName); file.setContent(content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); } static async createNewDocumentedType(project) { const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "docs"); if (defaultPath === undefined) { return; } const candidateFolderPath = await ProjectItemCreateManager._generateFolderNameForNewItem(project, defaultPath, "type"); if (candidateFolderPath === undefined) { return; } const pi = project.ensureItemByProjectPath(candidateFolderPath, IProjectItemData_1.ProjectItemStorageType.folder, candidateFolderPath, IProjectItemData_1.ProjectItemType.documentedTypeFolder, Project_1.FolderContext.metaData, undefined, IProjectItemData_1.ProjectItemCreationType.normal); await pi.loadFolder(); await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); } static getExistingPath(project, itemType) { if (!project.projectFolder) { return undefined; } for (const item of project.items) { if (item.itemType === itemType && item.primaryFile) { return item.primaryFile.parentFolder.getFolderRelativePath(project.projectFolder); } } return undefined; } static async createNewForm(project, name, folder) { let path = undefined; if (!project.projectFolder) { return undefined; } if (folder) { path = folder.getFolderRelativePath(project.projectFolder); } else { path = ProjectItemCreateManager.getExistingPath(project, IProjectItemData_1.ProjectItemType.dataForm); if (path === undefined) { path = await this._getDefaultBehaviorPackFolderPath(project, "forms"); if (path === undefined) { return undefined; } } } if (!path) { return undefined; } if (!name) { name = "form"; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, name, "form.json"); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.dataForm, Project_1.FolderContext.metaData, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { const content = "{}"; file.setContent(content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return pi; } static async ensureSoundDefinitionCatalogDefinition(project) { const items = project.getItemsByType(IProjectItemData_1.ProjectItemType.soundDefinitionCatalog); if (items.length > 0) { if (!items[0].isContentLoaded) { await items[0].loadContent(); } const itemFile = items[0].primaryFile; if (itemFile) { if (!itemFile.isContentLoaded) { await itemFile.loadContent(); } if (!itemFile.content) { this.setFileToDefaultContent(itemFile); } return await SoundDefinitionCatalogDefinition_1.default.ensureOnFile(itemFile); } } let path = undefined; if (!project.projectFolder) { return undefined; } path = await this._getDefaultResourcePackFolderPath(project, "sounds"); if (path === undefined) { return undefined; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, "sound_definitions", "json"); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.soundDefinitionCatalog, Project_1.FolderContext.resourcePack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file === null) { return undefined; } this.setFileToDefaultContent(file); await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return await SoundDefinitionCatalogDefinition_1.default.ensureOnFile(file); } static setFileToDefaultContent(file) { const content = '{\n "format_version" : "1.20.20",\n "sound_definitions" : {}\n}'; file.setContent(content); file.saveContent(); } static async addFromGallery(project, newName, galleryItem) { if (galleryItem.type === IGalleryItem_1.GalleryItemType.entityType) { await ProjectCreateManager_1.default.addEntityTypeFromGallery(project, galleryItem, newName, ProjectUtilities_1.NewEntityTypeAddMode.baseId, async (message) => { Log_1.default.message(message); }); } else if (galleryItem.type === IGalleryItem_1.GalleryItemType.itemType) { await ProjectCreateManager_1.default.addItemTypeFromGallery(project, galleryItem, newName); } else if (galleryItem.type === IGalleryItem_1.GalleryItemType.blockType) { await ProjectCreateManager_1.default.addBlockTypeFromGallery(project, galleryItem, newName); } else if (galleryItem.type === IGalleryItem_1.GalleryItemType.modelDesign) { await ProjectCreateManager_1.default.addModelDesignFromGallery(project, galleryItem, newName); } else if (galleryItem.type >= IGalleryItem_1.GalleryItemType.spawnLootRecipes && galleryItem.targetType) { await ProjectItemCreateManager.createNewItem(project, { itemType: galleryItem.targetType, contentTemplateName: galleryItem.id, name: newName, folder: undefined, }); } } static async ensureSoundCatalogDefinition(project) { const items = project.getItemsByType(IProjectItemData_1.ProjectItemType.soundCatalog); if (items.length > 0) { if (!items[0].isContentLoaded) { await items[0].loadContent(); } if (items[0].primaryFile) { return await SoundCatalogDefinition_1.default.ensureOnFile(items[0].primaryFile); } } let path = undefined; if (!project.projectFolder) { return undefined; } path = await this._getDefaultResourcePackFolderPath(project, "sounds"); if (path === undefined) { return undefined; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, "sounds", "json"); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.soundCatalog, Project_1.FolderContext.resourcePack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file === null) { return undefined; } const content = "{\n}"; file.setContent(content); await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return await SoundCatalogDefinition_1.default.ensureOnFile(file); } static async createDesignPackJsonItem(project, itemSeed) { let path = undefined; if (!project.projectFolder) { return undefined; } const folderRootsForType = ProjectItemUtilities_1.default.getFolderRootsForType(itemSeed.itemType); Log_1.default.assert(folderRootsForType.length > 0, "No folder roots for item type: " + itemSeed.itemType); if (itemSeed.folder) { path = itemSeed.folder.getFolderRelativePath(project.projectFolder); } else { path = ProjectItemCreateManager.getExistingPath(project, itemSeed.itemType); if (path === undefined) { path = await this._getDefaultDesignPackFolderPath(project, folderRootsForType[0]); if (path === undefined) { return undefined; } } } if (!path) { return undefined; } let namespacedId = itemSeed.name; let name = namespacedId; if (!namespacedId || !name) { name = ProjectItemUtilities_1.default.getNewItemTechnicalName(itemSeed.itemType); namespacedId = name; } name = MinecraftUtilities_1.default.getNamespacedIdName(name); const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, name, "json"); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), itemSeed.itemType, Project_1.FolderContext.designPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { let content = "{}"; await Database_1.default.loadContent(); if (Database_1.default.contentFolder !== null) { const contentTemplate = itemSeed.contentTemplateName ? itemSeed.contentTemplateName : ProjectItemUtilities_1.default.getNewItemTechnicalName(itemSeed.itemType); const sourceFile = await Database_1.default.contentFolder.getFileFromRelativePath("/newitemjson/" + contentTemplate + ".json"); if (sourceFile) { if (!sourceFile.isContentLoaded) { await sourceFile.loadContent(); } if (sourceFile.content) { content = sourceFile.content.toString(); } } } content = content.replace(/examplens:examplename/g, namespacedId); file.setContent(content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return pi; } static async createBehaviorPackJsonItem(project, itemSeed) { let path = undefined; if (!project.projectFolder) { return undefined; } const folderRootsForType = ProjectItemUtilities_1.default.getFolderRootsForType(itemSeed.itemType); Log_1.default.assert(folderRootsForType.length > 0, "No folder roots for item type: " + itemSeed.itemType); if (itemSeed.folder) { path = itemSeed.folder.getFolderRelativePath(project.projectFolder); } else { path = ProjectItemCreateManager.getExistingPath(project, itemSeed.itemType); if (path === undefined) { path = await this._getDefaultBehaviorPackFolderPath(project, folderRootsForType[0]); if (path === undefined) { return undefined; } } } if (!path) { return undefined; } let namespacedId = itemSeed.name; let name = namespacedId; if (!namespacedId || !name) { name = ProjectItemUtilities_1.default.getNewItemTechnicalName(itemSeed.itemType); namespacedId = name; } name = MinecraftUtilities_1.default.getNamespacedIdName(name); const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, name, "json"); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), itemSeed.itemType, Project_1.FolderContext.behaviorPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { let content = "{}"; await Database_1.default.loadContent(); if (Database_1.default.contentFolder !== null) { const contentTemplate = itemSeed.contentTemplateName ? itemSeed.contentTemplateName : ProjectItemUtilities_1.default.getNewItemTechnicalName(itemSeed.itemType); const path = "/newitemjson/" + contentTemplate + ".json"; const sourceFile = await Database_1.default.contentFolder.getFileFromRelativePath(path); if (sourceFile) { if (!sourceFile.isContentLoaded) { await sourceFile.loadContent(); } if (sourceFile.content) { content = sourceFile.content.toString(); } } } content = content.replace(/examplens:examplename/g, namespacedId); file.setContent(content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return pi; } static async createResourcePackJsonItem(project, itemSeed) { let path = undefined; if (!project.projectFolder) { return undefined; } const folderRootsForType = ProjectItemUtilities_1.default.getFolderRootsForType(itemSeed.itemType); Log_1.default.assert(folderRootsForType.length > 0, "No folder roots for item type: " + itemSeed.itemType); if (itemSeed.folder) { path = itemSeed.folder.getFolderRelativePath(project.projectFolder); } else { path = ProjectItemCreateManager.getExistingPath(project, itemSeed.itemType); if (path === undefined) { path = await this._getDefaultResourcePackFolderPath(project, folderRootsForType[0]); if (path === undefined) { return undefined; } } } if (!path) { return undefined; } let namespacedId = itemSeed.name; let name = namespacedId; if (!namespacedId || !name) { name = ProjectItemUtilities_1.default.getNewItemTechnicalName(itemSeed.itemType); namespacedId = name; } name = MinecraftUtilities_1.default.getNamespacedIdName(name); const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, name, "json"); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), itemSeed.itemType, Project_1.FolderContext.resourcePack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { let content = "{}"; await Database_1.default.loadContent(); if (Database_1.default.contentFolder !== null) { const contentTemplate = itemSeed.contentTemplateName ? itemSeed.contentTemplateName : ProjectItemUtilities_1.default.getNewItemTechnicalName(itemSeed.itemType); const sourceFile = await Database_1.default.contentFolder.getFileFromRelativePath("/newitemjson/" + contentTemplate + ".json"); if (sourceFile) { if (!sourceFile.isContentLoaded) { await sourceFile.loadContent(); } if (sourceFile.content) { content = sourceFile.content.toString(); } } } content = content.replace(/examplens:examplename/g, namespacedId); file.setContent(content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return pi; } static async createNewResourcePackBinaryItem(project, sourceFileName, extension, defaultFolderPath, exampleName, itemType, name, folder) { let path = undefined; if (!project.projectFolder) { return undefined; } await Database_1.default.loadContent(); if (Database_1.default.contentFolder === null) { Log_1.default.unexpectedContentState(); return undefined; } const sourceFile = Database_1.default.contentFolder.ensureFile(sourceFileName); if (!sourceFile.isContentLoaded) { await sourceFile.loadContent(); } if (!(sourceFile.content instanceof Uint8Array)) { Log_1.default.error("Could not find source " + extension + " file content."); return; } if (folder) { path = folder.getFolderRelativePath(project.projectFolder); } else { path = ProjectItemCreateManager.getExistingPath(project, itemType); if (path === undefined) { path = await this._getDefaultResourcePackFolderPath(project, defaultFolderPath); if (path === undefined) { return undefined; } } } if (!path) { return undefined; } if (!name) { name = exampleName; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, name, extension); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), itemType, Project_1.FolderContext.resourcePack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { file.setContent(sourceFile.content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return pi; } static async createNewDesignPackBinaryItem(project, sourceFileName, extension, defaultFolderPath, exampleName, itemType, name, folder) { let path = undefined; if (!project.projectFolder) { return undefined; } await Database_1.default.loadContent(); if (Database_1.default.contentFolder === null) { Log_1.default.unexpectedContentState(); return undefined; } const sourceFile = Database_1.default.contentFolder.ensureFile(sourceFileName); if (!sourceFile.isContentLoaded) { await sourceFile.loadContent(); } if (!(sourceFile.content instanceof Uint8Array)) { Log_1.default.error("Could not find source " + extension + " file content."); return; } if (folder) { path = folder.getFolderRelativePath(project.projectFolder); } else { path = ProjectItemCreateManager.getExistingPath(project, itemType); if (path === undefined) { path = await this._getDefaultDesignPackFolderPath(project, defaultFolderPath); if (path === undefined) { return undefined; } } } if (!path) { return undefined; } if (!name) { name = exampleName; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path, name, extension); if (candidateFilePath === undefined) { return undefined; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), itemType, Project_1.FolderContext.designPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { file.setContent(sourceFile.content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); return pi; } static async createNewDesignTexture(project, name, folder, creationData) { const projectItem = await this.createNewDesignPackBinaryItem(project, "blank64.png", "png", "design_textures", "design_texture", IProjectItemData_1.ProjectItemType.designTexture, name, folder); if (projectItem && creationData) { const imageEdits = await ImageEditsDefinition_1.default.ensureAsAccessoryOnImageProjectItem(projectItem); if (imageEdits) { await imageEdits.setFromCreationData(creationData); } } return projectItem; } static async createNewTexture(project, name, folder) { return await this.createNewResourcePackBinaryItem(project, "blank64.png", "png", "textures", "texture", IProjectItemData_1.ProjectItemType.texture, name, folder); } static async createNewAudio(project, name, folder) { return await this.createNewResourcePackBinaryItem(project, "blank.ogg", "ogg", "sounds", "sound", IProjectItemData_1.ProjectItemType.audio, name, folder); } static async createNewWorldTest(project, name, folder) { let path = undefined; if (!project.projectFolder) { return; } if (folder) { path = folder.getFolderRelativePath(project.projectFolder); } else { path = ProjectItemCreateManager.getExistingPath(project, IProjectItemData_1.ProjectItemType.dataForm); if (path === undefined) { path = await this._getDefaultBehaviorPackFolderPath(project, "forms"); if (path === undefined) { return; } } } if (!path) { return; } if (!name) { name = "form"; } const candidateFilePath = await ProjectItemCreateManager._generateFileNameForNewItem(project, path + "tests/", "worldtest", "json"); if (candidateFilePath === undefined) { return; } const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.worldTest, Project_1.FolderContext.behaviorPack, undefined, IProjectItemData_1.ProjectItemCreationType.normal); const file = await pi.loadFileContent(); if (file !== null) { const baseName = StorageUtilities_1.default.getBaseFromName(file.name); const content = ProjectContent_1.default.getEmptyWorldTest(project.name, baseName); file.setContent(content); } await ProjectAutogeneration_1.default.updateProjectAutogeneration(project, false); await project.save(); } } exports.default = ProjectItemCreateManager;