UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

1,282 lines (1,211 loc) 57.5 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); const ProjectInfoItem_1 = require("./ProjectInfoItem"); const IInfoItemData_1 = require("./IInfoItemData"); const IProjectInfoData_1 = require("./IProjectInfoData"); const Constants_1 = require("../core/Constants"); const Utilities_1 = require("../core/Utilities"); const Log_1 = require("../core/Log"); const Status_1 = require("../app/Status"); const GeneratorRegistrations_1 = require("./GeneratorRegistrations"); const StorageUtilities_1 = require("../storage/StorageUtilities"); const ContentIndex_1 = require("../core/ContentIndex"); class ProjectInfoSet { static getSuiteFromString(suiteName) { switch (suiteName.toLowerCase()) { case "addon": case "addons": return IProjectInfoData_1.ProjectInfoSuite.cooperativeAddOn; case "currentplatform": return IProjectInfoData_1.ProjectInfoSuite.currentPlatformVersions; default: return IProjectInfoData_1.ProjectInfoSuite.default; // default is all infogenerators except cooperative add-on } } static getSuiteString(suite) { switch (suite) { case IProjectInfoData_1.ProjectInfoSuite.cooperativeAddOn: return "addon"; case IProjectInfoData_1.ProjectInfoSuite.currentPlatformVersions: return "currentplatform"; default: return "all"; } } get completedGeneration() { return this._completedGeneration; } get errorAndFailCount() { let count = 0; for (const item of this.items) { if (item.itemType === IInfoItemData_1.InfoItemType.error || item.itemType === IInfoItemData_1.InfoItemType.internalProcessingError || item.itemType === IInfoItemData_1.InfoItemType.testCompleteFail) { count++; } } return count; } get errorFailWarnCount() { let count = 0; for (const item of this.items) { if (item.itemType === IInfoItemData_1.InfoItemType.error || item.itemType === IInfoItemData_1.InfoItemType.warning || item.itemType === IInfoItemData_1.InfoItemType.internalProcessingError || item.itemType === IInfoItemData_1.InfoItemType.testCompleteFail) { count++; } } return count; } get errorFailWarnString() { let str = []; for (const item of this.items) { if (item.itemType === IInfoItemData_1.InfoItemType.error || item.itemType === IInfoItemData_1.InfoItemType.warning || item.itemType === IInfoItemData_1.InfoItemType.internalProcessingError || item.itemType === IInfoItemData_1.InfoItemType.testCompleteFail) { str.push(item.toString()); } } return str.join("\r\n"); } constructor(project, suite, excludeTests, info, items, index) { this.items = []; this.itemsByStoragePath = {}; this._isGenerating = false; this._completedGeneration = false; this._pendingGenerateRequests = []; this.project = project; this.info = info ? info : {}; this.contentIndex = index ? index : new ContentIndex_1.default(); if (items) { for (const item of items) { let projectItem = undefined; if (item.p) { if (project) { projectItem = project.getItemByProjectPath(item.p); } if (!this.itemsByStoragePath[item.p]) { this.itemsByStoragePath[item.p] = []; } let projectInfoItem = new ProjectInfoItem_1.default(item.iTp, item.gId, item.gIx, item.m, projectItem, item.d, item.iId, item.c, item.p); this.itemsByStoragePath[item.p]?.push(projectInfoItem); this.items.push(projectInfoItem); } else { this.items.push(new ProjectInfoItem_1.default(item.iTp, item.gId, item.gIx, item.m, projectItem, item.d, item.iId, item.c)); } } } if (suite) { this.suite = suite; } else { this.suite = IProjectInfoData_1.ProjectInfoSuite.default; } if (index) { if (info) { for (const key in info) { const val = info[key]; if (val && typeof val === "string") { if (ProjectInfoSet.isAggregableFieldName(key)) { index.parseTextContent("inspector", val); } } } } } if (excludeTests) { const excludeTestList = []; for (const excludeTest of excludeTests) { const vals = excludeTest.trim().split(","); for (const val of vals) { const valD = val.toUpperCase().trim(); if (valD.length > 0) { excludeTestList.push(valD); } } } this._excludeTests = excludeTestList; } } static getTopicData(id, index) { const gen = ProjectInfoSet._generatorsById[id]; if (gen) { return gen.getTopicData(index); } for (const gen of GeneratorRegistrations_1.default.projectGenerators) { if (gen.id === id) { this._generatorsById[id] = gen; return gen.getTopicData(index); } } return undefined; } getCountByType(itemType) { let count = 0; for (const item of this.items) { if (item.itemType === itemType) { count++; } } return count; } getSummaryByType(itemType) { let str = []; for (const item of this.items) { if (str.length < 15 && item.itemType === itemType) { str.push(item.toString()); } } return str.join("\r\n"); } matchesSuite(generator) { if (this.suite === IProjectInfoData_1.ProjectInfoSuite.default && generator.id.indexOf("CADDON") < 0) { return true; } if (this.suite === IProjectInfoData_1.ProjectInfoSuite.currentPlatformVersions) { if (generator.id === "MINENGINEVER" || generator.id === "BASEGAMEVER" || generator.id === "FORMATVER" || generator.id === "WORLDDATA") { return true; } } if (this.suite === IProjectInfoData_1.ProjectInfoSuite.cooperativeAddOn) { if (generator.id.indexOf("CADDON") >= 0 || generator.id === "PACKSIZE" || generator.id === "STRICT" || generator.id === "TEXTURE" || generator.id === "MINENGINEVER" || generator.id === "WORLDDATA") { return true; } } return false; } async generateForProject(force) { if (force === true && this._completedGeneration) { this._completedGeneration = false; this._isGenerating = false; } if (this._completedGeneration) { return; } if (this._isGenerating) { const pendingGenerate = this._pendingGenerateRequests; const prom = (resolve, reject) => { pendingGenerate.push(resolve); }; await new Promise(prom); } else { this._isGenerating = true; const valOperId = await this.project?.carto.notifyOperationStarted("Validating '" + this.project.name + "'", Status_1.StatusTopic.validation); this.info.summary = undefined; const projGenerators = GeneratorRegistrations_1.default.projectGenerators; const itemGenerators = GeneratorRegistrations_1.default.itemGenerators; const fileGenerators = GeneratorRegistrations_1.default.fileGenerators; const genItems = []; const genItemsByStoragePath = {}; const genContentIndex = new ContentIndex_1.default(); genContentIndex.iteration = new Date().getTime(); if (!this.project) { Log_1.default.throwUnexpectedUndefined("PISGFP"); return; } await this.project.loc.load(); for (let i = 0; i < projGenerators.length; i++) { const gen = projGenerators[i]; if ((!this._excludeTests || !this._excludeTests.includes(gen.id)) && gen && this.matchesSuite(gen)) { GeneratorRegistrations_1.default.configureForSuite(gen, this.suite); try { const results = await gen.generate(this.project, genContentIndex); for (const item of results) { this.pushItem(genItems, genItemsByStoragePath, item); } } catch (e) { // V--- add a breakpoint to the line below to catch validator exceptions (1 of 3) ---V genItems.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.internalProcessingError, gen.id, 500, this.project.name + ": " + e)); Log_1.default.debugAlert(e); } } } const itemsCopy = this.project.getItemsCopy(); for (let i = 0; i < itemsCopy.length; i++) { const pi = itemsCopy[i]; await pi.load(); for (let j = 0; j < itemGenerators.length; j++) { const gen = itemGenerators[j]; if ((!this._excludeTests || !this._excludeTests.includes(gen.id)) && this.matchesSuite(gen)) { GeneratorRegistrations_1.default.configureForSuite(gen, this.suite); try { const results = await gen.generate(pi, genContentIndex); for (const item of results) { this.pushItem(genItems, genItemsByStoragePath, item); } } catch (e) { // V--- add a breakpoint to the line below to catch validator exceptions (2 of 3) ---V genItems.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.internalProcessingError, gen.id, 501, this.project.name + ": " + e.toString())); } } } } await this.processFolder(this.project, await this.project.ensureProjectFolder(), genItems, genItemsByStoragePath, genContentIndex, fileGenerators, 0); this.addTestSummations(genItems, genItemsByStoragePath, projGenerators, this._excludeTests); this.addTestSummations(genItems, genItemsByStoragePath, itemGenerators, this._excludeTests); this.addTestSummations(genItems, genItemsByStoragePath, fileGenerators, this._excludeTests); this.items = genItems; this.itemsByStoragePath = genItemsByStoragePath; this.contentIndex = genContentIndex; this._completedGeneration = true; this.generateProjectMetaInfo(); const pendingLoad = this._pendingGenerateRequests; this._pendingGenerateRequests = []; this._isGenerating = false; this.info.errorCount = this.getCountByType(IInfoItemData_1.InfoItemType.error); this.info.internalProcessingErrorCount = this.getCountByType(IInfoItemData_1.InfoItemType.internalProcessingError); this.info.warningCount = this.getCountByType(IInfoItemData_1.InfoItemType.warning); this.info.testSuccessCount = this.getCountByType(IInfoItemData_1.InfoItemType.testCompleteSuccess); this.info.testFailCount = this.getCountByType(IInfoItemData_1.InfoItemType.testCompleteFail); this.info.testNotApplicableCount = this.getCountByType(IInfoItemData_1.InfoItemType.testCompleteNoApplicableItemsFound); this.info.errorSummary = this.getSummaryByType(IInfoItemData_1.InfoItemType.error); this.info.internalProcessingErrorSummary = this.getSummaryByType(IInfoItemData_1.InfoItemType.internalProcessingError); this.info.warningSummary = this.getSummaryByType(IInfoItemData_1.InfoItemType.warning); this.info.testFailSummary = this.getSummaryByType(IInfoItemData_1.InfoItemType.testCompleteFail); if (valOperId !== undefined) { await this.project?.carto.notifyOperationEnded(valOperId, "Completed validation of '" + this.project.name + "'", Status_1.StatusTopic.validation); } for (const prom of pendingLoad) { prom(undefined); } } } disconnectFromProject() { this.project = undefined; for (const pi of this.items) { pi.disconnect(); } } addTestSummations(genItems, genItemsByStoragePath, generators, excludeTests) { for (const gen of generators) { if ((!excludeTests || !excludeTests.includes(gen.id)) && this.matchesSuite(gen)) { const results = ProjectInfoSet.getItemsInCollection(genItems, gen.id); if (results.length === 0 && !gen.canAlwaysProcess) { this.pushItem(genItems, genItemsByStoragePath, new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.testCompleteNoApplicableItemsFound, gen.id, 2, `No applicable items found for test ${gen.title} (${gen.id})`)); } else { let errorCount = 0; let internalErrorCount = 0; let foundTestVerdict = false; for (const result of results) { if (result.itemType === IInfoItemData_1.InfoItemType.testCompleteFail || result.itemType === IInfoItemData_1.InfoItemType.testCompleteSuccess || result.itemType === IInfoItemData_1.InfoItemType.testCompleteNoApplicableItemsFound) { foundTestVerdict = true; } else if (result.itemType === IInfoItemData_1.InfoItemType.error) { errorCount++; } else if (result.itemType === IInfoItemData_1.InfoItemType.internalProcessingError) { internalErrorCount++; } } if (!foundTestVerdict) { if (errorCount > 0 && internalErrorCount <= 0) { this.pushItem(genItems, genItemsByStoragePath, new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.testCompleteFail, gen.id, 0, `Found ${errorCount} errors for ${gen.title} (${gen.id}).`)); } else if (internalErrorCount > 0 && errorCount <= 0) { this.pushItem(genItems, genItemsByStoragePath, new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.testCompleteFail, gen.id, 0, `Found ${errorCount} internal errors for ${gen.title} (${gen.id}). This may be a temporary issue with the test run`)); } else if (errorCount + internalErrorCount > 0) { this.pushItem(genItems, genItemsByStoragePath, new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.testCompleteFail, gen.id, 0, `Found ${errorCount} errors and ${internalErrorCount} internal errors for ${gen.title} (${gen.id})`)); } else { this.pushItem(genItems, genItemsByStoragePath, new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.testCompleteSuccess, gen.id, 1, `${gen.title} (${gen.id}) completed successfully`)); } } } } } } pushItem(itemSet, itemsByStoragePath, item) { if (item.projectItem && item.projectItem.projectPath && item.itemType !== IInfoItemData_1.InfoItemType.info && item.itemType !== IInfoItemData_1.InfoItemType.featureAggregate) { if (!itemsByStoragePath[item.projectItem.projectPath]) { itemsByStoragePath[item.projectItem.projectPath] = []; } itemsByStoragePath[item.projectItem.projectPath]?.push(item); } itemSet.push(item); } mergeFeatureSetsAndFieldsTo(allFeatureSets, allFields) { if (!this.info || !this.info.featureSets) { return; } for (const str in this.info) { if (str !== "features") { allFields[str] = true; } } for (const str in allFields) { let inf = this.info; if (ProjectInfoSet.isAggregableFieldName(str)) { if (inf[str] === undefined) { inf[str] = ""; } } } for (const featureName in this.info.featureSets) { const myFeature = this.info.featureSets[featureName]; if (myFeature !== undefined) { let allFeature = allFeatureSets[featureName]; if (allFeature === undefined) { allFeature = {}; allFeatureSets[featureName] = allFeature; } for (const measureName in myFeature) { const measureVal = myFeature[measureName]; if (measureVal !== undefined) { let allMeasureVal = allFeature[measureName]; if (allMeasureVal === undefined) { allMeasureVal = measureVal; } else { allMeasureVal += measureVal; } allFeature[measureName] = allMeasureVal; } } } } } ensureGenerators() { if (!this.info) { return; } if (this.info.summary !== undefined) { return; } this.info.summary = {}; for (let i = 0; i < this.items.length; i++) { const gId = this.items[i].generatorId; const gIndex = this.items[i].generatorIndex; let gen = this.info.summary[gId]; if (gen === undefined) { gen = {}; this.info.summary[gId] = gen; } let genI = gen[gIndex]; if (genI === undefined) { genI = {}; gen[gIndex] = genI; } const topicInfo = ProjectInfoSet.getTopicData(gId, gIndex); if (topicInfo) { genI.title = topicInfo.title; } if (genI.defaultMessage === undefined && this.items[i].message !== genI.title) { genI.defaultMessage = this.items[i].message; } } for (let i = 0; i < this.items.length; i++) { const item = this.items[i]; const gId = item.generatorId; const gIndex = item.generatorIndex; let gen = this.info.summary[gId]; if (gen === undefined) { gen = {}; this.info.summary[gId] = gen; } let genI = gen[gIndex]; if (genI === undefined) { genI = {}; gen[gIndex] = genI; } if (item.itemType !== IInfoItemData_1.InfoItemType.featureAggregate) { switch (item.itemType) { case IInfoItemData_1.InfoItemType.error: genI.errors = genI.errors ? genI.errors + 1 : 1; break; case IInfoItemData_1.InfoItemType.testCompleteFail: genI.testCompleteFails = genI.testCompleteFails ? genI.testCompleteFails + 1 : 1; break; case IInfoItemData_1.InfoItemType.testCompleteSuccess: genI.testCompleteSuccesses = genI.testCompleteSuccesses ? genI.testCompleteSuccesses + 1 : 1; break; case IInfoItemData_1.InfoItemType.warning: genI.warnings = genI.warnings ? genI.warnings + 1 : 1; break; case IInfoItemData_1.InfoItemType.recommendation: genI.recommendations = genI.recommendations ? genI.recommendations + 1 : 1; break; case IInfoItemData_1.InfoItemType.internalProcessingError: genI.internalProcessingErrors = genI.internalProcessingErrors ? genI.internalProcessingErrors + 1 : 1; break; } } if (this.items[i].message === genI.defaultMessage || this.items[i].message === genI.title) { this.items[i].message = undefined; } } } itemToString(item) { let summaryString = item.typeSummaryShort + ": "; summaryString += "[" + item.generatorId + Utilities_1.default.frontPadToLength(item.generatorIndex, 3, "0") + "]"; if (item.shortProjectItemPath) { summaryString += " (" + item.shortProjectItemPath + ")"; } let effectiveMessage = this.getEffectiveMessage(item); if (effectiveMessage.length > 0) { summaryString += " " + effectiveMessage; } if (item.data) { summaryString += ": " + item.data; } const errorContent = item.contentSummary; if (errorContent) { summaryString += " [in " + errorContent + "]"; } return summaryString; } static getEffectiveMessageFromData(data, item) { if (item.m !== undefined) { return item.m; } if (data.info === undefined || data.info.summary === undefined) { return undefined; } let gen = data.info.summary[item.gId]; if (gen === undefined) { return undefined; } let genI = gen[item.gIx]; if (genI === undefined) { return undefined; } return genI.defaultMessage; } getEffectiveMessage(item) { if (item.message !== undefined) { return item.message; } if (this.info === undefined || this.info.summary === undefined) { return ""; } let gen = this.info.summary[item.generatorId]; if (gen === undefined) { return ""; } let genI = gen[item.generatorIndex]; if (genI === undefined) { return ""; } return genI.defaultMessage ? genI.defaultMessage : ""; } shouldIncludeInIndex(data) { if (data.gId === "JSON" || data.gId === "ESLINT") { return false; } return true; } getDataObject(sourceName, sourcePath, sourceHash, isIndexOnly, subsetReports) { const items = []; this.ensureGenerators(); for (let i = 0; i < this.items.length; i++) { const dataObj = this.items[i].dataObject; if (!isIndexOnly || this.shouldIncludeInIndex(dataObj)) { items.push(dataObj); } } Utilities_1.default.encodeObjectWithSequentialRunLengthEncodeUsingNegative(this.contentIndex.data.trie); return { info: this.info, items: items, index: this.contentIndex.data, generatorName: Constants_1.constants.name, suite: this.suite, subsetReports: subsetReports, generatorVersion: Constants_1.constants.version, sourceName: sourceName, sourcePath: sourcePath, sourceHash: sourceHash, }; } static isAggregableFieldName(name) { if (name !== "features" && name !== "summary" && name !== "featureSets" && name !== "defaultIcon") { return true; } return false; } static isAggregableFeatureMeasureName(name) { if (!name.startsWith("#")) { return true; } return false; } static getSummaryCsvHeaderLine(projectInfo, allFeatures) { let csvLine = "Name,Title,Reds,Area,"; let fieldNames = []; for (const str in projectInfo) { if (ProjectInfoSet.isAggregableFieldName(str)) { fieldNames.push(str); } } fieldNames = fieldNames.sort(ProjectInfoSet.sortMinecraftFeatures); for (const str of fieldNames) { csvLine += Utilities_1.default.humanifyJsName(str) + ","; } for (const str in projectInfo) { if (ProjectInfoSet.isAggregableFieldName(str)) { fieldNames.push(str); } } for (const featureName in allFeatures) { const feature = allFeatures[featureName]; if (feature) { for (const measureName in feature) { if (ProjectInfoSet.isAggregableFeatureMeasureName(measureName)) { const measure = feature[measureName]; if (measure !== undefined) { csvLine += ProjectInfoSet.getDataSummary(featureName + " " + measureName) + ","; } } } } } return csvLine; } getIndexJson(sourceName, sourcePath, sourceHash) { return JSON.stringify(this.getDataObject(sourceName, sourcePath, sourceHash, true)); } getStrictIndexJson(sourceName, sourcePath, sourceHash) { const jsonO = this.getDataObject(sourceName, sourcePath, sourceHash, true); if (jsonO) { jsonO.info = undefined; jsonO.items = undefined; } return JSON.stringify(jsonO); } getReportHtml(sourceName, sourcePath, sourceHash) { const lines = []; lines.push("<html><head>"); lines.push("<script>"); lines.push(`const _reportObjects = []; function _addReportJson(data) { _reportObjects.push(data); } `); const dataObject = this.getDataObject(sourceName, sourcePath, sourceHash); dataObject.index = undefined; lines.push("_addReportJson(" + JSON.stringify(dataObject) + ");"); lines.push("</script><script>"); lines.push(` function getDataName(name) { if (typeof name === "boolean" || typeof name === "number") { return name.toString(); } let retVal = ""; for (let i = 0; i < name.length; i++) { if (i === 0) { retVal += name[i].toUpperCase(); } else { if (name[i] >= "A" && name[i] <= "Z") { retVal += " "; } retVal += name[i]; } } return retVal; } function getDataSummary(data) { if (data) { return data; } if (typeof data === "number" || typeof data === "boolean") { return data.toString(); } if (typeof data === "object") { return JSON.stringify(data); } return "(not defined)"; } function getEmptySummary(data) { if (typeof data === "object") { return JSON.stringify(data); } if (typeof data === "number" || typeof data === "boolean") { return data.toString(); } if (data) { return data; } return ""; } function getEffectiveMessage(reportObj, item) { if (item.m !== undefined) { return item.m; } if (reportObj.info === undefined || reportObj.info.summary === undefined) { return undefined; } let gen = reportObj.info.summary[item.gId]; if (gen === undefined) { return undefined; } let genI = gen[item.gIx]; if (genI === undefined) { return undefined; } return genI.defaultMessage; } function generateReports() { for (let i=0; i<_reportObjects.length; i++) { document.write("<h1>" + _reportObjects[i].sourceName + "</h1>"); document.write("<h3>Summary</h3>"); document.write("<table class='summary-table'>"); document.write("<tr><th>Measure</th><th>Value</th></tr>"); const info = _reportObjects[i].info; if (info) { for (const key in info) { const val = info[key]; if (key !== 'featureSets' && key !== 'defaultIcon' && key !== 'summary') { document.write("<tr>"); document.write("<td class='summary-key items-cell'>" + getDataName(key) + "</td>"); document.write("<td class='summary-value items-cell'>" + getDataSummary(val) + "</td>"); document.write("</tr>"); } } if (info["featureSets"]) { for (const featureName in info.featureSets) { const feature = info.featureSets[featureName]; for (const measureName in feature) { const val = feature[measureName]; document.write("<tr>"); document.write("<td class='summary-key items-cell'>" + featureName + " " + measureName + "</td>"); document.write("<td class='summary-value items-cell'>" + getDataSummary(val) + "</td>"); document.write("</tr>"); } } } } document.write("</table>"); } for (let i=0; i<_reportObjects.length; i++) { document.write("<h3>Items</h3>"); document.write("<table class='items-table'>"); document.write("<tr><th>Type</th><th>Test Category</th><th>Category Id</th><th>Message</th><th>Data</th><th>Path</th></tr>"); const info = _reportObjects[i].info; const items = _reportObjects[i].items; if (items && items.length) { for (const item of items) { if (item.itemType !== 2) { document.write("<tr>"); document.write("<td class='items-type items-cell'>" + getDescriptionForItemType(item.iTp) + "</td>"); document.write("<td class='items-generator items-cell'>" + item.gId + "</td>"); document.write("<td class='items-generatorIndex items-cell'>" + item.gIx + "</td>"); document.write("<td class='items-message items-cell'>" + getEmptySummary(getEffectiveMessage(_reportObjects[i], item)) + "</td>"); document.write("<td class='items-data items-cell'>" + getEmptySummary(item.d) + "</td>"); document.write("<td class='items-path items-cell'>" + getEmptySummary(item.p) + "</td>"); document.write("</tr>"); } } } document.write("</table>"); } } function getDescriptionForItemType(itemType) { switch (itemType) { case 0: return "SUCCESS"; break; case 1: return "FAIL"; break; case 3: return "ERROR"; break; case 4: return "WARN"; break; case 5: return "INTERNALERR"; break; case 6: return "RECOMMEND"; break; } return "INFO"; } </script> <style> body { font-family: Noto Sans, Arial, Helvetica, sans-serif; padding: 8px; } .items-table { border: solid 1px #606060; padding: 0px; max-width: 100vw; } .items-cell { border: solid 1px #606060; padding: 4px; vertical-align: top; font-size: x-small; overflow-wrap: anywhere; max-width: 25vw; } .summary-table { border: solid 1px #606060; padding: 0px; max-width: 100vw; } </style> </head><body> `); lines.push("<script>"); lines.push("generateReports();"); lines.push("</script>"); lines.push("</body></html>"); return lines.join("\n"); } static getDataSummary(data) { if (typeof data === "number" || typeof data === "boolean") { return data.toString(); } else if (data) { return '"' + data.replace(/"/gi, "'") + '"'; } return "(not defined)"; } static sortMinecraftFeatures(a, b) { a = a.replace("minecraft:", "_"); b = b.replace("minecraft:", "_"); return a.localeCompare(b); } getArea(title) { title = title.toLowerCase(); if (title.indexOf("furniture") >= 0) { return "Furniture"; } if (title.indexOf("skyblock") >= 0 || title.indexOf("sky block") >= 0) { return "Skyblock"; } if (title.indexOf("oneblock") >= 0 || title.indexOf("one block") >= 0) { return "One block"; } if (title.indexOf("lucky") >= 0) { return "Lucky"; } if (title.indexOf("parkour") >= 0) { return "Parkour"; } if (title.indexOf("surviv") >= 0) { return "Survival"; } if (title.indexOf("weapon") >= 0 || title.indexOf("potion") >= 0 || title.indexOf("tool") >= 0 || title.indexOf("hook") >= 0) { return "Tools"; } if (title.indexOf("roleplay") >= 0 || title.indexOf("teen") >= 0 || title.indexOf("illionair") >= 0 || title.indexOf("hacker") >= 0) { return "Roleplay"; } if (title.indexOf("mob") >= 0 || title.indexOf("pirate") >= 0 || title.indexOf("unicorn") >= 0 || title.indexOf("alien") >= 0 || title.indexOf("animals") >= 0 || title.indexOf("cats") >= 0 || title.indexOf("dogs") >= 0 || title.indexOf("dragon") >= 0) { return "Mob"; } if (title.indexOf("vehicles") >= 0 || title.indexOf("car") >= 0 || title.indexOf("plane") >= 0) { return "Vehicles"; } if (title.indexOf("island") >= 0 || title.indexOf("kingdom") >= 0 || title.indexOf("tower") >= 0 || title.indexOf("mansion") >= 0 || title.indexOf("village") >= 0 || title.indexOf("resort") >= 0 || title.indexOf("castle") >= 0 || title.indexOf("base") >= 0 || title.indexOf("town") >= 0 || title.indexOf("city") >= 0 || title.indexOf("fortress") >= 0 || title.indexOf("citadel") >= 0 || title.indexOf("outpost") >= 0 || title.indexOf("farm") >= 0 || title.indexOf("hotel") >= 0 || title.indexOf("castle") >= 0) { return "Area"; } if (title.indexOf("simulat") >= 0) { return "Simulator"; } return "General"; } getRed() { let red = 0; if (!this.info || !this.info.featureSets) { return 0; } /* let val = this.info.featureSets["Animation content-size total"]; if (val) { red += val * 0.2; } val = this.info.featureSets["Animation controller content-size total"]; if (val) { red += val * 0.5; } val = this.info.featureSets["Attachable content-size total"]; if (val) { red += val * 0.1; } val = this.info.featureSets["Function content-size total"]; if (val) { red += val * 2; } val = this.info.featureSets["Tick content-size total"]; if (val) { red += val * 20; } val = this.info.featureSets["Command execute"]; if (val) { red += val * 4; } val = this.info.featureSets["Behavior pack animation content-size total"]; if (val) { red += val * 0.8; } val = this.info.featureSets["Behavior pack animation controller content-size total"]; if (val) { red += val * 1.2; } val = this.info.featureSets["Biome resources content-size total"]; if (val) { red += val * 1.2; } val = this.info.featureSets["Block minecraft:chain_command_block"]; if (val) { red += val * 8; } val = this.info.featureSets["Block minecraft:command_block"]; if (val) { red += val * 8; } val = this.info.featureSets["Block minecraft:repeating_command_block"]; if (val) { red += val * 8; } val = this.info.featureSets["Block minecraft:structure_block"]; if (val) { red += val * 8; } val = this.info.featureSets["Block minecraft:observer"]; if (val) { red += val * 4; } val = this.info.featureSets["Block minecraft:comparator"]; if (val) { red += val * 4; } val = this.info.featureSets["Block minecraft:dropper"]; if (val) { red += val * 2; } val = this.info.featureSets["Block minecraft:hopper"]; if (val) { red += val * 2; } val = this.info.featureSets["Block minecraft:pressure_plate"]; if (val) { red += val * 1; } val = this.info.featureSets["Block minecraft:lever"]; if (val) { red += val * 4; } val = this.info.featureSets["Block minecraft:lit_redstone_lamp"]; if (val) { red += val; } val = this.info.featureSets["Block minecraft:redstone_block"]; if (val) { red += val; } val = this.info.featureSets["Block minecraft:redstone_torch"]; if (val) { red += val; } val = this.info.featureSets["Block minecraft:redstone_wire"]; if (val) { red += val; } val = this.info.featureSets["Block type content-size total"]; if (val) { red += val * 2; } val = this.info.featureSets["Entity dialogue content-size total"]; if (val) { red += val * 2; } val = this.info.featureSets["Entity type content-size total"]; if (val) { red += val * 2; } val = this.info.featureSets["Entity type resources content-size total"]; if (val) { red += val * 1; } val = this.info.featureSets["Item type content-size total"]; if (val) { red += val * 2; } val = this.info.featureSets["Item type resources content-size total"]; if (val) { red += val * 1; } val = this.info.featureSets["JavaScript content-size total"]; if (val) { red += val * 2; } val = this.info.featureSets["Loot table content-size total"]; if (val) { red += val; } val = this.info.featureSets["Model content-size total"]; if (val) { red += val * 0.1; } val = this.info.featureSets["Particle content-size total"]; if (val) { red += val * 0.4; } val = this.info.featureSets["Recipe content-size total"]; if (val) { red += val * 0.4; } val = this.info.featureSets["Render controller content-size total"]; if (val) { red += val * 0.5; } val = this.info.featureSets["Spawn rule content-size total"]; if (val) { red += val * 1; } val = this.info.featureSets["Trading content-size total"]; if (val) { red += val * 1; } val = this.info.featureSets["User interface content-size total"]; if (val) { red += val * 2; }*/ return red; } getSummaryCsvLine(containerName, title, allFeatures) { let line = ProjectInfoSet.getDataSummary(containerName) + "," + ProjectInfoSet.getDataSummary(title) + "," + this.getRed() + "," + this.getArea(title) + ","; let fieldNames = []; for (const str in this.info) { if (ProjectInfoSet.isAggregableFieldName(str)) { fieldNames.push(str); } } fieldNames = fieldNames.sort(ProjectInfoSet.sortMinecraftFeatures); for (const str of fieldNames) { // @ts-ignore line += ProjectInfoSet.getDataSummary(this.info[str]) + ","; } if (this.info.featureSets) { for (const featureName in allFeatures) { const allFeature = allFeatures[featureName]; const thisFeature = this.info.featureSets[featureName]; if (allFeature) { for (const measureName in allFeature) { if (ProjectInfoSet.isAggregableFeatureMeasureName(measureName)) { if (thisFeature) { const measure = thisFeature[measureName]; if (measure !== undefined) { if (typeof measure === "number") { line += measure; } } } line += ","; } } } } } return line; } getItemCsvLines() { const lines = []; for (let i = 0; i < this.items.length; i++) { const item = this.items[i]; if (item.itemType !== IInfoItemData_1.InfoItemType.featureAggregate) { let sp = ""; if (item.projectItem && item.projectItem.projectPath) { sp = item.projectItem.projectPath; } else if (item.projectItemPath) { sp = item.projectItemPath; } let line = item.generatorId + "," + item.generatorIndex + "," + item.typeSummary + "," + (item.projectItem ? item.projectItem.name : "") + ',"' + this.getEffectiveMessage(item) + '",'; if (item.data) { if (typeof item.data === "string") { line += '"' + item.data + '"'; } else { line += item.data.toString(); } } line += "," + sp + ","; if (item.featureSets) { for (const featName in item.featureSets) { const feature = item.featureSets[featName]; if (feature) { for (const measureName in feature) { if (ProjectInfoSet.isAggregableFeatureMeasureName(measureName)) { const measure = feature[measureName]; if (measure !== undefined) { if (typeof measure === "number") { line += featName + " " + measureName + "," + measure + ","; } else if (typeof measure === "string") { line += featName + " " + measureName + ',"' + measure + '",'; } } } } } } } lines.push(line); } } return lines; } getItems(generatorId, itemIndex) { const resultItems = []; for (const genItem of this.items) { if (genItem.generatorId === generatorId && genItem.generatorIndex === itemIndex) { resultItems.push(genItem); } } return resultItems; } getItemsByType(generatorId, itemType) { return ProjectInfoSet.getItemsInCollectionByType(this.items, generatorId, itemType); } getItemsByStoragePath(path) { if (!this.itemsByStoragePath) { return; } return this.itemsByStoragePath[path]; } static getItemsInCollection(genItems, generatorId) { const resultItems = []; for (const genItem of genItems) { if (genItem.generatorId === generatorId) { resultItems.push(genItem); } } return resultItems; } static getItemsInCollectionByType(genItems, generatorId, itemType) { const resultItems = []; for (const genItem of genItems) { if (genItem.generatorId === generatorId && genItem.itemType === itemType) { resultItems.push(genItem); } } return resultItems; } async processFolder(project, folder, genItems, genItemsByStoragePath, genContentIndex, fileGenerators, depth) { await folder.load(); for (const fileName in folder.files) { const file = folder.files[fileName]; if (file) { const projectItem = project.getItemByFile(file); if (projectItem && projectItem.projectPath) { genContentIndex.insert(StorageUtilities_1.default.getBaseFromName(fileName), projectItem.projectPath); genContentIndex.insert(file.storageRelativePath, projectItem.projectPath); await file.loadContent(); if (file.content && typeof file.content === "string") { const fileExtension = StorageUtilities_1.default.getTypeFromName(fileName); if (projectItem && projectItem.projectPath) { switch (fileExtension) { case "json": genContentIndex.parseJsonContent(projectItem.projectPath, file.content); break; case "ts": case "js": case "mjs": genContentIndex.parseJsContent(projectItem.projectPath, file.content); break; } } } for (const fileGen of fileGenerators) { if (this.matchesSuite(fileGen)) { try { const results = await fileGen.generate(project, file, genContentIndex); for (const item of results) { this.pushItem(genItems, genItemsByStoragePath, item); } } catch (e) { // V--- add a breakpoint to the line below to catch validator exceptions (3 of 3) ---V genItems.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.internalProcessingError, fileGen.id, 502, file.fullPath + ": " + e.toString())); } } } if (StorageUtilities_1.default.isContainerFile(file.storageRelativePath)) { const zipFolder = await StorageUtilities_1.default.getFileStorageFolder(file); if (zipFolder) { await this.processFolder(project, zipFolder, genItems, genItemsByStoragePath, genContentIndex, fileGenerators, depth + 1); } } } } } if (depth < 15) { for (const folderName in folder.folders) { const childFolder = folder.folders[folderName]; if (childFolder && !childFolder.errorStatus && childFolder.name) { const name = childFolder.name.toLowerCase(); if ((!name.startsWith(".") || name.startsWith(".vscode")) && !name.startsWith("node_modules")) { awai