@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
550 lines (548 loc) • 26.9 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const ProjectContent_1 = require("./ProjectContent");
const IProjectData_1 = require("./IProjectData");
const IProjectItemData_1 = require("./IProjectItemData");
const StorageUtilities_1 = require("./../storage/StorageUtilities");
const ZipStorage_1 = require("../storage/ZipStorage");
const ProjectItemUtilities_1 = require("./ProjectItemUtilities");
const ProjectAutogeneration_1 = require("./ProjectAutogeneration");
const Database_1 = require("../minecraft/Database");
const Log_1 = require("../core/Log");
const SoundDefinitionCatalogDefinition_1 = require("../minecraft/SoundDefinitionCatalogDefinition");
const SoundCatalogDefinition_1 = require("../minecraft/SoundCatalogDefinition");
class ProjectItemManager {
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 _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);
}
if (itemSeed.itemType) {
switch (itemSeed.itemType) {
case IProjectItemData_1.ProjectItemType.js:
case IProjectItemData_1.ProjectItemType.ts:
return ProjectItemManager.createNewScript(project, itemSeed.itemType, itemSeed.name, itemSeed.folder);
case IProjectItemData_1.ProjectItemType.dataForm:
return ProjectItemManager.createNewForm(project, itemSeed.name, itemSeed.folder);
case IProjectItemData_1.ProjectItemType.spawnRuleBehavior:
return ProjectItemManager.createNewSpawnRule(project, itemSeed.name, itemSeed.folder);
case IProjectItemData_1.ProjectItemType.audio:
return ProjectItemManager.createNewAudio(project, itemSeed.name, itemSeed.folder);
}
}
return undefined;
}
static async createNewScript(project, itemType, name, folder) {
let defaultPath = undefined;
if (folder && project.projectFolder) {
defaultPath = folder.getFolderRelativePath(project.projectFolder);
}
else {
defaultPath = await ProjectItemManager._getDefaultScriptsFolderPath(project);
}
if (defaultPath === undefined) {
return;
}
const candidateFilePath = await ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
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);
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();
await containerFile.loadContent();
if (!containerFile.content || !(containerFile.content instanceof Uint8Array)) {
return undefined;
}
await zipStorage.loadFromUint8Array(containerFile.content, containerFile.name);
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();
await containerFile.loadContent();
if (!containerFile.content || !(containerFile.content instanceof Uint8Array)) {
return undefined;
}
await zipStorage.loadFromUint8Array(containerFile.content);
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 ProjectItemManager._getDefaultBehaviorPackFolderPath(project, "scripts");
if (defaultPath === undefined) {
return;
}
const candidateFilePath = await ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
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 ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
if (file !== null) {
const content = "say hello";
file.setContent(content);
}
await project.save();
}
static async createNewStructure(project) {
const defaultPath = await ProjectItemManager._getDefaultBehaviorPackFolderPath(project, "structures");
if (defaultPath === undefined) {
return;
}
const candidateFilePath = await ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
if (file !== null) {
const structureBytes = ProjectContent_1.default.generateDefaultStructure();
if (structureBytes !== undefined) {
file.setContent(structureBytes);
}
}
await project.save();
}
static async createNewActionSet(project) {
const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "actions");
if (defaultPath === undefined) {
return;
}
const candidateFilePath = await ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
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);
}
static async createNewDocumentedType(project) {
const defaultPath = await this._getDefaultBehaviorPackFolderPath(project, "docs");
if (defaultPath === undefined) {
return;
}
const candidateFolderPath = await ProjectItemManager._generateFolderNameForNewItem(project, defaultPath, "type");
if (candidateFolderPath === undefined) {
return;
}
const pi = project.ensureItemByProjectPath(candidateFolderPath, IProjectItemData_1.ProjectItemStorageType.folder, candidateFolderPath, IProjectItemData_1.ProjectItemType.documentedTypeFolder, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
await pi.ensureFolderStorage();
await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
await project.save();
}
static getExistingPath(project, itemType) {
if (!project.projectFolder) {
return undefined;
}
for (const item of project.items) {
if (item.itemType === itemType && item.file) {
return item.file.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 = ProjectItemManager.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 ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
if (file !== null) {
const content = "{}";
file.setContent(content);
}
await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
await project.save();
return pi;
}
static async ensureSoundDefinitionCatalogDefinition(project) {
const items = project.getItemByType(IProjectItemData_1.ProjectItemType.soundDefinitionCatalog);
if (items.length > 0) {
await items[0].ensureStorage();
if (items[0].file) {
await items[0].file.loadContent();
if (!items[0].file.content) {
this.setFileToDefaultContent(items[0].file);
}
return await SoundDefinitionCatalogDefinition_1.default.ensureOnFile(items[0].file);
}
}
let path = undefined;
if (!project.projectFolder) {
return undefined;
}
path = await this._getDefaultResourcePackFolderPath(project, "sounds");
if (path === undefined) {
return undefined;
}
const candidateFilePath = await ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
if (file === null) {
return undefined;
}
this.setFileToDefaultContent(file);
await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
await project.save();
return await SoundDefinitionCatalogDefinition_1.default.ensureOnFile(file);
}
static setFileToDefaultContent(file) {
const content = '{\r\n "format_version" : "1.20.20",\r\n "sound_definitions" : {}\r\n}';
file.setContent(content);
file.saveContent();
}
static async ensureSoundCatalogDefinition(project) {
const items = project.getItemByType(IProjectItemData_1.ProjectItemType.soundCatalog);
if (items.length > 0) {
await items[0].ensureStorage();
if (items[0].file) {
return await SoundCatalogDefinition_1.default.ensureOnFile(items[0].file);
}
}
let path = undefined;
if (!project.projectFolder) {
return undefined;
}
path = await this._getDefaultResourcePackFolderPath(project, "sounds");
if (path === undefined) {
return undefined;
}
const candidateFilePath = await ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
if (file === null) {
return undefined;
}
const content = "{\r\n}";
file.setContent(content);
await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
await project.save();
return await SoundCatalogDefinition_1.default.ensureOnFile(file);
}
static async createNewSpawnRule(project, name, folder) {
let path = undefined;
if (!project.projectFolder) {
return undefined;
}
if (folder) {
path = folder.getFolderRelativePath(project.projectFolder);
}
else {
path = ProjectItemManager.getExistingPath(project, IProjectItemData_1.ProjectItemType.spawnRuleBehavior);
if (path === undefined) {
path = await this._getDefaultBehaviorPackFolderPath(project, "spawn_rules");
if (path === undefined) {
return undefined;
}
}
}
if (!path) {
return undefined;
}
if (!name) {
name = "spawn_rule";
}
const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, path, name, "json");
if (candidateFilePath === undefined) {
return undefined;
}
const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.spawnRuleBehavior, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
if (file !== null) {
const content = "{}";
file.setContent(content);
}
await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
await project.save();
return pi;
}
static async createNewAudio(project, 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("blank.ogg");
await sourceFile.loadContent();
if (!(sourceFile.content instanceof Uint8Array)) {
Log_1.default.error("Could not find source OGG file content.");
return;
}
if (folder) {
path = folder.getFolderRelativePath(project.projectFolder);
}
else {
path = ProjectItemManager.getExistingPath(project, IProjectItemData_1.ProjectItemType.audio);
if (path === undefined) {
path = await this._getDefaultResourcePackFolderPath(project, "sounds");
if (path === undefined) {
return undefined;
}
}
}
if (!path) {
return undefined;
}
if (!name) {
name = "sound";
}
const candidateFilePath = await ProjectItemManager._generateFileNameForNewItem(project, path, name, "mp3");
if (candidateFilePath === undefined) {
return undefined;
}
const pi = project.ensureItemByProjectPath(candidateFilePath, IProjectItemData_1.ProjectItemStorageType.singleFile, StorageUtilities_1.default.getLeafName(candidateFilePath), IProjectItemData_1.ProjectItemType.audio, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
if (file !== null) {
file.setContent(sourceFile.content);
}
await ProjectAutogeneration_1.default.updateProjectAutogeneration(project);
await project.save();
return pi;
}
static async createNewWorldTest(project, name, folder) {
let path = undefined;
if (!project.projectFolder) {
return;
}
if (folder) {
path = folder.getFolderRelativePath(project.projectFolder);
}
else {
path = ProjectItemManager.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 ProjectItemManager._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, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
const file = await pi.ensureFileStorage();
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);
await project.save();
}
}
exports.default = ProjectItemManager;
//# sourceMappingURL=../maps/app/ProjectItemManager.js.map