UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

1,028 lines (1,024 loc) 56.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const Utilities_1 = __importDefault(require("../core/Utilities")); const IField_1 = require("../dataform/IField"); const Database_1 = __importDefault(require("../minecraft/Database")); const LegacyDocumentationDefinition_1 = __importDefault(require("../minecraft/docs/LegacyDocumentationDefinition")); const StorageUtilities_1 = __importDefault(require("../storage/StorageUtilities")); const ContentIndex_1 = require("../core/ContentIndex"); const DataFormUtilities_1 = __importDefault(require("../dataform/DataFormUtilities")); const EntityTypeDefinition_1 = __importDefault(require("../minecraft/EntityTypeDefinition")); const ICondition_1 = require("../dataform/ICondition"); const MinecraftUtilities_1 = __importDefault(require("../minecraft/MinecraftUtilities")); class MCCatGenerator { async updateMCCat(folder, isPreview) { await Database_1.default.loadVanillaCatalog(); const metadataFolder = isPreview ? await Database_1.default.loadPreviewMetadataFolder() : await Database_1.default.loadReleaseMetadataFolder(); const newMcCatFile = folder.ensureFile("mccat.json"); const cat = Database_1.default.vanillaCatalog; if (!cat) { return; } const blockAuxToStateNodes = await LegacyDocumentationDefinition_1.default.loadNode("addons", "/Blocks/AuxValueToBlockStatesMap/", isPreview); if (blockAuxToStateNodes) { for (const node of blockAuxToStateNodes?.nodes) { let name = node.name; let type = node.type; if (type) { let derivedTypeName = type; let description = node.description; let descriptStr = description && description.length > 0 ? description[0] : type; let leftBracket = descriptStr.indexOf("["); let propList = []; let propValues = []; if (leftBracket >= 0) { derivedTypeName = descriptStr.substring(0, leftBracket).trim(); let rightBracket = descriptStr.indexOf("]", leftBracket + 1); const propStr = descriptStr.substring(leftBracket + 1, rightBracket >= 0 ? rightBracket : descriptStr.length); const props = propStr.split(","); for (const prop of props) { const eqPos = prop.split("="); if (eqPos.length === 2) { let propName = eqPos[0].trim().replace(/\"/gi, ""); let propValue = eqPos[1].trim().replace(/\"/gi, ""); propList.push(propName); propValues.push(propValue); } } } else if (descriptStr.length > 0) { derivedTypeName = descriptStr.trim(); } type = MinecraftUtilities_1.default.canonicalizeName(type); derivedTypeName = MinecraftUtilities_1.default.canonicalizeName(derivedTypeName); let baseType = cat.blockBaseTypes.find((bt) => bt.n === type); if (!baseType) { baseType = { n: type, properties: [], }; cat.blockBaseTypes.push(baseType); } /* for (const propName of propList) { let prop: IBlockTypePropertyData | undefined = baseType.properties?.find((p) => p.name === propName); if (!prop) { prop = { name: propName, type: BlockPropertyType.intEnum, }; if (!baseType.properties) { baseType.properties = []; } baseType.properties.push(prop); } }*/ baseType.properties = undefined; if (derivedTypeName !== type) { if (!baseType.variants) { baseType.variants = []; } let derivedType = baseType.variants.find((dt) => (baseType && dt.n + baseType.n === derivedTypeName) || dt.n === derivedTypeName); if (!derivedType) { derivedType = { n: derivedTypeName, }; baseType.variants.push(derivedType); } } } } } const blockNodes = await LegacyDocumentationDefinition_1.default.loadNode("addons", "/Blocks/Blocks/", isPreview); if (blockNodes) { for (const node of blockNodes.nodes) { let name = MinecraftUtilities_1.default.canonicalizeName(node.name); let existingObj = undefined; for (const blockBaseType of cat.blockBaseTypes) { if (blockBaseType.n === name) { existingObj = blockBaseType; break; } if (blockBaseType.variants) { for (const variant of blockBaseType.variants) { if (variant.n === name || variant.n + blockBaseType.n === name) { existingObj = variant; break; } } } } if (!existingObj && cat.blockBaseTypes) { const baseType = { n: name, }; cat.blockBaseTypes.push(baseType); } } } for (const blockBaseType of cat.blockBaseTypes) { if (blockBaseType.variants) { for (const variant of blockBaseType.variants) { if (variant.n && variant.n.endsWith("_" + blockBaseType.n)) { variant.n = variant.n.substring(0, variant.n.length - blockBaseType.n.length); variant.lid = undefined; } } blockBaseType.variants.sort((a, b) => { return a.n.localeCompare(b.n); }); } blockBaseType.id = undefined; } cat.blockBaseTypes.sort((a, b) => { return a.n.localeCompare(b.n); }); if (cat.entityTypes) { cat.entityTypes.sort((a, b) => { return a.id.localeCompare(b.id); }); } let out = JSON.stringify(cat, undefined, 2); newMcCatFile.setContent(out); await newMcCatFile.saveContent(); } static cleanForId(id) { if (!id) { return ""; } id = Utilities_1.default.removeQuotes(id.replace(/\`/gi, "")); let parenStart = id.indexOf(" ("); let parenEnd = id.indexOf(")"); if (parenStart > 0 && parenEnd > parenStart) { id = id.substring(0, parenStart) + id.substring(parenEnd + 1); id = id.trim(); } return id; } async generateFormJson(inputFolder, outputFolder) { await outputFolder.deleteAllFolderContents(); await this.generateFormJsonFromFolder(inputFolder, outputFolder); } async generateFormJsonFromFolder(inputFolder, outputFolder) { await outputFolder.ensureExists(); if (!inputFolder.isLoaded) { await inputFolder.load(); } const fileList = { files: [], folders: [] }; for (const folderName in inputFolder.folders) { const folder = inputFolder.folders[folderName]; if (folder) { await this.generateFormJsonFromFolder(folder, outputFolder.ensureFolder(folderName)); fileList.folders.push(folderName); } } for (const fileName in inputFolder.files) { const file = inputFolder.files[fileName]; try { if (file) { await file.loadContent(); const jsonO = StorageUtilities_1.default.getJsonObject(file); if (jsonO) { const outputFile = outputFolder.ensureFile(fileName); fileList.files.push(fileName); await this.finalizeJsonForm(jsonO, outputFile); } // Unload file content after extracting JSON to save memory during bulk processing file.unload(); } } catch (e) { console.log("Error processing " + fileName + ": " + e); } } fileList.files.sort(); fileList.folders.sort(); const indexFile = outputFolder.ensureFile("index.json"); indexFile.setContent(Utilities_1.default.consistentStringifyTrimmed(fileList)); await indexFile.saveContent(); } async finalizeJsonForm(formObj, outputFile) { if (!formObj.generated_doNotEdit && !formObj.generatedFromSchema_doNotEdit && formObj.id) { const id = formObj.id.replace(/:/gi, "_").replace(/\./gi, "_"); await outputFile.loadContent(); const originalNode = StorageUtilities_1.default.getJsonObject(outputFile); await this.annotateFormJson(formObj, id, outputFile.parentFolder.name, originalNode); } if (formObj.generatedFromSchema_doNotEdit) { this.mergeOntoForm(formObj, formObj.generatedFromSchema_doNotEdit); } if (formObj.generated_doNotEdit) { this.mergeOntoForm(formObj, formObj.generated_doNotEdit); } formObj.generated_doNotEdit = undefined; formObj.generatedFromSchema_doNotEdit = undefined; outputFile.setContent(JSON.stringify(formObj, undefined, 2)); await outputFile.saveContent(); } mergeOntoForm(targetForm, formToMergeOn) { if (!targetForm.description || targetForm.description === "") { targetForm.description = formToMergeOn.description; } if (!targetForm.technicalDescription || targetForm.technicalDescription === "") { targetForm.technicalDescription = formToMergeOn.technicalDescription; } if (!targetForm.title || targetForm.title === "") { targetForm.title = formToMergeOn.title; } if (targetForm.samples) { for (const samplePath in formToMergeOn.samples) { targetForm.samples[samplePath] = formToMergeOn.samples[samplePath]; } } else { targetForm.samples = formToMergeOn.samples; } if (!targetForm.id) { targetForm.id = formToMergeOn.id; } if (!targetForm.note) { targetForm.note = formToMergeOn.note; } if (!targetForm.note2) { targetForm.note2 = formToMergeOn.note2; } if (!targetForm.note3) { targetForm.note3 = formToMergeOn.note3; } if (!targetForm.restrictions) { targetForm.restrictions = formToMergeOn.restrictions; } if (!targetForm.requires) { targetForm.requires = formToMergeOn.requires; } if (!targetForm.scalarFieldUpgradeName && formToMergeOn.scalarFieldUpgradeName) { targetForm.scalarFieldUpgradeName = formToMergeOn.scalarFieldUpgradeName; targetForm.scalarField = undefined; // you can either have a scalarFieldUpgradeName, or a scalarField, but not both. defer to scalarFieldUpgradeName } else if (!targetForm.scalarField) { targetForm.scalarField = formToMergeOn.scalarField; } if (!targetForm.customField) { targetForm.customField = formToMergeOn.customField; } if (!targetForm.isDeprecated) { targetForm.isDeprecated = formToMergeOn.isDeprecated; } if (!targetForm.versionIntroduced) { targetForm.versionIntroduced = formToMergeOn.versionIntroduced; } if (!targetForm.versionDeprecated) { targetForm.versionDeprecated = formToMergeOn.versionDeprecated; } if (!targetForm.tags) { targetForm.tags = formToMergeOn.tags; } if (!targetForm.isInternal) { targetForm.isInternal = formToMergeOn.isInternal; } if (!targetForm.dataVersion) { targetForm.dataVersion = formToMergeOn.dataVersion; } if (targetForm.fields && targetForm.fields.length === 0) { targetForm.fields = formToMergeOn.fields; } else { const formFields = {}; if (!targetForm.fields) { targetForm.fields = formToMergeOn.fields; } else { for (const targetField of targetForm.fields) { formFields[targetField.id] = targetField; } for (const mergeOnField of formToMergeOn.fields) { const targetField = formFields[mergeOnField.id]; if (!targetField) { targetForm.fields.push(mergeOnField); } else { if (targetField.isRemoved) { formFields[mergeOnField.id] = undefined; const newFieldArr = []; for (const updatedField of targetForm.fields) { if (updatedField.id !== mergeOnField.id) { newFieldArr.push(updatedField); } } targetForm.fields = newFieldArr; } else { targetField.samples = mergeOnField.samples; if (targetField.defaultValue === undefined) { targetField.defaultValue = mergeOnField.defaultValue; } if (mergeOnField.subForm && !targetField.subFormId) { if (!targetField.subForm) { targetField.subForm = { fields: [], }; } this.mergeOntoForm(targetField.subForm, mergeOnField.subForm); } if (mergeOnField.subFormId) { targetField.subFormId = mergeOnField.subFormId; targetField.subForm = undefined; // you can either have a subFormId, or a subForm, but not both. defer to subFormId } if (!targetField.alternates) { targetField.alternates = mergeOnField.alternates; } if (!targetField.description) { targetField.description = mergeOnField.description; } if (!targetField.title) { targetField.title = mergeOnField.title; } if (!targetField.versionDeprecated) { targetField.versionDeprecated = mergeOnField.versionDeprecated; } if (!targetField.versionIntroduced) { targetField.versionIntroduced = mergeOnField.versionIntroduced; } if (!targetField.humanifyValues) { targetField.humanifyValues = mergeOnField.humanifyValues; } if (!targetField.tags) { targetField.tags = mergeOnField.tags; } if (!targetField.minLength) { targetField.minLength = mergeOnField.minLength; } if (!targetField.maxLength) { targetField.maxLength = mergeOnField.maxLength; } if (!targetField.minValue) { targetField.minValue = mergeOnField.minValue; } if (!targetField.priority) { targetField.priority = mergeOnField.priority; } if (!targetField.note) { targetField.note = mergeOnField.note; } if (!targetField.note2) { targetField.note2 = mergeOnField.note2; } if (!targetField.note3) { targetField.note3 = mergeOnField.note3; } if (!targetField.fixedLength) { targetField.fixedLength = mergeOnField.fixedLength; } if (!targetField.retainIfEmptyOrDefault) { targetField.retainIfEmptyOrDefault = mergeOnField.retainIfEmptyOrDefault; } if (!targetField.allowedKeys) { targetField.allowedKeys = mergeOnField.allowedKeys; } if (!targetField.objectArrayTitleFieldKey) { targetField.objectArrayTitleFieldKey = mergeOnField.objectArrayTitleFieldKey; } if (!targetField.objectArrayToSubFieldKey) { targetField.objectArrayToSubFieldKey = mergeOnField.objectArrayToSubFieldKey; } if (!targetField.matchObjectArrayLengthToSubFieldLength) { targetField.matchObjectArrayLengthToSubFieldLength = mergeOnField.matchObjectArrayLengthToSubFieldLength; } if (!targetField.matchObjectArrayToSubFieldKey) { targetField.matchObjectArrayToSubFieldKey = mergeOnField.matchObjectArrayToSubFieldKey; } if (!targetField.keyDescription) { targetField.keyDescription = mergeOnField.keyDescription; } if (!targetField.maxValue) { targetField.maxValue = mergeOnField.maxValue; } if (!targetField.suggestedMinValue) { targetField.suggestedMinValue = mergeOnField.suggestedMinValue; } if (!targetField.suggestedMaxValue) { targetField.suggestedMaxValue = mergeOnField.suggestedMaxValue; } if (!targetField.isRequired) { targetField.isRequired = mergeOnField.isRequired; } if (targetField.dataType === undefined) { targetField.dataType = mergeOnField.dataType; } if (mergeOnField.choices) { if (!targetField.choices) { targetField.choices = []; } for (const mergeOnChoice of mergeOnField.choices) { let foundChoice = false; for (const targetChoice of targetField.choices) { if (targetChoice.id === mergeOnChoice.id) { foundChoice = true; if (!targetChoice.title) { targetChoice.title = mergeOnChoice.title; } if (!targetChoice.description) { targetChoice.description = mergeOnChoice.description; } if (!targetChoice.isDeprecated) { targetChoice.isDeprecated = mergeOnChoice.isDeprecated; } if (!targetChoice.iconImage) { targetChoice.iconImage = mergeOnChoice.iconImage; } if (!targetChoice.versionIntroduced) { targetChoice.versionIntroduced = mergeOnChoice.versionIntroduced; } if (!targetChoice.versionDeprecated) { targetChoice.versionDeprecated = mergeOnChoice.versionDeprecated; } break; } } if (!foundChoice) { targetField.choices.push(mergeOnChoice); } } targetField.choices = mergeOnField.choices; } if (!targetField.validity) { targetField.validity = mergeOnField.validity; } } } } } } } getFormFileNameBase(key) { key = key.toLowerCase(); if (key.startsWith("struct_") || key.startsWith("struct ")) { key = key.substring(7); } if ((key.startsWith("enum_") || key.startsWith("enum ")) && key.indexOf("num_property") < 0) { key = key.substring(5); } key = key.replace("sharedtypes", ""); key = StorageUtilities_1.default.sanitizePathBasic(key); return key; } getVersionlessString(key) { let verStart = key.indexOf(" v1."); if (verStart >= 0) { const nextSpace = key.indexOf(" ", verStart + 4); if (nextSpace >= 0) { key = key.substring(0, verStart) + key.substring(nextSpace + 1); } else { key = key.substring(0, verStart); } } return key; } async generateFormNodesFromLegacyDocNode(formJsonFolder, node, prefix) { for (const childNode of node.nodes) { if (childNode.name) { const name = this.getFormFileName(childNode.name); const formDocNode = this.getFormFromDocNode(childNode, childNode.name); const genFormDocNode = await this.getOriginalFormDefinition(formJsonFolder, name, prefix); await this.annotateFormJson(formDocNode, name, prefix, genFormDocNode); await this.mergeToFile(formJsonFolder, name, formDocNode, prefix); } } } async getOriginalFormDefinition(formJsonFolder, name, categoryName) { if (categoryName && categoryName.length > 0) { formJsonFolder = formJsonFolder.ensureFolder(categoryName); } name = name.toLowerCase(); name = name.replace(/ /gi, "_"); const file = formJsonFolder.ensureFile(name + ".form.json"); if (!file.isContentLoaded) { await file.loadContent(); } return StorageUtilities_1.default.getJsonObject(file); } async mergeToFile(formJsonFolder, name, formDefNode, categoryName, isSchema) { if (categoryName && categoryName.length > 0) { formJsonFolder = formJsonFolder.ensureFolder(categoryName); } name = name.toLowerCase(); name = name.replace(/ /gi, "_"); const file = formJsonFolder.ensureFile(name + ".form.json"); if (!file.isContentLoaded) { await file.loadContent(); } let jsonO = StorageUtilities_1.default.getJsonObject(file); if (isSchema) { if (jsonO) { jsonO.generatedFromSchema_doNotEdit = formDefNode; } else { jsonO = { id: MCCatGenerator.cleanForId(formDefNode.id), fields: [], generatedFromSchema_doNotEdit: formDefNode, }; } } else { if (jsonO) { jsonO.generated_doNotEdit = formDefNode; } else { jsonO = { id: MCCatGenerator.cleanForId(formDefNode.id), fields: [], generated_doNotEdit: formDefNode, }; } } file.setContent(JSON.stringify(jsonO, undefined, 2)); await file.saveContent(); } async annotateFormJson(formDefNode, name, prefix, originalNode) { let canonName = EntityTypeDefinition_1.default.getComponentFromBaseFileName(name); let isMinecraftComponent = false; if (name.startsWith("minecraft_")) { isMinecraftComponent = true; if (canonName.startsWith("behavior.")) { let hasPrioNode = false; for (const field of formDefNode.fields) { if (field.id === "priority") { hasPrioNode = true; } } if (!hasPrioNode) { formDefNode.fields.push({ id: "priority", title: "Priority", hideSamples: true, description: "As priority approaches 0, the priority is increased. The higher the priority, the sooner this behavior will be executed as a goal.", dataType: IField_1.FieldDataType.int, }); } } } if (prefix === "entity" && isMinecraftComponent) { await this.addVanillaMatches(formDefNode, canonName, [ ContentIndex_1.AnnotationCategory.entityComponentDependent, ContentIndex_1.AnnotationCategory.entityComponentDependentInGroup, ]); await this.addSamplesMatches(formDefNode, canonName, [ ContentIndex_1.AnnotationCategory.entityComponentDependent, ContentIndex_1.AnnotationCategory.entityComponentDependentInGroup, ]); } else if (prefix === "item" && isMinecraftComponent) { await this.addVanillaMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.itemComponentDependent]); await this.addSamplesMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.itemComponentDependent]); } else if (prefix === "block" && isMinecraftComponent) { await this.addVanillaMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.blockComponentDependent]); await this.addSamplesMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.blockComponentDependent]); } else if (prefix === "entityfilters") { await this.addVanillaMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.entityFilter]); await this.addSamplesMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.entityFilter]); } else if (prefix === "features") { await this.addVanillaMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.entityFilter]); await this.addSamplesMatches(formDefNode, canonName, [ContentIndex_1.AnnotationCategory.entityFilter]); } if (formDefNode.samples) { this.distributeSampleValues(formDefNode.samples, formDefNode, [], originalNode); } } async distributeSampleValues(samplesNode, formDefNode, pathTokens, originalNode) { if (!formDefNode.fields) { return; } const fieldsById = {}; for (const field of formDefNode.fields) { if (Utilities_1.default.isUsableAsObjectKey(field.id)) { fieldsById[field.id] = field; } } const originalFieldsById = {}; if (originalNode && originalNode.fields) { for (const field of originalNode.fields) { if (Utilities_1.default.isUsableAsObjectKey(field.id)) { originalFieldsById[field.id] = field; } } } for (const exampleFilePath in samplesNode) { const sampleList = samplesNode[exampleFilePath]; if (sampleList) { for (const sample of sampleList) { if (sample.content && typeof sample.content === "object") { let obj = sample.content; if (obj) { for (const fieldName in obj) { const fieldVal = obj[fieldName]; let subForm = undefined; if (!fieldsById[fieldName] && (!originalNode || !originalNode.customField || originalFieldsById[fieldName])) { let dataType = IField_1.FieldDataType.string; if (fieldName.startsWith("on_")) { dataType = IField_1.FieldDataType.minecraftEventTrigger; } else { if (typeof fieldVal === "number") { dataType = IField_1.FieldDataType.number; } else if (Array.isArray(fieldVal)) { if (fieldVal.length > 0) { if (typeof fieldVal[0] === "object") { dataType = IField_1.FieldDataType.objectArray; subForm = DataFormUtilities_1.default.generateFormFromObject(fieldName, fieldVal[0], exampleFilePath); } else if (typeof fieldVal[0] === "string") { dataType = IField_1.FieldDataType.stringArray; } } } else if (typeof fieldVal === "object") { dataType = IField_1.FieldDataType.object; subForm = DataFormUtilities_1.default.generateFormFromObject(fieldName, fieldVal, exampleFilePath); } } const newField = { id: MCCatGenerator.cleanForId(fieldName), title: Utilities_1.default.humanifyMinecraftName(fieldName), dataType: dataType, subForm: subForm, }; if (Utilities_1.default.isUsableAsObjectKey(fieldName)) { fieldsById[fieldName] = newField; } formDefNode.fields.push(newField); } } } } } } } for (const field of formDefNode.fields) { const pathTokensToSearch = pathTokens.slice(); pathTokensToSearch.push(field.id); for (const exampleFilePath in samplesNode) { const sampleList = samplesNode[exampleFilePath]; if (sampleList) { for (const sample of sampleList) { if (sample.content && typeof sample.content === "object") { let obj = sample.content; for (let i = 0; i < pathTokensToSearch.length; i++) { if (obj && obj[pathTokensToSearch[i]] !== undefined) { obj = obj[pathTokensToSearch[i]]; } else { obj = undefined; } } if (obj) { let exampleInstanceCount = 0; if (!field.samples) { field.samples = {}; } if (field.subForm) { let exampleObj = obj; if (Array.isArray(exampleObj) && exampleObj.length > 0) { const subSamples = {}; let subSamplesAdded = 0; const path = exampleFilePath; for (const subObj of exampleObj) { if (typeof subObj === "object" && Utilities_1.default.isUsableAsObjectKey(path)) { if (!subSamples[path]) { subSamples[path] = []; } subSamples[path].push({ path: sample.path + "|" + pathTokensToSearch.join(".") + "|" + subSamplesAdded.toString(), content: subObj, }); subSamplesAdded++; } } if (subSamplesAdded > 0) { await this.distributeSampleValues(subSamples, field.subForm, pathTokensToSearch); } } } const exampleSamp = JSON.stringify(obj); const path = exampleFilePath; for (const path in field.samples) { for (let i = 0; i < field.samples[path].length; i++) { if (JSON.stringify(field.samples[path][i].content) === exampleSamp) { exampleInstanceCount++; } } } if (exampleInstanceCount < 2) { if (!field.samples[path]) { field.samples[path] = []; } field.samples[path].push({ path: sample.path, content: obj }); } } } } } } } } async addVanillaMatches(formDefNode, name, annotations) { const vanillaMatches = await Database_1.default.getPreviewVanillaMatches(name, true, annotations); if (vanillaMatches && vanillaMatches.length > 0) { if (!formDefNode.samples) { formDefNode.samples = {}; } const vanillaPreview = await Database_1.default.getPreviewVanillaFolder(); if (!vanillaPreview) { return; } for (const match of vanillaMatches) { if (match.value.startsWith("/") && match.value.indexOf("metadata") < 0) { const file = await vanillaPreview.getFileFromRelativePath(match.value); if (file && (await file.exists())) { if (!file.isContentLoaded) { await file.loadContent(); } const jsonO = StorageUtilities_1.default.getJsonObject(file); if (jsonO) { if (!formDefNode.samples["/vanilla" + match.value]) { formDefNode.samples["/vanilla" + match.value] = []; } this.appendNodesByName(formDefNode.samples["/vanilla" + match.value], "minecraft:" + name, jsonO, "/"); } // Unload file content after extracting JSON to save memory during bulk processing file.unload(); } } } } } async addSamplesMatches(formDefNode, name, annotations) { const samplesMatches = await Database_1.default.getSamplesMatches(name, true, annotations); if (samplesMatches && samplesMatches.length > 0) { if (!formDefNode.samples) { formDefNode.samples = {}; } const samples = await Database_1.default.getSamplesFolder(); if (!samples) { return; } for (const match of samplesMatches) { if (match.value.startsWith("/")) { const file = await samples.getFileFromRelativePath(match.value); if (file && (await file.exists())) { if (!file.isContentLoaded) { await file.loadContent(); } const jsonO = StorageUtilities_1.default.getJsonObject(file); if (jsonO) { if (!formDefNode.samples["/samples" + match.value]) { formDefNode.samples["/samples" + match.value] = []; } this.appendNodesByName(formDefNode.samples["/samples" + match.value], "minecraft:" + name, jsonO, "/"); } // Unload file content after extracting JSON to save memory during bulk processing file.unload(); } } } } } appendNodesByName(exampleList, nodeName, source, path) { for (const attributeName in source) { const childItem = source[attributeName]; if (attributeName === nodeName && childItem !== undefined) { exampleList.push({ path: path + nodeName + "/", content: childItem }); } else if (attributeName === "test" && "minecraft:" + childItem === nodeName) { exampleList.push({ path: path, content: source }); } else if (typeof childItem === "object") { this.appendNodesByName(exampleList, nodeName, childItem, path + attributeName + "/"); } } } static sanitizeTitle(title) { if (title.indexOf("enum ") || title.indexOf("struct ")) { title = title.replace("enum ", ""); title = title.replace("struct ", ""); } } getFormFromDocNode(childNode, name) { /*"title": "Break doors annotation", "description": "Allows an entity to break doors, assuming that that flags set up for the component to use in navigation. Requires the entity's navigation component to have the parameter can_break_doors set to true.", "fields": [ { "id": "break_time", "description": "The time in seconds required to break through doors.", "dataType": 0 }, { "id": "min_difficulty", "title": "Minimum Difficulty", "description": "The minimum difficulty that the world must be on for this entity to break doors.", "dataType": 8, "lookupId": "difficulty" } ]*/ const fields = []; if (childNode.nodes) { for (const fieldNode of childNode.nodes) { const field = this.getFieldFromDocNode(fieldNode); if (field) { if (field.id.toLowerCase().indexOf("s an obj") >= 0 && field.subForm) { for (const subField of field.subForm.fields) { fields.push(subField); } } else { fields.push(field); } } } } const docForm = { id: MCCatGenerator.cleanForId(name), title: name ? Utilities_1.default.humanifyMinecraftName(name) : undefined, description: childNode.description ? MCCatGenerator.humanifyText(childNode.description.join("\n")) : undefined, fields: fields, }; if (childNode.examples) { const examples = []; for (const example of childNode.examples) { if (example.name && example.text) { examples.push({ path: example.name, content: example.text.join("\n"), }); } } if (examples.length > 0) { if (!docForm.samples) { docForm.samples = {}; } docForm.samples["samples"] = examples; } } if (childNode.type && childNode.type !== "JSON Object" && childNode.type !== "List" && childNode.type !== "Array" && childNode.type !== "Trigger") { if (childNode.type.indexOf("Boolean") >= 0) { docForm.scalarField = { id: "boolean", title: "Boolean", dataType: IField_1.FieldDataType.boolean, }; } else if (childNode.type.indexOf("String") >= 0) { if (!docForm.title || (docForm.title.indexOf("eplaceable") < 0 && docForm.title.indexOf("edstone Cond") < 0 && docForm.title.indexOf("iquid Detection") < 0 && docForm.title.indexOf("tem Visual") < 0)) docForm.scalarField = { id: "string", title: "String", dataType: IField_1.FieldDataType.string, }; } else if (childNode.type.indexOf("Number") >= 0 || childNode.type.indexOf("Decimal") >= 0) { docForm.scalarField = { id: "number", title: "Number", dataType: IField_1.FieldDataType.number, }; } else if (childNode.type.indexOf("Integer") >= 0) { docForm.scalarField = { id: "integer", title: "Integer", dataType: IField_1.FieldDataType.int, }; } } return docForm; } getFieldFromDocNode(childNode) { let type = IField_1.FieldDataType.string; let typeStr = childNode.type; if (typeStr === undefined) { typeStr = childNode.name; // this fixup is likely because of mistakes in the source } switch (typeStr) { case "Range [a, b]": type = IField_1.FieldDataType.intRange; break; case "Trigger": type = IField_1.FieldDataType.minecraftEventTrigger; break; case "Positive Integer": case "Integer": type = IField_1.FieldDataType.int; break; case "Decimal": type = IField_1.FieldDataType.float; break; case "Minecraft Filter": type = IField_1.FieldDataType.minecraftFilter; break; case "Boolean": type = IField_1.FieldDataType.boolean; break; case "Vector [a, b, c]": type = IField_1.FieldDataType.point3; break; case "Vector [a, b]": type = IField_1.FieldDataType.point2; break; case "Molang": type = IField_1.FieldDataType.string; break; case "Array": case "List": case "Item Description Properties": type = IField_1.FieldDataType.stringArray; break; case "JSON Object": type = IField_1.FieldDataType.objectArray; break; case "Localization String": type = IField_1.FieldDataType.localizableString; break; case "String": type = IField_1.FieldDataType.string; break; default: type = IField_1.FieldDataType.string; break; } if (childNode.nodes && childNode.nodes.length > 0 && type === IField_1.FieldDataType.string) { for (const subChildNode of childNode.nodes) { if (subChildNode.type === "Array" || (subChildNode.nodes && subChildNode.nodes.length > 0)) { type = IField_1.FieldDataType.object; } } } if ((childNode.name === "grow_up" || childNode.name === "event" || childNode.name.endsWith("_event") || childNode.name.startsWith("on_")) && !childNode.name.endsWith("_sound_event") && !childNode.name.startsWith("on_increase") && !childNode.name.startsWith("on_break") && (type === IField_1.FieldDataType.string || type === IField_1.FieldDataType.object || type === IField_1.FieldDataType.objectArray || type === IField_1.FieldDataType.stringArray)) { type = IField_1.FieldDataType.minecraftEventTrigger; } let defaultVal = undefined; if (childNode.default) { defaultVal = childNode.default; if (typeof childNode.default === "string" && childNode.default.startsWith("[") && childNode.default.endsWith("]") && type === IField_1.FieldDataType.point3) { let coordStr = childNode.default.substring(1, childNode.default.length - 1); let coordElements = coordStr.split(","); let coordArray = []; for (let str of coordElements) { if (str.length > 0) { try { const numVal = parseFloat(str); coordArray.push(numVal); } catch (e) { } } } defaultVal = coordArray; } else if (type === IField_1.FieldDataType.int || type === IField_1.FieldDataType.intRange) { try { defaultVal = parseInt(defaultVal); } catch (e) { } } else if (type === IField_1.FieldDataType.boolean) { try { defaultVal = defaultVal === "true" ? true : false; } catch (e) { } } else if (type === IField_1.FieldDataType.float) { try { defaultVal = parseFloat(defaultVal); }