UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

485 lines (484 loc) 24.1 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CooperativeAddOnRequirementsGeneratorTest = void 0; const ProjectInfoItem_1 = __importDefault(require("./ProjectInfoItem")); const IInfoItemData_1 = require("./IInfoItemData"); const StorageUtilities_1 = __importDefault(require("../storage/StorageUtilities")); const BehaviorManifestDefinition_1 = __importDefault(require("../minecraft/BehaviorManifestDefinition")); const IProjectItemData_1 = require("../app/IProjectItemData"); const Utilities_1 = __importDefault(require("../core/Utilities")); const ResourceManifestDefinition_1 = __importDefault(require("../minecraft/ResourceManifestDefinition")); const UniqueRegEx = new RegExp(/[a-zA-Z0-9]{2,}_[a-zA-Z0-9]{2,}:[\w]+/); const GenericTermList = [ "abilities", "actions", "adventure", "animals", "anims", "armor", "assets", "attachables", "banners", "base", "blocks", "book", "boss", "bosses", "bridge", "camping", "cars", "characters", "chests", "cinema", "cinematics", "cloud", "collectables", "collectibles", "custom_ui", "cut_scene", "cutscene", "deco", "decor", "dev", "dialogue", "dinos", "dinosaurs", "doors", "dragon", "dragons", "dummy", "effects", "enemies", "enemy", "entities", "entity", "env", "equipment", "events", "food", "furniture", "furnitures", "fx", "game_menu", "gameplay", "general", "glow", "guide", "guidebook", "inanimate", "interface", "internal", "intro", "item", "items", "launchers", "machines", "magic", "markers", "market", "marketing_banners", "mastermind", "mechanics", "menu", "menus", "minigames", "misc", "miscellaneous", "mob", "mobs", "monsters", "morphs", "mutant", "neutral", "npc", "npcs", "objectives", "particles", "passive", "passive_mobs", "pets", "platform", "player", "players", "portal", "portals", "preset", "projectile", "projectiles", "properties", "props", "recipe_models", "scanner", "script", "security", "sequences", "sfx", "shop", "skills", "sounds", "static_entity", "store", "structure", "structures", "systems", "tasks", "teams", "teleporter", "tnt", "tools", "towers", "trinkets", "tutorial", "ui", "user_interface", "util", "utilities", "vanilla", "vanilla_mob", "vehicle", "vehicles", "vr", "weapon", "weapons", "wrench", "opaque", "map", "on", "item", "player", "map", "charged", "beacon", "conduit", "moving", "banner", "bed", "cow", "chicken", "dragon", "ender", "enderman", "fang", "fireball", "mob", "warden", "village", "pattern", "wandering", "trial", "stray", "spider", "slime", "chest", "silverfish", "polar", "shield", "husk", "blaze", "axolotl", ]; // rule name/check. For validation errors, name should be a terse description of "your problem" var CooperativeAddOnRequirementsGeneratorTest; (function (CooperativeAddOnRequirementsGeneratorTest) { CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noLooseFileInTypeFolder"] = 101] = "noLooseFileInTypeFolder"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noCommonNamesInCreatorFolderName"] = 102] = "noCommonNamesInCreatorFolderName"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noLooseFileInCreatorFolder"] = 104] = "noLooseFileInCreatorFolder"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["moreThanOneFolderInCreatorFolderBesidesMaybeCommon"] = 108] = "moreThanOneFolderInCreatorFolderBesidesMaybeCommon"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noUnsupportedFolderNameInTypeFolder"] = 109] = "noUnsupportedFolderNameInTypeFolder"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["moreThanOneFolderInTypeFolder"] = 110] = "moreThanOneFolderInTypeFolder"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noLooseFilesInTypeFolder"] = 111] = "noLooseFilesInTypeFolder"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noDimensionElements"] = 131] = "noDimensionElements"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noUiElements"] = 133] = "noUiElements"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["notOneBehaviorPackManifest"] = 160] = "notOneBehaviorPackManifest"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["notOneResourcePackManifest"] = 161] = "notOneResourcePackManifest"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["behaviorPackManifestNotValid"] = 163] = "behaviorPackManifestNotValid"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["resourcePackManifestNotValid"] = 164] = "resourcePackManifestNotValid"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["notOneDependencyFromBehaviorPackToResourcePack"] = 165] = "notOneDependencyFromBehaviorPackToResourcePack"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["dependencyFromBehaviorPackToResourcePackNotValid"] = 166] = "dependencyFromBehaviorPackToResourcePackNotValid"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["notOneDependencyFromResourcePackToBehaviorPack"] = 168] = "notOneDependencyFromResourcePackToBehaviorPack"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["dependencyFromResourcePackToBehaviorPackNotValid"] = 169] = "dependencyFromResourcePackToBehaviorPackNotValid"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["foundBehaviorPack"] = 200] = "foundBehaviorPack"; CooperativeAddOnRequirementsGeneratorTest[CooperativeAddOnRequirementsGeneratorTest["noVibrantVisualsForNow"] = 210] = "noVibrantVisualsForNow"; })(CooperativeAddOnRequirementsGeneratorTest || (exports.CooperativeAddOnRequirementsGeneratorTest = CooperativeAddOnRequirementsGeneratorTest = {})); /** * Validates cooperative add-on requirements for marketplace submissions. * * @see {@link ../../public/data/forms/mctoolsval/caddonreq.form.json} for topic definitions */ class CooperativeAddOnRequirementsGenerator { id = "CADDONREQ"; title = "Cooperative Add-On Requirements"; async generate(project, contentIndex) { const items = []; let behaviorPackManifest = undefined; let behaviorPackItem = undefined; let resourcePackManifest = undefined; let resourcePackItem = undefined; const itemsCopy = project.getItemsCopy(); for (const projectItem of itemsCopy) { if (projectItem.primaryFile) { if (projectItem.itemType === IProjectItemData_1.ProjectItemType.behaviorPackManifestJson) { if (behaviorPackManifest) { // CADDONREQ160 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.notOneBehaviorPackManifest, `Found more than one behavior pack manifest in a cooperative add-on, which is not a best practice`, projectItem)); } else { items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, CooperativeAddOnRequirementsGeneratorTest.foundBehaviorPack, `Behavior pack manifest found.`, projectItem)); } behaviorPackManifest = await BehaviorManifestDefinition_1.default.ensureOnFile(projectItem.primaryFile); behaviorPackItem = projectItem; await behaviorPackManifest?.load(); } else if (projectItem.itemType === IProjectItemData_1.ProjectItemType.resourcePackManifestJson) { if (resourcePackManifest) { // CADDONREQ161 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.notOneResourcePackManifest, `Found more than one resource pack manifest in a cooperative add-on, which is not a best practice`, projectItem)); } resourcePackManifest = await ResourceManifestDefinition_1.default.ensureOnFile(projectItem.primaryFile); resourcePackItem = projectItem; await resourcePackManifest?.load(); } } } if (!behaviorPackManifest || !behaviorPackManifest.definition) { // CADDONREQ163 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.behaviorPackManifestNotValid, `Did not find a valid behavior pack manifest.`, undefined)); } if (!resourcePackManifest || !resourcePackManifest.definition) { //CADDONREQ164 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.resourcePackManifestNotValid, `Did not find a valid resource pack manifest.`, undefined)); } if (behaviorPackManifest && resourcePackManifest && behaviorPackManifest.definition && resourcePackManifest.definition) { const bpNonInternalDependency = behaviorPackManifest.getFirstNonScriptModuleDependency(); if (!behaviorPackManifest.definition.dependencies || behaviorPackManifest.getNonScriptModuleDependencyCount() !== 1) { // CADDONREQ165 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.notOneDependencyFromBehaviorPackToResourcePack, `Did not find exactly one dependency on the corresponding resource pack in the behavior pack manifest.`, behaviorPackItem, behaviorPackManifest.getNonScriptModuleDependencyCount())); } else if (!bpNonInternalDependency || !bpNonInternalDependency.uuid || !Utilities_1.default.uuidEqual(bpNonInternalDependency.uuid, resourcePackManifest.definition.header.uuid)) { // CADDONREQ166 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.dependencyFromBehaviorPackToResourcePackNotValid, `Behavior pack manifest does not have a proper dependency on the resource pack identifier.`, behaviorPackItem)); } if (!resourcePackManifest.definition.dependencies || resourcePackManifest.definition.dependencies.length !== 1) { // CADDONREQ168 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.notOneDependencyFromResourcePackToBehaviorPack, `Did not find exactly one dependency on the corresponding behavior pack in the resource pack manifest.`, resourcePackItem)); } else if (!resourcePackManifest.definition.dependencies[0].uuid || !Utilities_1.default.uuidEqual(resourcePackManifest.definition.dependencies[0].uuid, behaviorPackManifest.definition.header.uuid)) { // CADDONREQ169 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.dependencyFromResourcePackToBehaviorPackNotValid, `Resource pack manifest does not have a proper dependency on the behavior pack identifier.`, behaviorPackItem)); } } const bpFolder = await project.getDefaultBehaviorPackFolder(); if (bpFolder) { await this.generateFromBehaviorPackFolder(project, bpFolder, items); } const rpFolder = await project.getDefaultResourcePackFolder(); if (rpFolder) { await this.generateFromResourcePackFolder(project, rpFolder, items); } return items; } summarize(info, infoSet) { } async generateFromBehaviorPackFolder(project, folder, items) { if (!folder.isLoaded) { await folder.load(); } for (const folderName in folder.folders) { const childFolder = folder.folders[folderName]; const folderNameCanon = StorageUtilities_1.default.canonicalizeName(folderName); if (folderNameCanon === "dimensions") { // CADDONREQ131 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.noDimensionElements, `Found dimensions in a cooperative add-on, which is not a best practice.`, undefined)); } if (childFolder && !folder.errorStatus) { if (folderNameCanon === "structures") { await this.generateFromFirstLevelFolderCreator_Game(project, childFolder, items); } else if (folderNameCanon !== "texts" && folderNameCanon !== "entities" && folderNameCanon !== "features" && folderNameCanon !== "feature_rules" && folderNameCanon !== "particles" && folderNameCanon !== "items" && folderNameCanon !== "scripts" && folderNameCanon !== "recipes" && folderNameCanon !== "spawn_rules" && folderNameCanon !== "animations" && folderNameCanon !== "animation_controllers" && folderNameCanon !== "render_controllers" && folderNameCanon !== "blocks") { await this.generateFromFirstLevelFolderCreatorNameGameName(project, childFolder, items); } } } } async generateFromResourcePackFolder(project, folder, items) { if (!folder.isLoaded) { await folder.load(); } for (const folderName in folder.folders) { const childFolder = folder.folders[folderName]; const folderNameCanon = StorageUtilities_1.default.canonicalizeName(folderName); if (folderNameCanon === "ui") { // CADDONREQ133 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.noUiElements, `Found ui elements in a cooperative add-on, which is not supported`, undefined)); } if (childFolder && !folder.errorStatus) { if (folderNameCanon !== "texts" && folderNameCanon !== "entity" && folderNameCanon !== "items" && folderNameCanon !== "particles" && folderNameCanon !== "materials" && folderNameCanon !== "blocks" && folderNameCanon !== "models" && folderNameCanon !== "attachables" && folderNameCanon !== "render_controllers" && folderNameCanon !== "animation_controllers" && folderNameCanon !== "animations") { await this.generateFromFirstLevelFolderCreatorNameGameName(project, childFolder, items); } } } } static isNameGenericTerm(name) { name = StorageUtilities_1.default.canonicalizeName(name); return GenericTermList.includes(name); } static isNamespacedIdentifier(id) { let identifierSplit = id.split(":"); if (identifierSplit.length !== 2) { return false; } if (identifierSplit[0].length < 2 || identifierSplit[1].length < 2) { return false; } return this.isNamespacedString(identifierSplit[0]); } static isNamespacedString(name) { let tokens = name.split("_"); if (tokens.length < 2) { return false; } return tokens[0].length >= 2 && tokens[1].length >= 2; } static isCommonMaterialName(name) { let tokens = name.split("_"); if (tokens.length < 3) { return true; } return GenericTermList.includes(tokens[0]); } static isUniqueNamespaceOrShortName(name) { name = StorageUtilities_1.default.canonicalizeName(name); if (name.length < 3) { return false; } return UniqueRegEx.test(name); } async generateFromFirstLevelFolderCreator_Game(project, folder, items) { if (!folder.isLoaded) { await folder.load(); } for (const fileName in folder.files) { if (!this.isPerPackCatalogFile(folder.name, fileName)) { const file = folder.files[fileName]; const projectItem = file?.extendedPath ? project.getItemByExtendedOrProjectPath(file?.extendedPath) : undefined; // CADDONREQ111 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.noLooseFilesInTypeFolder, `Found a loose file in the ${folder.name} folder. Should only see files in the folder ${folder.name}\\creatorshortname_gamename\\`, projectItem, fileName)); } } let folderCount = 0; for (const folderName in folder.folders) { const folderNameCanon = StorageUtilities_1.default.canonicalizeName(folderName); folderCount++; if (CooperativeAddOnRequirementsGenerator.isUniqueNamespaceOrShortName(folderNameCanon)) { // CADDONREQ109 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.noUnsupportedFolderNameInTypeFolder, `Found an add-on-blocked folder '${folderName}' in a parent folder pack\\${folder.name}. Should be named 'creatorshortname' and not a common term`, undefined, folderName)); } } if (folderCount > 1) { // CADDONREQ110 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.moreThanOneFolderInTypeFolder, `Folder '${folder.name}' has more than one subfolder, which is not supported. There should only be one folder in pack\\${folder.name}\\<studioname>_<mygamename>`, undefined, folder.name)); } } isPerPackCatalogFile(folderName, fileName) { const fileNameCanon = StorageUtilities_1.default.canonicalizeName(fileName); if ((folderName !== "functions" || fileNameCanon !== "tick.json") && (folderName !== "textures" || (fileNameCanon !== "flipbook_textures.json" && fileNameCanon !== "item_textures.json" && fileNameCanon !== "blocks.json" && fileNameCanon !== "block.json" && fileNameCanon !== "textures_list.json" && fileNameCanon !== "texture_list.json" && fileNameCanon !== "terrain_textures.json" && fileNameCanon !== "item_texture.json" && fileNameCanon !== "terrain_texture.json")) && (folderName !== "item_catalog" || fileNameCanon !== "crafting_item_catalog.json") && (folderName !== "sounds" || (fileNameCanon !== "sound_definitions.json" && fileNameCanon !== "sounds.json" && fileNameCanon !== "music_definitions.json"))) { return false; } return true; } async generateFromFirstLevelFolderCreatorNameGameName(project, folder, items) { if (!folder.isLoaded) { await folder.load(); } for (const fileName in folder.files) { if (!this.isPerPackCatalogFile(folder.name, fileName)) { const file = folder.files[fileName]; const projectItem = file?.extendedPath ? project.getItemByExtendedOrProjectPath(file?.extendedPath) : undefined; // CADDONREQ101 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.noLooseFileInTypeFolder, `Found a loose file in the ${folder.name} folder. Should only see files in the folder ${folder.name}\\creatorshortname\\gamename\\`, projectItem, fileName)); } } for (const folderName in folder.folders) { const folderNameCanon = StorageUtilities_1.default.canonicalizeName(folderName); if (CooperativeAddOnRequirementsGenerator.isNameGenericTerm(folderNameCanon)) { // CADDONREQ102 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.noCommonNamesInCreatorFolderName, `Found an cooperative add-on common name folder '${folderName}' in a parent folder pack\\${folder.name}. Should be named 'creatorshortname' and not a common term`, undefined, folderName)); } const childFolder = folder.folders[folderName]; if (childFolder) { await this.generateFromSecondLevelFolderGameName(project, folder.name, childFolder, items); } } } async generateFromSecondLevelFolderGameName(project, parentFolderName, folder, items) { if (!folder.isLoaded) { await folder.load(); } for (const fileName in folder.files) { const file = folder.files[fileName]; const projectItem = file?.extendedPath ? project.getItemByExtendedOrProjectPath(file.extendedPath) : undefined; // CADDONREQ104 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.noLooseFileInCreatorFolder, `Found a loose file '${fileName}' in ${parentFolderName}\\${folder.name}. Files should only be in the folder ${parentFolderName}\\${folder.name}\\<mygamename>`, projectItem, fileName)); } let folderCount = 0; for (const childFolderName in folder.folders) { const folderNameCanon = StorageUtilities_1.default.canonicalizeName(childFolderName); if (folderNameCanon !== "common") { folderCount++; } } if (folderCount > 1) { // CADDONREQ108 items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, CooperativeAddOnRequirementsGeneratorTest.moreThanOneFolderInCreatorFolderBesidesMaybeCommon, `Secondary folder '${folder.name}' in ${parentFolderName} has more than one subfolder (besides 'common'), which is not supported. There should only be one folder (plus optionally 'common') in pack\\${parentFolderName}\\${folder.name}\\<mygamename>`, undefined, folder.name)); } } } exports.default = CooperativeAddOnRequirementsGenerator;