@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
1,205 lines (1,197 loc) • 50.4 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const BlockType_1 = require("./BlockType");
const BlockBaseType_1 = require("./BlockBaseType");
const MinecraftUtilities_1 = require("./MinecraftUtilities");
const Log_1 = require("./../core/Log");
const HttpStorage_1 = require("../storage/HttpStorage");
const CartoApp_1 = require("./../app/CartoApp");
const Utilities_1 = require("../core/Utilities");
const NpmModule_1 = require("../devproject/NpmModule");
const ContentIndex_1 = require("../core/ContentIndex");
const Project_1 = require("../app/Project");
const IProjectItemData_1 = require("../app/IProjectItemData");
const StorageUtilities_1 = require("../storage/StorageUtilities");
const ICartoData_1 = require("../app/ICartoData");
const BlocksCatalogDefinition_1 = require("./BlocksCatalogDefinition");
const TerrainTextureCatalogDefinition_1 = require("./TerrainTextureCatalogDefinition");
const SoundDefinitionCatalogDefinition_1 = require("./SoundDefinitionCatalogDefinition");
const ItemTextureCatalogDefinition_1 = require("./ItemTextureCatalogDefinition");
const ZipStorage_1 = require("../storage/ZipStorage");
class Database {
static get defaultBlockBaseType() {
if (Database._defaultBlockBaseType === undefined) {
Database._defaultBlockBaseType = Database.ensureBlockBaseType("block");
}
return Database._defaultBlockBaseType;
}
static async ensureFormLoadedByPath(path) {
const lastSlash = path.lastIndexOf("/");
if (lastSlash >= 0) {
return await Database.ensureFormLoaded(path.substring(0, lastSlash), path.substring(lastSlash + 1));
}
return undefined;
}
static async ensureFormLoaded(subFolder, name) {
name = name.toLowerCase();
if (Database.uxCatalog[name] !== undefined) {
return Database.uxCatalog[name];
}
let path = CartoApp_1.default.contentRoot + "data/forms/";
if (subFolder) {
path += subFolder + "/";
}
if (Database.local) {
const storage = await Database.local.createStorage(path);
if (storage) {
await storage.rootFolder.load();
const file = storage.rootFolder.files[name + ".form.json"];
if (file) {
await file.loadContent();
return StorageUtilities_1.default.getJsonObject(file);
}
Log_1.default.fail("Could not load file locally for '" + (subFolder ? subFolder + "/" : "") + name + "'.");
return undefined;
}
}
else {
try {
const response = await axios_1.default.get(path + name + ".form.json");
Database.uxCatalog[(subFolder ? subFolder + "." : "") + name] = response.data;
Database.loadedFormCount++;
return response.data;
}
catch {
Log_1.default.fail("Could not load UX file for '" + (subFolder ? subFolder + "/" : "") + name + "'.");
}
}
return undefined;
}
static async getFormsFolder(subFolder) {
if (this.formsFolders[subFolder]) {
return this.formsFolders[subFolder];
}
const folderPath = "data/forms/" + subFolder + "/";
if (Database.local) {
const storage = await Database.local.createStorage(folderPath);
if (storage) {
await storage.rootFolder.load();
this.formsFolders[subFolder] = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + folderPath);
await storage.rootFolder.load();
this.formsFolders[subFolder] = storage.rootFolder;
}
return this.formsFolders[subFolder];
}
static getFormByPath(path) {
const lastSlash = path.lastIndexOf("/");
if (lastSlash >= 0) {
return Database.getForm(path.substring(0, lastSlash), path.substring(lastSlash + 1));
}
return undefined;
}
static getForm(subFolder, name) {
name = name.toLowerCase();
return Database.uxCatalog[(subFolder ? subFolder + "." : "") + name];
}
static getBlockType(name) {
name = MinecraftUtilities_1.default.canonicalizeName(name);
const blockType = Database.blockTypes[name];
return blockType;
}
static populateBlockTypesByLegacyId() {
this._blockTypesByLegacyId = [];
for (const blockTypeName in this.blockTypes) {
const blockType = this.blockTypes[blockTypeName];
if (blockType.numericId !== undefined) {
Log_1.default.assert(this._blockTypesByLegacyId[blockType.numericId] === undefined, "Multiple block types registered for the same ID:" + blockType.id);
this._blockTypesByLegacyId[blockType.numericId] = blockType;
}
}
}
static async getModuleDescriptor(moduleId) {
if (Database.moduleDescriptors[moduleId]) {
return Database.moduleDescriptors[moduleId];
}
try {
const response = await axios_1.default.get("https://registry.npmjs.org/" + moduleId);
Database.moduleDescriptors[moduleId] = new NpmModule_1.default(response.data);
}
catch {
Log_1.default.fail("Could not load registry for '" + moduleId + "'");
}
return Database.moduleDescriptors[moduleId];
}
static async getLatestMinecraftRetailVersion() {
const moduleDescriptor = await this.getModuleDescriptor("@minecraft/server");
if (!moduleDescriptor || !moduleDescriptor.latestRetailVersion) {
return "1.21.0";
}
return moduleDescriptor.latestRetailVersion;
}
static async isRecentVersionFromVersionArray(version) {
if (version === undefined || version.length !== 3) {
return false;
}
const ver = await this.getLatestVersionInfo(ICartoData_1.MinecraftTrack.main);
if (!ver) {
return false;
}
const verArr = MinecraftUtilities_1.default.getVersionArrayFrom(ver);
if (!verArr || verArr.length < 3) {
return false;
}
const majorVersion = verArr[0];
const minorVersion = verArr[1];
if (version[0] < majorVersion) {
return false;
}
if (majorVersion === version[0] && minorVersion - version[1] > 1) {
return false;
}
return true;
}
static async ensureCreatorToolsIngameProject() {
if (Database._creatorToolsIngameProject) {
return Database._creatorToolsIngameProject;
}
await Database.loadContent();
if (Database.contentFolder === null || !CartoApp_1.default.carto) {
Log_1.default.unexpectedContentState();
return undefined;
}
const file = Database.contentFolder.ensureFile("creator_tools_ingame.mcaddon");
await file.loadContent();
if (file.content instanceof Uint8Array) {
Database._creatorToolsIngameProject = new Project_1.default(CartoApp_1.default.carto, "Creator Tools", null);
const projectFolder = await Database._creatorToolsIngameProject.ensureProjectFolder();
const folder = projectFolder.ensureFolder("addons");
const contentFile = folder.ensureFile(file.name);
contentFile.setContent(file.content);
contentFile.saveContent();
const relPath = contentFile.getFolderRelativePath(Database._creatorToolsIngameProject.projectFolder);
if (relPath !== undefined) {
Database._creatorToolsIngameProject.ensureItemByProjectPath(relPath, IProjectItemData_1.ProjectItemStorageType.singleFile, file.name, IProjectItemData_1.ProjectItemType.MCAddon, undefined, IProjectItemData_1.ProjectItemCreationType.normal);
await Database._creatorToolsIngameProject.inferProjectItemsFromZipFile(relPath, contentFile, false);
}
return Database._creatorToolsIngameProject;
}
return undefined;
}
static async getLatestVersionInfo(track, force) {
if (track === ICartoData_1.MinecraftTrack.edu) {
return Database.minecraftEduVersion;
}
if (track === ICartoData_1.MinecraftTrack.eduPreview) {
return Database.minecraftEduPreviewVersion;
}
if (track === ICartoData_1.MinecraftTrack.preview && Database.latestPreviewVersion && !force) {
return Database.latestPreviewVersion;
}
if (track === ICartoData_1.MinecraftTrack.main && Database.latestVersion && !force) {
return Database.latestVersion;
}
let minecraftInfoResponse = undefined;
let versionUrl = "https://raw.githubusercontent.com/Mojang/bedrock-samples/main/version.json";
if (track === ICartoData_1.MinecraftTrack.preview) {
versionUrl = "https://raw.githubusercontent.com/Mojang/bedrock-samples/preview/version.json";
}
try {
minecraftInfoResponse = await axios_1.default.get(versionUrl);
}
catch (e) {
console.log("Could not access Minecraft version details." + e);
throw new Error(e.toString());
}
let latestVersionIndex = 0;
let latestVerStr = "";
try {
if (minecraftInfoResponse === undefined || minecraftInfoResponse.data === undefined) {
throw new Error("Unexpected empty response.");
}
const responseJson = JSON.parse(JSON.stringify(minecraftInfoResponse.data));
if (!responseJson) {
throw new Error("Improperly formatted response (source: " + minecraftInfoResponse.data + ")");
}
for (const verId in responseJson) {
const ver = responseJson[verId].version;
if (ver) {
const isPreview = Database.getVersionIsPreview(ver); // version ends with .20 or higher
const versionIndex = Database.getVersionIndexFromVersionStr(ver);
if (versionIndex > 0 &&
versionIndex > latestVersionIndex &&
((isPreview && track === ICartoData_1.MinecraftTrack.preview) || (!isPreview && track === ICartoData_1.MinecraftTrack.main))) {
latestVersionIndex = versionIndex;
// re-constitute the version number ourselves
const verNums = ver.split(".");
latestVerStr =
verNums[0] + "." + verNums[1] + "." + verNums[2] + "." + Utilities_1.default.frontPadToLength(verNums[3], 2, "0");
}
}
}
}
catch (e) {
Log_1.default.error("Could not process Minecraft version details." + e);
throw new Error(e.toString());
}
if (latestVerStr && latestVerStr.length > 0) {
if (track === ICartoData_1.MinecraftTrack.preview) {
Database.latestPreviewVersion = latestVerStr;
}
else {
Database.latestVersion = latestVerStr;
}
}
return latestVerStr;
}
static getVersionIsPreview(ver) {
const verNums = ver.split(".");
if (verNums.length !== 4) {
return false;
}
for (let j = 0; j < verNums.length; j++) {
if (!Utilities_1.default.isNumeric(verNums[j])) {
return false;
}
}
return parseInt(verNums[3]) > 19;
}
static getVersionIndexFromVersionStr(ver) {
const verNums = ver.split(".");
if (verNums.length !== 4) {
return -1;
}
for (let j = 0; j < verNums.length; j++) {
if (!Utilities_1.default.isNumeric(verNums[j])) {
return -1;
}
}
const versionIndex = parseInt(verNums[0]) * 16777216 +
parseInt(verNums[1]) * 65536 +
parseInt(verNums[2]) * 256 +
parseInt(verNums[3]);
return versionIndex;
}
static getBlockTypeByLegacyId(id) {
if (!this._blockTypesByLegacyId) {
this._blockTypesByLegacyId = [];
this.populateBlockTypesByLegacyId();
}
const result = this._blockTypesByLegacyId[id];
// Log.assert(result !== undefined);
return result;
}
static getMatchingBlocks(searchTerm) {
searchTerm = searchTerm.toLowerCase().trim();
searchTerm = searchTerm.replace(/_/gi, " ");
const searchTerms = searchTerm.split(" ");
let exactMatch = undefined;
let matches = [];
for (const name in this.blockTypes) {
const bt = this.blockTypes[name];
const titleCanon = bt.title.toLowerCase();
if (titleCanon === searchTerm && exactMatch === undefined) {
exactMatch = bt;
}
else {
for (let i = 0; i < searchTerms.length; i++) {
if (titleCanon.indexOf(searchTerms[i]) >= 0) {
matches.push(bt);
break;
}
}
}
}
if (exactMatch !== undefined) {
const newMatches = [exactMatch];
for (let i = 0; i < matches.length; i++) {
newMatches.push(matches[i]);
}
matches = newMatches;
}
return matches;
}
static ensureBlockType(name) {
name = MinecraftUtilities_1.default.canonicalizeName(name);
let blockType = Database.blockTypes[name];
if (blockType == null && Database.catalog != null) {
blockType = new BlockType_1.default(name);
Database.blockTypes[name] = blockType;
blockType.data = {
name: name,
};
}
return blockType;
}
static ensureBlockBaseType(name) {
name = MinecraftUtilities_1.default.canonicalizeName(name);
let blockBaseType = Database.blockBaseTypes[name];
if (blockBaseType == null) {
blockBaseType = new BlockBaseType_1.default(name);
Database.blockBaseTypes[name] = blockBaseType;
}
return blockBaseType;
}
static async loadContent() {
if (Database.contentFolder !== null) {
return;
}
if (Database.local) {
const storage = await Database.local.createStorage("data/content/");
if (storage) {
await storage.rootFolder.load();
Database.contentFolder = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "data/content/");
await storage.rootFolder.load();
Database.contentFolder = storage.rootFolder;
}
}
static async initSnippetsFolder() {
if (Database.snippetsFolder !== null) {
return;
}
if (this._isLoadingSnippets) {
const pendingLoad = this._pendingLoadSnippetsRequests;
const prom = (resolve, reject) => {
pendingLoad.push(resolve);
};
await new Promise(prom);
return;
}
else {
this._isLoadingSnippets = true;
let folder;
if (Database.local) {
const storage = await Database.local.createStorage("data/snippets/");
if (storage) {
folder = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "data/snippets/");
folder = storage.rootFolder;
}
if (folder === undefined) {
return;
}
await folder.load();
for (const fileName in folder.files) {
const file = folder.files[fileName];
if (file) {
await file.loadContent();
}
}
Database.snippetsFolder = folder;
this._isLoadingSnippets = false;
const pendingLoad = this._pendingLoadSnippetsRequests;
this._pendingLoadSnippetsRequests = [];
for (const prom of pendingLoad) {
prom(undefined);
}
}
}
static itemMatchesSearch(item, searchString) {
if (!searchString || searchString.length < 3) {
return true;
}
const searchKey = searchString.toLowerCase();
if ((item.title && item.title.toLowerCase().indexOf(searchKey) >= 0) ||
(item.description && item.description.toLowerCase().indexOf(searchKey) >= 0)) {
return true;
}
if (item.topics) {
for (const topic of item.topics) {
if (topic.toLowerCase().indexOf(searchKey) >= 0) {
return true;
}
}
}
return false;
}
static async getSnippet(sampleSet, snippetId) {
if (!Database.snippetsFolder) {
await Database.initSnippetsFolder();
}
if (!Database.snippetsFolder) {
return undefined;
}
if (Database.snippetsFolder !== null && Database.snippetsFolder.files) {
const file = Database.snippetsFolder.files[sampleSet + ".json"];
if (file) {
const snipSet = StorageUtilities_1.default.getJsonObject(file);
if (snipSet && snipSet[snippetId]) {
return snipSet[snippetId];
}
}
}
return undefined;
}
static async getAddonsDocs() {
if (!Database.addonsDocs) {
Database.addonsDocs = await Database.getMetadataObject("/doc_modules/addons.json");
}
return Database.addonsDocs;
}
static async getBiomesMetadata() {
if (!Database.biomesMetadata) {
Database.biomesMetadata = await Database.getMetadataObject("/vanilladata_modules/mojang-biomes.json");
}
return Database.biomesMetadata;
}
static getVanillaBlocksCatalogDirect() {
return this.blocksCatalog;
}
static async getVanillaBlocksCatalog() {
if (!Database.blocksCatalog) {
const file = await Database.getPreviewVanillaFile("/resource_pack/blocks.json");
if (file) {
const blockCat = new BlocksCatalogDefinition_1.default();
blockCat.file = file;
await blockCat.load();
this.blocksCatalog = blockCat;
}
}
return this.blocksCatalog;
}
static getVanillaTerrainTexturesCatalogDirect() {
return this.terrainTextureCatalog;
}
static async getVanillaTerrainTexturesCatalog() {
if (!Database.terrainTextureCatalog) {
const file = await Database.getPreviewVanillaFile("/resource_pack/textures/terrain_texture.json");
if (file) {
const terrainCat = new TerrainTextureCatalogDefinition_1.default();
terrainCat.file = file;
await terrainCat.load();
Database.terrainTextureCatalog = terrainCat;
}
}
return Database.terrainTextureCatalog;
}
static async getVanillaItemTexturesCatalog() {
if (!Database.itemTextureCatalog) {
const file = await Database.getPreviewVanillaFile("/resource_pack/textures/item_texture.json");
if (file) {
const itemCat = new ItemTextureCatalogDefinition_1.default();
itemCat.file = file;
await itemCat.load();
Database.itemTextureCatalog = itemCat;
}
}
return Database.itemTextureCatalog;
}
static async getVanillaSoundDefinitionCatalog() {
if (!Database.soundDefinitionCatalog) {
const file = await Database.getPreviewVanillaFile("/resource_pack/sounds/sound_definitions.json");
if (file) {
const soundDefinitionCat = new SoundDefinitionCatalogDefinition_1.default();
soundDefinitionCat.file = file;
await soundDefinitionCat.load();
Database.soundDefinitionCatalog = soundDefinitionCat;
}
}
return Database.soundDefinitionCatalog;
}
static async getBlocksMetadata() {
if (!Database.blocksMetadata) {
Database.blocksMetadata = await Database.getMetadataObject("/vanilladata_modules/mojang-blocks.json");
}
return Database.blocksMetadata;
}
static async getEntitiesMetadata() {
if (!Database.entitiesMetadata) {
Database.entitiesMetadata = await Database.getMetadataObject("/vanilladata_modules/mojang-entities.json");
}
return Database.entitiesMetadata;
}
static async getItemsMetadata() {
if (!Database.itemsMetadata) {
Database.itemsMetadata = await Database.getMetadataObject("/vanilladata_modules/mojang-items.json");
}
return Database.itemsMetadata;
}
static async getMetadataObject(metaPath) {
await Database.loadPreviewMetadataFolder();
if (!Database.previewMetadataFolder) {
return null;
}
const jsonFile = await Database.previewMetadataFolder.getFileFromRelativePath(metaPath);
if (!jsonFile) {
Log_1.default.unexpectedUndefined();
return null;
}
await jsonFile.loadContent();
const jsonObj = StorageUtilities_1.default.getJsonObject(jsonFile);
if (!jsonObj) {
Log_1.default.unexpectedUndefined();
return null;
}
return jsonObj;
}
static async getPreviewVanillaFile(filePath) {
const vanillaFolder = await Database.getPreviewVanillaFolder();
if (!vanillaFolder) {
return null;
}
const jsonFile = await vanillaFolder.getFileFromRelativePath(filePath);
if (!jsonFile) {
Log_1.default.unexpectedUndefined();
return null;
}
await jsonFile.loadContent();
return jsonFile;
}
static async getPreviewVanillaObject(filePath) {
const jsonFile = await Database.getPreviewVanillaFile(filePath);
if (!jsonFile) {
Log_1.default.unexpectedUndefined();
return null;
}
const jsonObj = StorageUtilities_1.default.getJsonObject(jsonFile);
if (!jsonObj) {
Log_1.default.unexpectedUndefined();
return null;
}
return jsonObj;
}
static async loadPreviewMetadataFolder() {
if (!this.previewMetadataFolder) {
if (Database.local) {
const storage = await Database.local.createStorage("res/latest/van/preview/metadata/");
if (storage) {
this.previewMetadataFolder = storage.rootFolder;
}
}
else {
const metadataStorage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "res/latest/van/preview/metadata/");
await metadataStorage.rootFolder.load();
this.previewMetadataFolder = metadataStorage.rootFolder;
}
}
return this.previewMetadataFolder;
}
static async loadReleaseMetadataFolder() {
if (!this.releaseMetadataFolder) {
if (Database.local) {
const storage = await Database.local.createStorage("res/latest/van/release/metadata/");
if (storage) {
this.releaseMetadataFolder = storage.rootFolder;
}
}
else {
const metadataStorage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "res/latest/van/release/metadata/");
await metadataStorage.rootFolder.load();
this.releaseMetadataFolder = metadataStorage.rootFolder;
}
}
return this.releaseMetadataFolder;
}
static async getReleaseVanillaFolder() {
if (Database.releaseVanillaFolder !== null) {
return Database.releaseVanillaFolder;
}
if (Database.local) {
const storage = await Database.local.createStorage("res/latest/van/release/");
if (storage) {
Database.releaseVanillaFolder = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "res/latest/van/release/");
Database.releaseVanillaFolder = storage.rootFolder;
}
if (Database.releaseVanillaFolder) {
await Database.releaseVanillaFolder.load();
}
return Database.releaseVanillaFolder;
}
static async getPreviewVanillaFolder() {
if (Database.previewVanillaFolder !== null) {
return Database.previewVanillaFolder;
}
if (Database.local) {
const storage = await Database.local.createStorage("res/latest/van/preview/");
if (storage) {
Database.previewVanillaFolder = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "res/latest/van/preview/");
Database.previewVanillaFolder = storage.rootFolder;
}
if (Database.previewVanillaFolder) {
await Database.previewVanillaFolder.load();
}
return Database.previewVanillaFolder;
}
static async getSamplesFolder() {
if (Database.samplesFolder !== null) {
return Database.samplesFolder;
}
if (Database.local) {
const storage = await Database.local.createStorage("res/samples/microsoft/minecraft-samples-main/");
if (storage) {
Database.samplesFolder = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "res/samples/microsoft/minecraft-samples-main/");
Database.samplesFolder = storage.rootFolder;
}
if (Database.samplesFolder) {
await Database.samplesFolder.load();
}
return Database.samplesFolder;
}
static async getReleaseVanillaBehaviorPackFolder() {
if (Database.releaseVanillaBehaviorPackFolder !== null) {
return Database.releaseVanillaBehaviorPackFolder;
}
if (Database.local) {
const storage = await Database.local.createStorage("res/latest/van/release/behavior_pack/");
if (storage) {
Database.releaseVanillaBehaviorPackFolder = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "res/latest/van/release/behavior_pack/");
Database.releaseVanillaBehaviorPackFolder = storage.rootFolder;
}
if (Database.releaseVanillaBehaviorPackFolder) {
await Database.releaseVanillaBehaviorPackFolder.load();
}
return Database.releaseVanillaBehaviorPackFolder;
}
static async getReleaseVanillaResourcePackFolder() {
if (Database.releaseVanillaResourcePackFolder !== null) {
return Database.releaseVanillaResourcePackFolder;
}
if (Database.local) {
const storage = await Database.local.createStorage("res/latest/van/release/resource_pack/");
if (storage) {
Database.releaseVanillaResourcePackFolder = storage.rootFolder;
}
}
else {
const storage = new HttpStorage_1.default(CartoApp_1.default.contentRoot + "res/latest/van/release/resource_pack/");
Database.releaseVanillaResourcePackFolder = storage.rootFolder;
}
if (Database.releaseVanillaResourcePackFolder) {
await Database.releaseVanillaResourcePackFolder.load();
}
return Database.releaseVanillaResourcePackFolder;
}
static async loadUx() { }
static getComponentFormField(propertyName) {
if (Database.uxCatalog === undefined || Database.uxCatalog === null) {
Log_1.default.unexpectedNull();
return undefined;
}
throw new Error("Not implemented.");
/*
const componentForms = Database.uxCatalog.forms;
for (const formName in componentForms) {
const form = componentForms[formName];
if (form === undefined) {
break;
}
for (let i = 0; i < form.fields.length; i++) {
const field = form.fields[i];
if (field.id === propertyName || field.altId === propertyName) {
return {
form: form,
field: field,
};
}
}
}
*/
}
static async getSchema(path) {
path = path.toLowerCase();
if (Database.schemaContents[path]) {
return Database.schemaContents[path];
}
const schemaPath = "/" + Database.dataPath + "schemas/" + path;
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(Utilities_1.default.ensureEndsWithSlash(CartoApp_1.default.contentRoot) + Utilities_1.default.ensureNotStartsWithSlash(schemaPath));
Database.schemaContents[path] = response.data;
if (!Database.schemaContents[path]) {
Log_1.default.fail("Could not load schema '" + schemaPath + "'");
}
return Database.schemaContents[path];
}
else if (Database.local) {
const result = await Database.local.readJsonFile(schemaPath);
if (result !== null) {
Database.schemaContents[path] = result;
return Database.schemaContents[path];
}
else {
Log_1.default.fail("Could not load schema '" + schemaPath + "'");
return undefined;
}
}
else {
Log_1.default.fail("Unexpected database config (no database available) when trying to load schema for:" + path);
return undefined;
}
}
catch (e) {
Log_1.default.fail("Could not load Minecraft schema catalog: " + CartoApp_1.default.contentRoot + " - " + schemaPath + " " + e.toString());
return undefined;
}
}
static async loadBetaScriptTypes() {
if (Database.betaTypeDefs) {
return;
}
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(CartoApp_1.default.contentRoot + "data/typedefs.beta.json");
Database.betaTypeDefs = response.data;
}
else if (Database.local) {
const result = await Database.local.readJsonFile("data/typedefs.beta.json");
if (result !== null) {
Database.betaTypeDefs = result;
}
}
}
catch {
Log_1.default.fail("Could not load beta Minecraft types catalog.");
}
}
static async loadStableScriptTypes() {
if (Database.stableTypeDefs) {
return;
}
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(CartoApp_1.default.contentRoot + "data/typedefs.stable.json");
Database.stableTypeDefs = response.data;
}
else if (Database.local) {
const result = await Database.local.readJsonFile("data/typedefs.stable.json");
if (result !== null) {
Database.stableTypeDefs = result;
}
}
}
catch {
Log_1.default.fail("Could not load stable Minecraft types catalog.");
}
}
static async getLibs() {
if (Database.libs) {
return Database.libs;
}
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(CartoApp_1.default.contentRoot + "data/libs.json");
Database.libs = response.data;
}
else if (Database.local) {
const result = await Database.local.readJsonFile("data/libs.json");
if (result !== null) {
Database.libs = result;
}
}
}
catch {
Log_1.default.fail("Could not load libraries catalog.");
}
return Database.libs;
}
static async matchesVanillaPath(path) {
const rpFolder = await Database.getReleaseVanillaResourcePackFolder();
if (rpFolder && rpFolder.folderCount > 0) {
path = Utilities_1.default.ensureStartsWithSlash(path);
const folder = await rpFolder.getFolderFromRelativePath(StorageUtilities_1.default.getFolderPath(path));
if (!folder) {
return false;
}
const exists = await folder.exists();
if (!exists) {
return false;
}
const itemName = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.getLeafName(path)).toLowerCase();
await folder.load();
for (let fileName in folder.files) {
if (fileName && StorageUtilities_1.default.getBaseFromName(fileName).toLowerCase() === itemName) {
return true;
}
}
}
else {
let res = await Database.matchesVanillaPathFromIndex(path);
return res;
}
return false;
}
static async matchesVanillaPathFromIndex(path) {
if (!Database.vanillaContentIndex) {
await this.loadVanillaInfoData();
}
if (!Database.vanillaContentIndex) {
return false;
}
let result = Database.vanillaContentIndex.hasPathMatches(path);
if (!result) {
result = await Database.isVanillaToken(path);
}
if (!result) {
if (!path.startsWith("/resource_pack/") && path.startsWith("/")) {
result = Database.vanillaContentIndex.hasPathMatches("/resource_pack" + path);
if (!result) {
result = await Database.isVanillaToken("/resource_pack" + path);
if (!result) {
if (!path.startsWith("/behavior_pack/")) {
result = Database.vanillaContentIndex.hasPathMatches("/behavior_pack" + path);
if (!result) {
result = await Database.isVanillaToken("/behavior_pack" + path);
}
}
}
}
}
}
return result;
}
static async isVanillaToken(path) {
const matches = await Database.getVanillaMatches(path, true);
if (matches && matches.length > 0) {
return true;
}
return false;
}
static async getVanillaAll(withAnnotation) {
if (!Database.vanillaContentIndex) {
await this.loadVanillaInfoData();
}
if (!Database.vanillaContentIndex) {
return undefined;
}
return Database.vanillaContentIndex.getAll(withAnnotation);
}
static async getVanillaMatches(path, wholeTermSearch, withAnnotation) {
if (!Database.vanillaContentIndex) {
await this.loadVanillaInfoData();
}
if (!Database.vanillaContentIndex) {
return undefined;
}
return await Database.vanillaContentIndex.getMatches(path, wholeTermSearch, withAnnotation);
}
static async getPreviewVanillaMatches(path, wholeTermSearch, withAnnotation) {
if (!Database.previewVanillaContentIndex) {
await this.loadPreviewVanillaInfoData();
}
if (!Database.previewVanillaContentIndex) {
return undefined;
}
return await Database.previewVanillaContentIndex.getMatches(path, wholeTermSearch, withAnnotation);
}
static async getSamplesMatches(path, wholeTermSearch, withAnnotation) {
if (!Database.samplesContentIndex) {
await this.loadSampleInfoData();
}
if (!Database.samplesContentIndex) {
return undefined;
}
return await Database.samplesContentIndex.getMatches(path, wholeTermSearch, withAnnotation);
}
static async loadVanillaInfoData() {
if (Database.vanillaInfoData) {
return;
}
if (this._isLoadingVanilla) {
const pendingLoad = this._pendingLoadVanillaRequests;
const prom = (resolve, reject) => {
pendingLoad.push(resolve);
};
await new Promise(prom);
}
else {
this._isLoadingVanilla = true;
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(CartoApp_1.default.contentRoot + "data/mci/release.mci.json.zip", {
responseType: "arraybuffer",
headers: {
Accept: "application/octet-stream, application/json, text/plain, */*",
},
});
if (response) {
Database.vanillaInfoData = await ZipStorage_1.default.fromZipBytesToJsonObject(response.data);
}
}
else if (Database.local) {
const result = await Database.local.readJsonFile("data/mci/release.mci.json");
if (result !== null) {
Database.vanillaInfoData = result;
}
}
if (Database.vanillaInfoData && Database.vanillaInfoData.index && !Database.vanillaContentIndex) {
Database.vanillaContentIndex = new ContentIndex_1.default();
Database.vanillaContentIndex.loadFromData(Database.vanillaInfoData.index);
}
}
catch {
// Log.fail("Could not load vanilla metadata.");
}
this._isLoadingVanilla = false;
const pendingLoad = this._pendingLoadVanillaRequests;
this._pendingLoadVanillaRequests = [];
for (const prom of pendingLoad) {
prom(undefined);
}
}
}
static async loadPreviewVanillaInfoData() {
if (Database.previewVanillaContentIndex) {
return;
}
if (this._isLoadingPreviewVanilla) {
const pendingLoad = this._pendingLoadPreviewVanillaRequests;
const prom = (resolve, reject) => {
pendingLoad.push(resolve);
};
await new Promise(prom);
}
else {
this._isLoadingPreviewVanilla = true;
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(CartoApp_1.default.contentRoot + "data/mci/preview.mci.json.zip", {
responseType: "arraybuffer",
headers: {
Accept: "application/octet-stream, application/json, text/plain, */*",
},
});
if (response) {
Database.previewVanillaInfoData = await ZipStorage_1.default.fromZipBytesToJsonObject(response.data);
}
}
else if (Database.local) {
const result = await Database.local.readJsonFile("data/mci/preview.mci.json");
if (result !== null) {
Database.previewVanillaInfoData = result;
}
}
if (Database.previewVanillaInfoData &&
Database.previewVanillaInfoData.index &&
!Database.previewVanillaContentIndex) {
Database.previewVanillaContentIndex = new ContentIndex_1.default();
Database.previewVanillaContentIndex.loadFromData(Database.previewVanillaInfoData.index);
}
}
catch {
// Log.fail("Could not load preview vanilla metadata.");
}
this._isLoadingVanilla = false;
const pendingLoad = this._pendingLoadPreviewVanillaRequests;
this._pendingLoadPreviewVanillaRequests = [];
for (const prom of pendingLoad) {
prom(undefined);
}
}
}
static async loadSampleInfoData() {
if (Database.samplesContentIndex) {
return;
}
if (this._isLoadingSamples) {
const pendingLoad = this._pendingLoadSamplesRequests;
const prom = (resolve, reject) => {
pendingLoad.push(resolve);
};
await new Promise(prom);
}
else {
this._isLoadingSamples = true;
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(CartoApp_1.default.contentRoot + "data/mci/minecraft-samples-main.mci.json");
Database.samplesInfoData = response.data;
}
else if (Database.local) {
const result = await Database.local.readJsonFile("data/mci/minecraft-samples-main.mci.json");
if (result !== null) {
Database.samplesInfoData = result;
}
}
if (Database.samplesInfoData && Database.samplesInfoData.index && !Database.samplesContentIndex) {
Database.samplesContentIndex = new ContentIndex_1.default();
Database.samplesContentIndex.loadFromData(Database.samplesInfoData.index);
}
}
catch {
// Log.fail("Could not load preview vanilla metadata.");
}
this._isLoadingSamples = false;
const pendingLoad = this._pendingLoadSamplesRequests;
this._pendingLoadSamplesRequests = [];
for (const prom of pendingLoad) {
prom(undefined);
}
}
}
static async load() {
if (Database.isLoaded) {
return;
}
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios_1.default.get(CartoApp_1.default.contentRoot + "data/mccat.json");
Database.catalog = response.data;
}
else if (Database.local) {
const result = await Database.local.readJsonFile("data/mccat.json");
if (result !== null) {
Database.catalog = result;
// Log.debugAlert("Loaded catalog: " + Database.catalog.blockBaseTypes.length);
}
}
if (Database.catalog !== null) {
for (let i = 0; i < Database.catalog.blockBaseTypes.length; i++) {
const blockBaseTypeData = Database.catalog.blockBaseTypes[i];
const baseTypeName = MinecraftUtilities_1.default.canonicalizeName(blockBaseTypeData.name);
const blockBaseType = new BlockBaseType_1.default(baseTypeName);
blockBaseType.data = blockBaseTypeData;
if (blockBaseTypeData.abstract === undefined || blockBaseTypeData.abstract === false) {
const newBlockType = {
name: blockBaseTypeData.name,
id: blockBaseTypeData.id,
icon: blockBaseTypeData.icon,
mapColor: blockBaseTypeData.mapColor,
shortId: blockBaseTypeData.shortId,
altShortId: blockBaseTypeData.altShortId,
};
const blockType = this.ensureBlockType(baseTypeName);
blockType.data = newBlockType;
blockType.baseType = blockBaseType;
}
if (blockBaseTypeData.variants !== undefined) {
for (let j = 0; j < blockBaseTypeData.variants.length; j++) {
const variantBlockTypeData = blockBaseTypeData.variants[j];
const blockType = this.ensureBlockType(variantBlockTypeData.name);
if (!variantBlockTypeData.id && blockBaseTypeData.id) {
variantBlockTypeData.id = blockBaseTypeData.id;
}
if (!variantBlockTypeData.icon && blockBaseTypeData.icon) {
variantBlockTypeData.icon = blockBaseTypeData.icon;
}
if (!variantBlockTypeData.shortId && blockBaseTypeData.shortId) {
variantBlockTypeData.shortId = blockBaseTypeData.shortId;
}
if (!variantBlockTypeData.altShortId && blockBaseTypeData.altShortId) {
variantBlockTypeData.altShortId = blockBaseTypeData.altShortId;
}
if (!variantBlockTypeData.mapColor && blockBaseTypeData.mapColor) {
variantBlockTypeData.mapColor = blockBaseTypeData.mapColor;
}
blockType.data = variantBlockTypeData;
blockType.baseType = blockBaseType;
}
}
}
}
}
catch {
Log_1.default.fail("Could not load Minecraft types catalog.");
}
/*
try {
// @ts-ignore
if (typeof window !== "undefined") {
const response = await axios.get(CartoApp.contentRoot + "data/javacat.json");
Database.javaBlockTypeData = response.data;
} else if (Database.local) {
const result = await Database.local.readJsonFile("data/javacat.json");
if (result !== null) {
Database.javaBlockTypeData = result as { [id: string]: IJavaBlockTypeData };
}
}
if (Database.javaBlockTypeData) {
for (const blockName in Database.javaBlockTypeData) {
const jtnBlock = Database.javaBlockTypeData[blockName];
jtnBlock.source = blockName;
this.ensureBlockType(blockName).javaData = jtnBlock;
}
}
Database.isLoaded = true;
} catch {
Log.fail("Could not load java catalog.");
}*/
}
}
exports.default = Database;
Database.isLoaded = false;
Database.isScriptTypesLoaded = false;
Database.catalog = null;
Database.loadedFormCount = 0;
Database._creatorToolsIngameProject = null;
Database.uxCatalog = {};
Database.formsFolders = {};
Database.betaTypeDefs = null;
Database.libs = null;
Database.stableTypeDefs = null;
Database.contentFolder = null;
Database.snippetsFolder = null;
Database.previewMetadataFolder = null;
Database.releaseMetadataFolder = null;
Database.previewVanillaFolder = null;
Database.releaseVanillaFolder = null;
Database.samplesFolder = null;
Database.releaseVanillaBehaviorPackFolder = null;
Database.releaseVanillaResourcePackFolder = null;
Database.local = null;
Database.vanillaInfoData = null;
Database.vanillaContentIndex = null;
Database.previewVanillaInfoData = null;
Database.previewVanillaContentIndex = null;
Database.samplesInfoData = null;
Database.samplesContentIndex = null;
Database.addonsDocs = null;
Database.biomesMetadata = null;
Database.blocksMetadata = null;
Database.entitiesMetadata = null;
Database.itemsMetadata = null;
Database.blocksCatalog = null;
Database.itemTextureCatalog = null;
Database.terrainTextureCatalog = null;
Database.soundDefinitionCatalog = null;
Database._isLoadingSnippets = false;
Database._pendingLoadSnippetsRequests = [];
Database._isLoadingVanilla = false;
Database._pendingLoadVanillaRequests = [];
Database._isLoadingPreviewVanilla = false;
Database._pendingLoadPreviewVanillaRequests = [];
Database._isLoadingSamples = false;
Database._pendingLoadSamplesRequests = [];
Database.dataPath = "res/latest/";
Database.minecraftEduVersion = "1.21.0";
Database.minecraftEduPreviewVersion = "1.21.0";
Database.minecraftModuleNames = [
"@minecraft/server-gametest",
"@minecraft/server",
"@minecraft