@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
1,316 lines • 164 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.vanillaSliceFolderSeeds = exports.remappedMinecraftScriptModules = exports.minecraftScriptModules = exports.AUTOGENERATED_WHOLEFILE_GENERAL_SEPARATOR = exports.AUTOGENERATED_WHOLEFILE_MCFUNCTION_SEPARATOR = exports.AUTOGENERATED_WHOLEFILE_JS_SEPARATOR = exports.AUTOGENERATED_JS_SEPARATOR = exports.AUTOGENERATED_CONTENT_TOKEN = exports.ProjectTargetStrings = exports.FolderContext = exports.ProjectErrorState = exports.ProjectAutoDeploymentMode = void 0;
/*
* ==========================================================================================
* PROJECT - CORE PROJECT MANAGEMENT NOTES
* ==========================================================================================
*
* OVERVIEW:
* ---------
* Project is the central class for managing a Minecraft content project. It handles:
* - Project structure (behavior packs, resource packs, worlds, scripts)
* - Item discovery and inference from folder structure
* - Pack management (BehaviorManifest, ResourceManifest)
* - Validation integration via ProjectInfoSet
* - Export/deployment coordination
*
* PROJECT STRUCTURE:
* ------------------
* A project typically contains:
* - behaviorPacksContainer/ - Behavior pack folders
* - resourcePacksContainer/ - Resource pack folders
* - worldContainer/ - World folders
* - docsContainer/ - Documentation
* - defaultBehaviorPackFolder, defaultResourcePackFolder - Primary packs
*
* KEY METHOD: _inferProjectItemsFromFolder():
* -------------------------------------------
* This is the monster recursive function that scans a folder tree and creates
* ProjectItem objects based on file type and location. Logic includes:
* - Path-based type inference (items/ folder → itemTypeBehaviorJson)
* - Extension-based inference (.mcfunction, .json, .ts)
* - Manifest detection for pack identification
* - World detection from level.dat
*
* PROJECTITEM RELATIONSHIP:
* -------------------------
* - Project contains ProjectItem[] in #items
* - Items indexed by #itemsByProjectPath (canonicalized storage path)
* - Items grouped by #itemsByType for quick type lookups
* - Each ProjectItem has storagePath relative to project root
* - Items link to IFile via file property, with .manager for type-specific logic
*
* PACK MANAGEMENT:
* ----------------
* - #packs: Pack[] - All discovered packs (behavior, resource, skin, world)
* - Pack objects wrap manifest files and provide pack-level operations
* - hasMultiplePacksOfSameType affects folder structure assumptions
*
* VARIANTS:
* ---------
* - variants: { [label]: ProjectVariant } - Alternative configurations
* - Used for multi-target builds (different Minecraft versions, platforms)
* - ProjectItemVariantCreateManager handles variant-specific item creation
*
* LOADING SEQUENCE FOR EXTERNAL USERS:
* ------------------------------------
* 1. new Project(creatorTools, folder, prefsFile) - Basic setup
* 2. loadPreferencesAndFolder() - Basic loading from prefsFile JSON (isLoaded)
* 3. inferProjectItemsFromFolder() - Create ProjectItems from files.
* This is a somewhat expensive operation, and only needs to be done on
* first instantiation on a folder, or if the folder/file set structure
* changes
* 4. ensureInflate() - Load file contents and initialize managers (isInflated)
*
* OPTIONAL ADDITION THINGS YOU SHOULD DO:
* ---------------------------------------
*
* The web app, for example, does these asynchronously after first load.
* These operations can take minutes to run, depending on project size.
*
* processRelations() - Build cross-item dependency graph (best done async)
*
*
* INTERNAL FUNCTIONS
* ------------------
* loadFolderStructure() - Discover folder hierarchy and rough mapping
*
* EVENTS:
* -------
* - onPropertyChanged: Project metadata changed
* - onLoaded: Folder structure loaded
* - onInflated: All items loaded
* - onItemChanged/Added/Removed: Item list modifications
* - onItemContentChanged: Item file content changed
* - onNeedsSaveChanged: Dirty state changed
*
* WORLD SETTINGS:
* ---------------
* - worldSettings: IWorldSettings - Default world configuration
* - editorWorldSettings: Settings for Editor API worlds
* - ensureWorldSettings() / ensureEditorWorldSettings() - Lazy initialization
*
* RELATED FILES:
* --------------
* - ProjectItem.ts: Individual item management
* - ProjectUtilities.ts: Static helper methods (moved from Project)
* - ProjectExporter.ts: Export/packaging logic
* - ProjectInfoSet.ts: Validation integration
* - Pack.ts: Pack-level operations
* - ProjectItemInference.ts: Item type inference logic
*
* FOLDER CONTEXTS (FolderContext enum):
* -------------------------------------
* Used to identify folder purpose during inference:
* - behaviorPack (1), resourcePack (2), skinPack (3)
* - world (5), docs (4), typeDefs (6)
* - distBuildFolder (7), vscodeFolder (8)
* - mctoolsWorkingFolder (13), designPack (14)
*
* COMMON PATTERNS:
* ----------------
* - Get item: project.getItemByProjectPath(storagePath)
* - Get items by type: project.getItemsByType(ProjectItemType.entityTypeBehaviorJson)
* - Ensure folder: project.ensureDefaultBehaviorPackFolder()
* - Save project: project.save()
*
* ==========================================================================================
*/
const IFile_1 = require("../storage/IFile");
const IProjectData_1 = require("./IProjectData");
const IProjectData_2 = require("./IProjectData");
const ProjectItem_1 = __importDefault(require("./ProjectItem"));
const IProjectItemData_1 = require("./IProjectItemData");
const Utilities_1 = __importDefault(require("./../core/Utilities"));
const ste_events_1 = require("ste-events");
const StorageUtilities_1 = __importDefault(require("../storage/StorageUtilities"));
const Log_1 = __importDefault(require("../core/Log"));
const ProjectUtilities_1 = __importDefault(require("./ProjectUtilities"));
const WorldLevelDat_1 = require("../minecraft/WorldLevelDat");
const IWorldSettings_1 = require("../minecraft/IWorldSettings");
const BehaviorManifestDefinition_1 = __importDefault(require("../minecraft/BehaviorManifestDefinition"));
const MinecraftUtilities_1 = __importDefault(require("../minecraft/MinecraftUtilities"));
const LocManager_1 = __importDefault(require("../minecraft/LocManager"));
const ProjectInfoSet_1 = __importDefault(require("../info/ProjectInfoSet"));
const ProjectInfoItem_1 = __importDefault(require("../info/ProjectInfoItem"));
const ProjectUpdateRunner_1 = __importDefault(require("../updates/ProjectUpdateRunner"));
const InfoGeneratorTopicUtilities_1 = __importDefault(require("../info/InfoGeneratorTopicUtilities"));
const GeneratorRegistrations_1 = __importDefault(require("../info/registration/GeneratorRegistrations"));
const Telemetry_1 = __importDefault(require("../analytics/Telemetry"));
const TelemetryStub_1 = __importDefault(require("../analytics/TelemetryStub"));
let telemetry = TelemetryStub_1.default;
// @ts-ignore - ENABLE_ANALYTICS is injected by webpack and vite configs
if (typeof ENABLE_ANALYTICS !== "undefined" && ENABLE_ANALYTICS === true) {
telemetry = Telemetry_1.default;
}
const TelemetryConstants_1 = require("../analytics/TelemetryConstants");
const Status_1 = require("./Status");
const IProjectInfoData_1 = require("../info/IProjectInfoData");
const Pack_1 = __importStar(require("../minecraft/Pack"));
const ProjectDeploySync_1 = __importDefault(require("./ProjectDeploySync"));
const ICreatorToolsData_1 = require("./ICreatorToolsData");
const ProjectItemRelations_1 = __importDefault(require("./ProjectItemRelations"));
const ResourceManifestDefinition_1 = __importDefault(require("../minecraft/ResourceManifestDefinition"));
const ProjectLookupUtilities_1 = __importDefault(require("./ProjectLookupUtilities"));
const ProjectVariant_1 = __importDefault(require("./ProjectVariant"));
const IProjectItemVariant_1 = require("./IProjectItemVariant");
const ProjectItemInference_1 = __importDefault(require("./ProjectItemInference"));
const IProjectWorkerManager_1 = require("./IProjectWorkerManager");
const ScriptModuleInfo_1 = require("../langcore/javascript/ScriptModuleInfo");
var ProjectAutoDeploymentMode;
(function (ProjectAutoDeploymentMode) {
ProjectAutoDeploymentMode[ProjectAutoDeploymentMode["deployOnSave"] = 0] = "deployOnSave";
ProjectAutoDeploymentMode[ProjectAutoDeploymentMode["noAutoDeployment"] = 1] = "noAutoDeployment";
})(ProjectAutoDeploymentMode || (exports.ProjectAutoDeploymentMode = ProjectAutoDeploymentMode = {}));
var ProjectErrorState;
(function (ProjectErrorState) {
ProjectErrorState[ProjectErrorState["noError"] = 0] = "noError";
ProjectErrorState[ProjectErrorState["projectFolderOrFileDoesNotExist"] = 1] = "projectFolderOrFileDoesNotExist";
ProjectErrorState[ProjectErrorState["cabinetFileCouldNotBeProcessed"] = 2] = "cabinetFileCouldNotBeProcessed";
})(ProjectErrorState || (exports.ProjectErrorState = ProjectErrorState = {}));
var FolderContext;
(function (FolderContext) {
FolderContext[FolderContext["unknown"] = 0] = "unknown";
FolderContext[FolderContext["behaviorPack"] = 1] = "behaviorPack";
FolderContext[FolderContext["resourcePack"] = 2] = "resourcePack";
FolderContext[FolderContext["skinPack"] = 3] = "skinPack";
FolderContext[FolderContext["docs"] = 4] = "docs";
FolderContext[FolderContext["world"] = 5] = "world";
FolderContext[FolderContext["typeDefs"] = 6] = "typeDefs";
FolderContext[FolderContext["distBuildFolder"] = 7] = "distBuildFolder";
FolderContext[FolderContext["vscodeFolder"] = 8] = "vscodeFolder";
FolderContext[FolderContext["resourcePackSubPack"] = 9] = "resourcePackSubPack";
FolderContext[FolderContext["metaData"] = 10] = "metaData";
FolderContext[FolderContext["libFolder"] = 11] = "libFolder";
FolderContext[FolderContext["persona"] = 12] = "persona";
FolderContext[FolderContext["mctoolsWorkingFolder"] = 13] = "mctoolsWorkingFolder";
FolderContext[FolderContext["designPack"] = 14] = "designPack";
})(FolderContext || (exports.FolderContext = FolderContext = {}));
exports.ProjectTargetStrings = [
"<default>",
"Latest Minecraft Bedrock",
"Latest Minecraft Bedrock preview",
"Latest Minecraft Education",
"Latest Minecraft Education preview",
];
exports.AUTOGENERATED_CONTENT_TOKEN = "==== AUTOGENERATED";
exports.AUTOGENERATED_JS_SEPARATOR = "\n// ===== AUTOGENERATED CONTENT ===== CONTENT AT OR BELOW THIS LINE WILL BE WIPED AND UPDATED WHEN USED IN TOOLING";
exports.AUTOGENERATED_WHOLEFILE_JS_SEPARATOR = "// ===== AUTOGENERATED FILE ===== CONTENT WITHIN THIS FILE WILL BE WIPED AND UPDATED WHEN USED IN TOOLING";
exports.AUTOGENERATED_WHOLEFILE_MCFUNCTION_SEPARATOR = "# ===== AUTOGENERATED FILE ===== CONTENT WITHIN THIS FILE WILL BE WIPED AND UPDATED WHEN USED IN TOOLING";
exports.AUTOGENERATED_WHOLEFILE_GENERAL_SEPARATOR = "===== AUTOGENERATED FILE ===== CONTENT WITHIN THIS FILE WILL BE WIPED AND UPDATED WHEN USED IN TOOLING";
exports.minecraftScriptModules = [
{
id: "@minecraft/server",
module_name: "@minecraft/server",
preferredVersion: ScriptModuleInfo_1.ScriptModuleInfoProvider.getLatestVersion("server", true) || "1.17.0-beta",
},
{
id: "@minecraft/server-gametest",
module_name: "@minecraft/server-gametest",
preferredVersion: ScriptModuleInfo_1.ScriptModuleInfoProvider.getLatestVersion("server-gametest", true) || "1.0.0-beta",
},
{
id: "@minecraft/server-ui",
module_name: "@minecraft/server-ui",
preferredVersion: ScriptModuleInfo_1.ScriptModuleInfoProvider.getLatestVersion("server-ui", true) || "1.5.0-beta",
},
{
id: "@minecraft/server-admin",
module_name: "@minecraft/server-admin",
preferredVersion: ScriptModuleInfo_1.ScriptModuleInfoProvider.getLatestVersion("server-admin", true) || "1.0.0-beta",
},
{
id: "@minecraft/server-net",
module_name: "@minecraft/server-net",
preferredVersion: ScriptModuleInfo_1.ScriptModuleInfoProvider.getLatestVersion("server-net", true) || "1.0.0-beta",
},
{
id: "@minecraft/server-editor",
module_name: "@minecraft/server-editor",
preferredVersion: ScriptModuleInfo_1.ScriptModuleInfoProvider.getLatestVersion("server-editor", true) || "0.1.0-beta",
},
];
exports.remappedMinecraftScriptModules = {
"mojang-minecraft": "@minecraft/server",
"mojang-gametest": "@minecraft/server-gametest",
"mojang-minecraft-ui": "@minecraft/server-ui",
"mojang-server-admin": "@minecraft/server-admin",
"mojang-net": "@minecraft/server-net",
"@minecraft/server-editor-bindings": "@minecraft/server-editor",
};
exports.vanillaSliceFolderSeeds = ["vanilla", "chemistry"];
const ProcessItemRelationsBatchSize = 400;
class Project {
#data;
#preferencesFile;
#creatorTools;
loc;
#errorState = ProjectErrorState.noError;
#errorMessage;
#indevInfoSet = null;
differencesFromGitHub;
/** Transient action to perform after this project first opens in the editor (not persisted). */
pendingPostCreateAction;
/** Transient content definition to generate after this project first opens in the editor (not persisted). */
pendingContentDefinition;
#hasMultiplePacksOfSameType;
#relationsProcessed = false;
#folderStructureLoaded = false;
#indevInfoSetNeedsUpdating = false;
// Promise to track in-progress info set generation (allows callers to wait for existing operation)
#infoSetGenerationPromise = null;
/**
* Debounce timer for batching external file changes.
* When files are added/removed externally (e.g., by MCP),
* we batch them into a single re-inference pass.
*/
#externalChangeDebounceTimer = null;
/** Pending external file additions, keyed by storage path */
#pendingExternalAdds = new Set();
/** Pending external file removals, keyed by storage path */
#pendingExternalRemoves = new Set();
/** Debounce time for external file changes in milliseconds */
static EXTERNAL_CHANGE_DEBOUNCE_MS = 500;
#mainDeployFolder = null;
#projectFolder;
#projectCabinetFile = null;
#distBuildFolder = null;
#libFolder = null;
#distBuildScriptsFolder = null;
#libScriptsFolder = null;
docsContainer;
worldContainer = null;
#mainDeploySync = null;
#isDisposed = false;
behaviorPacksContainer;
defaultBehaviorPackFolder;
skinPacksContainer;
defaultSkinPackFolder;
personaPacksContainer;
defaultPersonaPackFolder;
designPacksContainer;
defaultDesignPackFolder;
projectItemAccessoryFolder;
#packs = [];
#containerFiles = [];
defaultWorldFolder;
#defaultScriptsFolder;
resourcePacksContainer;
defaultResourcePackFolder;
creationTime;
#items;
#itemsByProjectPath = new Map();
#itemsByType = new Map();
changedFilesSinceLastSaved = {};
#isLoaded = false;
#isInflated = false;
#isProjectFolderEnsured = false;
#useProjectNameInProjectStorage = false;
#accessoryFilePaths;
#accessoryFoldersForFilePaths = null;
#accessoryFolders = null;
_onPropertyChanged = new ste_events_1.EventDispatcher();
_onLoaded = new ste_events_1.EventDispatcher();
_onInflated = new ste_events_1.EventDispatcher();
_onSaved = new ste_events_1.EventDispatcher();
_onNeedsSaveChanged = new ste_events_1.EventDispatcher();
_onItemChanged = new ste_events_1.EventDispatcher();
_onItemContentChanged = new ste_events_1.EventDispatcher();
_onItemAdded = new ste_events_1.EventDispatcher();
_onItemRemoved = new ste_events_1.EventDispatcher();
#isProcessingRelations = false;
#relationsBatchOperId = -1;
#itemsToBeProcessed = 0;
#itemsProcessed = 0;
#pendingProcessingRelationsRequests = [];
variants;
hasInferredFiles = false;
#readOnlySafety = false;
#isVanillaEditSession;
get unknownFiles() {
return [...this._unknownFiles];
}
_unknownFiles = new Set();
addUnknownFile(file) {
this._unknownFiles.add(file);
}
get hasMultiplePacksOfSameType() {
if (this.#hasMultiplePacksOfSameType !== undefined) {
return this.#hasMultiplePacksOfSameType;
}
// Determine if there are multiple packs of the same type
const packTypes = [];
for (const pack of this.#packs) {
if (packTypes[pack.packType] !== undefined) {
this.#hasMultiplePacksOfSameType = true;
return true;
}
else {
packTypes[pack.packType] = 1;
}
}
this.#hasMultiplePacksOfSameType = false;
return false;
}
get readOnlySafety() {
return this.#readOnlySafety;
}
set readOnlySafety(newReadOnly) {
this.#readOnlySafety = newReadOnly;
if (this.#projectFolder) {
this.#projectFolder.storage.readOnly = this.#readOnlySafety;
}
}
get creatorTools() {
return this.#creatorTools;
}
/**
* Get the project data for persistence.
* This includes chat session and other project metadata.
*/
get projectData() {
return this.#data;
}
get role() {
if (this.#data.role === undefined) {
return IProjectData_1.ProjectRole.general;
}
return this.#data.role;
}
set role(newRole) {
this.#data.role = newRole;
}
get errorState() {
return this.#errorState;
}
get errorMessage() {
return this.#errorMessage;
}
get preferencesFile() {
return this.#preferencesFile;
}
get accessoryFolders() {
return this.#accessoryFolders;
}
set accessoryFolders(folders) {
this.#accessoryFolders = folders;
}
get accessoryFilePaths() {
return this.#accessoryFilePaths;
}
set accessoryFilePaths(files) {
this.#accessoryFilePaths = files;
}
// This property is a maintained and updated "in development" info set
// that contains errors and validation information useful while a project is
// in develpoment. For other validator suites, instantiate a ProjectInfoSet
// with this project in its constructor
get indevInfoSet() {
if (!this.#indevInfoSet) {
this.#indevInfoSet = new ProjectInfoSet_1.default(this, IProjectInfoData_1.ProjectInfoSuite.defaultInDevelopment);
}
return this.#indevInfoSet;
}
get collapsedStoragePaths() {
if (!this.#data.collapsedStoragePaths) {
this.#data.collapsedStoragePaths = [];
}
return this.#data.collapsedStoragePaths;
}
set collapsedStoragePaths(newCollapsedPaths) {
this.#data.collapsedStoragePaths = newCollapsedPaths;
}
get packs() {
return this.#packs;
}
hasUnsavedChanges() {
for (const filePath in this.changedFilesSinceLastSaved) {
return true;
}
return false;
}
getBehaviorPackCount() {
let count = 0;
for (const projectItem of this.items) {
if (projectItem.itemType === IProjectItemData_1.ProjectItemType.behaviorPackManifestJson) {
count++;
}
}
return count;
}
getResourcePackCount() {
let count = 0;
for (const projectItem of this.items) {
if (projectItem.itemType === IProjectItemData_1.ProjectItemType.resourcePackManifestJson) {
count++;
}
}
return count;
}
getIsPackFolderManaged() {
let rpCount = 0;
let bpCount = 0;
for (const projectItem of this.items) {
if (projectItem.itemType === IProjectItemData_1.ProjectItemType.behaviorPackManifestJson) {
bpCount++;
}
else if (projectItem.itemType === IProjectItemData_1.ProjectItemType.resourcePackManifestJson) {
rpCount++;
}
}
return bpCount < 2 && rpCount < 2;
}
get key() {
if (this.localFilePath) {
return StorageUtilities_1.default.canonicalizePath(this.localFilePath);
}
if (this.#projectFolder) {
if (this.#projectFolder.name && this.#projectFolder.name.length > 0) {
return this.#projectFolder.name;
}
return StorageUtilities_1.default.canonicalizePath(this.#projectFolder.fullPath);
}
if (this.#preferencesFile) {
return StorageUtilities_1.default.canonicalizePath(this.#preferencesFile.name);
}
return this.title;
}
get containerName() {
if (this.localFilePath) {
return StorageUtilities_1.default.getLeafName(this.localFilePath);
}
if (this.#projectFolder) {
if (this.#projectFolder.name && this.#projectFolder.name.length > 0) {
return this.#projectFolder.name;
}
return StorageUtilities_1.default.getLeafName(this.#projectFolder.fullPath);
}
if (this.#preferencesFile) {
return StorageUtilities_1.default.getBaseFromName(this.#preferencesFile.name);
}
return this.title;
}
get defaultNamespace() {
return this.#data.defaultNamespace;
}
get effectiveDefaultNamespace() {
if (this.#data.defaultNamespace || this.#data.defaultNamespace === "") {
return this.#data.defaultNamespace;
}
return this.effectiveShortName;
}
set defaultNamespace(newDefaultNamespace) {
if (newDefaultNamespace !== this.#data.defaultNamespace) {
this.#data.defaultNamespace = newDefaultNamespace;
this._onPropertyChanged.dispatch(this, "defaultNamespace");
}
}
get scriptEntryPoint() {
if (this.#data.scriptEntryPoint || this.#data.scriptEntryPoint === "") {
return this.#data.scriptEntryPoint;
}
return this.scriptEntryPoint;
}
set scriptEntryPoint(newScriptEntryPoint) {
if (newScriptEntryPoint !== this.#data.scriptEntryPoint) {
this.#data.scriptEntryPoint = newScriptEntryPoint;
this._onPropertyChanged.dispatch(this, "scriptEntryPoint");
}
}
get worldSettings() {
return this.#data.worldSettings;
}
get editorWorldSettings() {
return this.#data.editorWorldSettings;
}
get isMinecraftCreator() {
return this.#data.creator?.toLowerCase() === "minecraft";
}
async getLookupChoices(lookupId) {
return await ProjectLookupUtilities_1.default.getLookup(this, lookupId);
}
ensureWorldSettings() {
if (this.#data.worldSettings === undefined) {
if (this.creatorTools.worldSettings) {
this.#data.worldSettings = this.creatorTools.worldSettings;
}
else {
this.initializeWorldSettings();
if (this.#data.worldSettings === undefined) {
throw new Error();
}
}
}
return this.#data.worldSettings;
}
ensureEditorWorldSettings() {
if (this.#data.editorWorldSettings === undefined) {
if (this.creatorTools.editorWorldSettings) {
this.#data.editorWorldSettings = this.creatorTools.editorWorldSettings;
}
else {
this.initializeEditorWorldSettings();
if (this.#data.editorWorldSettings === undefined) {
throw new Error();
}
}
}
return this.#data.editorWorldSettings;
}
get usesCustomWorldSettings() {
return this.#data.usesCustomWorldSettings;
}
set usesCustomWorldSettings(newValue) {
this.#data.usesCustomWorldSettings = newValue;
}
get isLoaded() {
return this.#isLoaded;
}
get isInflated() {
return this.#isInflated;
}
get isRelationsProcessed() {
return this.#relationsProcessed;
}
get distBuildFolder() {
return this.#distBuildFolder;
}
set distBuildFolder(folder) {
this.#distBuildFolder = folder;
}
get libFolder() {
return this.#libFolder;
}
set libFolder(folder) {
this.#libFolder = folder;
}
get distScriptsFolder() {
return this.#distBuildScriptsFolder;
}
get libScriptsFolder() {
return this.#libScriptsFolder;
}
get useProjectNameInRootProjectStorage() {
return this.#useProjectNameInProjectStorage;
}
set useProjectNameInRootProjectStorage(newVal) {
this.#useProjectNameInProjectStorage = newVal;
}
get onPropertyChanged() {
return this._onPropertyChanged.asEvent();
}
get onLoaded() {
return this._onLoaded.asEvent();
}
get onInflated() {
return this._onInflated.asEvent();
}
get onSaved() {
return this._onSaved.asEvent();
}
get onNeedsSaveChanged() {
return this._onNeedsSaveChanged.asEvent();
}
get onItemChanged() {
return this._onItemChanged.asEvent();
}
get onItemContentChanged() {
return this._onItemContentChanged.asEvent();
}
get onItemAdded() {
return this._onItemAdded.asEvent();
}
get onItemRemoved() {
return this._onItemRemoved.asEvent();
}
get projectFolderTitle() {
return this.#data.projectFolderTitle;
}
set projectFolderTitle(newTitle) {
this.#data.projectFolderTitle = newTitle;
}
get projectFolder() {
return this.#projectFolder;
}
get accessoryFoldersForFilePaths() {
return this.#accessoryFoldersForFilePaths;
}
get localFolderPath() {
return this.#data.localFolderPath;
}
set localFolderPath(newPath) {
this.#data.localFolderPath = newPath;
}
get mainDeployFolderPath() {
return this.#data.mainDeployFolderPath;
}
set mainDeployFolderPath(newPath) {
this.#data.mainDeployFolderPath = newPath;
}
get localFilePath() {
return this.#data.localFilePath;
}
set localFilePath(newPath) {
this.#data.localFilePath = newPath;
}
get items() {
return this.#items;
}
get gitHubReferences() {
if (this.#data.gitHubReferences === undefined) {
this.#data.gitHubReferences = [];
}
return this.#data.gitHubReferences;
}
async getBehaviorPackScriptsFolder() {
const bpFolder = await this.ensureDefaultBehaviorPackFolder();
return bpFolder.folders["scripts"];
}
async ensureBehaviorPackScriptsFolder() {
const bpFolder = await this.ensureDefaultBehaviorPackFolder();
return bpFolder.ensureFolder("scripts");
}
async getMainScriptsFolder() {
if (!this.#folderStructureLoaded) {
await this.loadFolderStructure();
}
if (this.#projectFolder === undefined || this.#projectFolder === null) {
throw new Error("Unexpectedly could not create project folder");
}
return this.#projectFolder.folders["scripts"];
}
async ensureProjectItemAccessoryFolder() {
if (this.projectItemAccessoryFolder) {
return this.projectItemAccessoryFolder;
}
if (!this.#folderStructureLoaded) {
await this.loadFolderStructure();
}
if (this.#projectFolder === undefined || this.#projectFolder === null) {
throw new Error("Unexpectedly could not create project folder");
}
const defaultDesignFolder = await this.ensureDefaultDesignPackFolder();
this.projectItemAccessoryFolder = defaultDesignFolder.ensureFolder("project_item_data");
return this.projectItemAccessoryFolder;
}
async ensureMainScriptsFolder() {
if (!this.#folderStructureLoaded) {
await this.loadFolderStructure();
}
if (this.#projectFolder === undefined || this.#projectFolder === null) {
throw new Error("Unexpectedly could not create project folder");
}
return this.#projectFolder.ensureFolder("scripts");
}
async ensureScriptGenFolder() {
const scriptsFolder = await this.ensureMainScriptsFolder();
if (!scriptsFolder) {
throw new Error("Unexpectedly could not create a main scripts folder");
}
return scriptsFolder.ensureFolder("_gen");
}
get preferredScriptLanguage() {
if (this.#data.preferredScriptLanguage === undefined ||
this.#data.preferredScriptLanguage === IProjectData_1.ProjectScriptLanguage.typeScript) {
return IProjectData_1.ProjectScriptLanguage.typeScript;
}
return this.#data.preferredScriptLanguage;
}
set preferredScriptLanguage(newLanguage) {
this.#data.preferredScriptLanguage = newLanguage;
}
get scriptVersion() {
if (this.#data.scriptVersion === undefined) {
return IProjectData_1.ProjectScriptVersion.latestStable;
}
return this.#data.scriptVersion;
}
get messages() {
return this.#data.messages;
}
set scriptVersion(newVersion) {
this.#data.scriptVersion = newVersion;
}
get effectiveEditPreference() {
if (this.editPreference === IProjectData_1.ProjectEditPreference.default || !this.editPreference) {
if (this.creatorTools.editPreference === ICreatorToolsData_1.CreatorToolsEditPreference.raw) {
return IProjectData_1.ProjectEditPreference.raw;
}
else if (this.creatorTools.editPreference === ICreatorToolsData_1.CreatorToolsEditPreference.editors) {
return IProjectData_1.ProjectEditPreference.editors;
}
else if (this.creatorTools.editPreference === ICreatorToolsData_1.CreatorToolsEditPreference.summarized) {
if (this.isVanillaEditSession) {
return IProjectData_1.ProjectEditPreference.editors;
}
return IProjectData_1.ProjectEditPreference.summarized;
}
return IProjectData_1.ProjectEditPreference.editors;
}
return this.editPreference;
}
get editPreference() {
if (this.#data.editPreference === undefined) {
return IProjectData_1.ProjectEditPreference.default;
}
return this.#data.editPreference;
}
set editPreference(newEditPreference) {
this.#data.editPreference = newEditPreference;
}
get contentsModified() {
let val = this.#data.contentsModified;
if (val === null) {
return null;
}
if (!(val instanceof Date)) {
val = new Date(val);
}
return val;
}
get created() {
let val = this.#data.created;
if (!val) {
return null;
}
if (!(val instanceof Date)) {
val = new Date(val);
}
return val;
}
set created(value) {
this.#data.created = value;
}
get lastOpened() {
let val = this.#data.lastOpened;
if (!val) {
return null;
}
if (!(val instanceof Date)) {
val = new Date(val);
}
return val;
}
set lastOpened(value) {
this.#data.lastOpened = value;
}
getItemsCopy() {
return this.#items.slice();
}
getItemsByType(itemType) {
let itemsByTypeArr = this.#itemsByType.get(itemType);
if (itemsByTypeArr) {
return itemsByTypeArr;
}
itemsByTypeArr = [];
for (const item of this.#items) {
if (item.itemType === itemType) {
itemsByTypeArr.push(item);
}
}
this.#itemsByType.set(itemType, itemsByTypeArr);
return itemsByTypeArr;
}
initializeWorldSettings() {
if (this.#data.worldSettings === undefined) {
this.#data.worldSettings = {
gameType: WorldLevelDat_1.GameType.creative,
generator: WorldLevelDat_1.Generator.infinite,
randomSeed: "2000",
isEditor: false,
backupType: IWorldSettings_1.BackupType.every5Minutes,
useCustomSettings: false,
};
this.ensureDefaultWorldName();
}
}
ensureDefaultWorldName() {
if (this.worldSettings && this.worldSettings.name === undefined) {
this.worldSettings.name = this.name + " " + Utilities_1.default.getDateStr(new Date());
}
}
initializeEditorWorldSettings() {
if (this.#data.editorWorldSettings === undefined) {
this.#data.editorWorldSettings = {
gameType: WorldLevelDat_1.GameType.creative,
generator: WorldLevelDat_1.Generator.infinite,
randomSeed: "2000",
isEditor: true,
backupType: IWorldSettings_1.BackupType.every5Minutes,
useCustomSettings: false,
};
this.ensureDefaultEditorWorldName();
}
}
ensureDefaultEditorWorldName() {
if (this.editorWorldSettings && this.editorWorldSettings.name === undefined) {
this.editorWorldSettings.name = this.name + " " + Utilities_1.default.getDateStr(new Date());
this.save();
}
}
addMessage(message, context, operation, type, topic) {
if (this.#data.messages === undefined) {
this.#data.messages = [];
}
if (type === undefined) {
type = Status_1.StatusType.message;
}
const messageCanon = message.trim().toLowerCase();
if (messageCanon.length > 1) {
const status = {
time: new Date(),
message: message,
context: context,
operation: operation,
topic: topic,
type: type,
};
this.#data.messages.push(status);
}
}
appendErrors(errorable, operation) {
if (!errorable.errorMessages) {
return;
}
for (const err of errorable.errorMessages) {
this.creatorTools.notifyStatusUpdate(err.message, Status_1.StatusTopic.general);
this.addMessage(err.message, err.context, operation, Status_1.StatusType.message);
}
}
removeItem(item) {
const newArr = [];
for (let i = 0; i < this.items.length; i++) {
if (this.items[i] !== item) {
newArr.push(this.items[i]);
}
}
const path = ProjectUtilities_1.default.canonicalizeStoragePath(item.projectPath);
if (!Utilities_1.default.isUsableAsObjectKey(path)) {
return;
}
this.#itemsByProjectPath.delete(path);
this.#itemsByType.delete(item.itemType);
this.#items = newArr;
const newDataArr = [];
for (let i = 0; i < this.#data.items.length; i++) {
if (this.#data.items[i].projectPath !== item.projectPath) {
newDataArr.push(this.#data.items[i]);
}
}
this.#data.items = newDataArr;
this.#indevInfoSetNeedsUpdating = true;
this._onItemRemoved.dispatch(this, item);
}
updateContentsModified() {
this.#data.contentsModified = new Date();
}
get modified() {
if (this.#preferencesFile != null && this.#preferencesFile.latestModified != null) {
if (this.contentsModified != null && this.contentsModified > this.#preferencesFile.latestModified) {
return this.contentsModified;
}
return this.#preferencesFile.latestModified;
}
else {
return this.contentsModified;
}
}
get effectiveShowHiddenItems() {
if (this.#data.showHiddenItems === true ||
this.effectiveEditPreference === IProjectData_1.ProjectEditPreference.raw ||
this.effectiveEditPreference === IProjectData_1.ProjectEditPreference.editors) {
return true;
}
return false;
}
get showDevFiles() {
return this.#data.showDevFiles === true;
}
set showDevFiles(show) {
if (show !== this.showDevFiles) {
this.#data.showDevFiles = show;
this._onPropertyChanged.dispatch(this, "showDevFiles");
}
}
get showHiddenItems() {
if (this.#data.showHiddenItems === true) {
return true;
}
return false;
}
set showHiddenItems(showItems) {
if (showItems !== this.showHiddenItems) {
this.#data.showHiddenItems = showItems;
this._onPropertyChanged.dispatch(this, "showHiddenItems");
}
}
get showFunctions() {
if (this.#data.showFunctions === undefined) {
return true;
}
return this.#data.showFunctions;
}
set showFunctions(showFunctions) {
if (showFunctions !== this.showFunctions) {
this.#data.showFunctions = showFunctions;
this._onPropertyChanged.dispatch(this, "showFunctions");
}
}
get showAssets() {
if (this.#data.showAssets === undefined) {
return true;
}
return this.#data.showAssets;
}
set showAssets(showAssets) {
if (showAssets !== this.showAssets) {
this.#data.showAssets = showAssets;
this._onPropertyChanged.dispatch(this, "showAssets");
}
}
get showTypes() {
if (this.#data.showTypes === undefined) {
return true;
}
return this.#data.showTypes;
}
set showTypes(showTypes) {
if (showTypes !== this.showTypes) {
this.#data.showTypes = showTypes;
this._onPropertyChanged.dispatch(this, "showTypes");
}
}
get name() {
return this.#data.name;
}
get simplifiedName() {
return ProjectUtilities_1.default.getSimplifiedProjectName(this.#data.name);
}
set name(newName) {
this.#data.name = newName;
}
get lastMapDeployedHash() {
return this.#data.lastMapDeployedHash;
}
get lastMapDeployedDate() {
return this.#data.lastMapDeployedDate;
}
set lastMapDeployedHash(newValue) {
this.#data.lastMapDeployedHash = newValue;
}
set lastMapDeployedDate(newValue) {
this.#data.lastMapDeployedDate = newValue;
}
get deployWorldId() {
if (!this.#data.deployWorldId) {
this.#data.deployWorldId = Utilities_1.default.createUuid();
}
return this.#data.deployWorldId;
}
set deployWorldId(newValue) {
this.#data.deployWorldId = newValue;
}
get previewImageBase64() {
return this.#data.previewImageBase64;
}
set previewImageBase64(newValue) {
this.#data.previewImageBase64 = newValue;
}
get effectiveCreator() {
if (this.#data.creator && this.#data.creator.length > 0) {
return this.#data.creator;
}
if (this.creatorTools.creator && this.creatorTools.creator.length > 0) {
return this.creatorTools.creator;
}
return "contoso";
}
get effectiveShortName() {
if (this.#data.shortName && this.#data.shortName.length > 0) {
return this.#data.shortName;
}
if (this.effectiveCreator.length > 0 && this.#data.name && this.#data.name.length > 0) {
return ProjectUtilities_1.default.getSuggestedProjectShortName(this.effectiveCreator, this.#data.name);
}
return "cont_game";
}
get shortName() {
return this.#data.shortName;
}
set shortName(newShortName) {
if (this.#data.shortName !== newShortName) {
this.#data.shortName = newShortName;
this._onPropertyChanged.dispatch(this, "shortName");
}
}
get creator() {
return this.#data.creator;
}
set creator(newCreator) {
if (this.#data.creator !== newCreator) {
this.#data.creator = newCreator;
this._onPropertyChanged.dispatch(this, "creator");
}
}
get title() {
if (this.#data.title) {
return this.#data.title;
}
return this.name;
}
set title(newTitle) {
if (this.#data.title !== newTitle) {
this.#data.title = newTitle;
this._onPropertyChanged.dispatch(this, "title");
}
}
get track() {
return this.#data.track;
}
set track(newTrack) {
if (newTrack !== this.#data.track) {
this.#data.track = newTrack;
this._onPropertyChanged.dispatch(this, "track");
}
}
get effectiveTrack() {
if (this.#data.track !== undefined) {
return this.#data.track;
}
return this.#creatorTools.effectiveTrack;
}
set originalFullPath(newOriginalPath) {
if (this.#data.originalFullPath !== newOriginalPath) {
this.#data.originalFullPath = newOriginalPath;
this._onPropertyChanged.dispatch(this, "originalFullPath");
}
}
get originalFullPath() {
return this.#data.originalFullPath;
}
set originalFileList(newFileList) {
if (this.#data.originalFileList !== newFileList) {
this.#data.originalFileList = newFileList;
this._onPropertyChanged.dispatch(this, "originalFileList");
}
}
get originalFileList() {
return this.#data.originalFileList;
}
set originalGitHubOwner(newGitHubOwner) {
if (this.#data.originalGitHubOwner !== newGitHubOwner) {
this.#data.originalGitHubOwner = newGitHubOwner;
this._onPropertyChanged.dispatch(this, "originalGitHubOwner");
}
}
set originalGalleryId(newGalleryId) {
if (this.#data.originalGalleryId !== newGalleryId) {
this.#data.originalGalleryId = newGalleryId;
this._onPropertyChanged.dispatch(this, "originalGalleryId");
}
}
get originalGalleryId() {
return this.#data.originalGalleryId;
}
set originalSampleId(newSampleId) {
if (this.#data.originalSampleId !== newSampleId) {
this.#data.originalSampleId = newSampleId;
this._onPropertyChanged.dispatch(this, "originalSampleId");
}
}
get originalSampleId() {
return this.#data.originalSampleId;
}
get originalGitHubOwner() {
return this.#data.originalGitHubOwner;
}
set originalGitHubFolder(newGitHubFolder) {
if (this.#data.originalGitHubFolder !== newGitHubFolder) {
this.#data.originalGitHubFolder = newGitHubFolder;
this._onPropertyChanged.dispatch(this, "originalGitHubFolder");
}
}
get originalGitHubFolder() {
return this.#data.originalGitHubFolder;
}
set originalGitHubRepoName(newGitHubRepoName) {
if (this.#data.originalGitHubRepoName !== newGitHubRepoName) {
this.#data.originalGitHubRepoName = newGitHubRepoName;
this._onPropertyChanged.dispatch(this, "originalGitHubRepoName");
}
}
get originalGitHubRepoName() {
return this.#data.originalGitHubRepoName;
}
set originalGitHubBranch(newGitHubBranch) {
if (this.#data.originalGitHubBranch !== newGitHubBranch) {
this.#data.originalGitHubBranch = newGitHubBranch;
this._onPropertyChanged.dispatch(this, "originalGitHubBranch");
}
}
get originalGitHubBranch() {
return this.#data.originalGitHubBranch;
}
set gitHubOwner(newGitHubOwner) {
if (this.#data.gitHubOwner !== newGitHubOwner) {
this.#data.gitHubOwner = newGitHubOwner;
this._onPropertyChanged.dispatch(this, "gitHubOwner");
}
}
get gitHubOwner() {
return this.#data.gitHubOwner;
}
set gitHubFolder(newGitHubFolder) {
if (this.#data.gitHubFolder !== newGitHubFolder) {
this.#data.gitHubFolder = newGitHubFolder;
this._onPropertyChanged.dispatch(this, "gitHubFolder");
}
}
get gitHubFolder() {
return this.#data.gitHubFolder;
}
set gitHubRepoName(newGitHubRepoName) {
if (this.#data.gitHubRepoName !== newGitHubRepoName) {
this.#data.gitHubRepoName = newGitHubRepoName;
this._onPropertyChanged.dispatch(this, "gitHubRepoName");
}
}
get gitHubRepoName() {
return this.#data.gitHubRepoName;
}
set gitHubBranch(newGitHubBranch) {
if (this.#data.gitHubBranch !== newGitHubBranch) {
this.#data.gitHubBranch = newGitHubBranch;
this._onPropertyChanged.dispatch(this, "gitHubBranch");
}
}
get gitHubBranch() {
return this.#data.gitHubBranch;
}
get description() {
return this.#data.description;
}
set description(newDescription) {
if (this.#data.description !== newDescription) {
this.#data.description = newDescription;
this._onPropertyChanged.dispatch(this, "description");
}
}
async applyDescription(newTitle) {
this.title = newTitle;
if (this.editPreference === IProjectData_1.ProjectEditPreference.summarized && this.defaultBehaviorPackUniqueId) {
for (const projectItem of this.items) {
const itemFile = projectItem.primaryFile;
if (itemFile && projectItem.itemType === IProjectItemData_1.ProjectItemType.behaviorPackManifestJson) {
const manifestJson = await BehaviorManifestDefinition_1.default.ensureOnFile(itemFile);
if (manifestJson &&
manifestJson.definition &&
Utilities_1.default.uuidEqual(manifestJson.definition.header.uuid, this.defaultBehaviorPackUniqueId)) {
const header = manifestJson.ensureHeader(this.title, this.description);
header.name = newTitle;
await manifestJson.save();
}
}
}
}
}
get autoDeploymentMode() {
if (this.#data.autoDeploymentMode === undefined) {
return 0;
}
return this.#data.autoDeploymentMode;
}
set autoDeploymentMode(newMode) {
if (this.#data.autoDeploymentMode !== newMode) {
this.#data.autoDeploymentMode = newMode;
this._onPropertyChanged.dispatch(this, "autoDeploymentMode");
}
}
get versionAsArray() {
let vmj = this.#data.versionMajor;
if (vmj === undefined) {
vmj = 0;
}
let vmi = this.#data.versionMinor;
if (vmi === undefined) {
vmi = 0;
}
let vmp = this.#data.versionPatch;
if (vmp === undefined) {
vmp = 0;
}
return [vmj, vmi, vmp];
}
get versionAsString() {
let vmj = this.#data.versionMajor;
if (vmj === undefined) {
vmj = 0;
}
let vmi = this.#data.versionMinor;
if (vmi === undefined) {
vmi = 0;
}
let vmp = this.#data.versionPatch;
if (vmp === undefined) {
vmp = 0;
}
return vmj + "." + vmi + "." + vmp;
}
get versionMajor() {
return this.#data.versionMajor;
}
set versionMajor(newVersion) {
if (this.#data.versionMajor !== newVersion) {
this.#data.versionMajor = newVersion;
this._onPropertyChanged.dispatch(this, "versionMajor");
}
}
get versionMinor() {
return this.#data.versionMinor;
}
set versionMinor(newVersion) {
if (this.#data.versionMinor !== newVersion) {
this.#data.versionMinor = newVersion;
this._onPropertyChanged.dispatch(this, "versionMinor");
}
}
get ve