UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

661 lines (659 loc) 30.5 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectImportExclusions = void 0; const MCWorld_1 = require("./../minecraft/MCWorld"); const StorageUtilities_1 = require("./../storage/StorageUtilities"); const Utilities_1 = require("../core/Utilities"); const Database_1 = require("./../minecraft/Database"); const Log_1 = require("../core/Log"); const GitHubStorage_1 = require("./../github/GitHubStorage"); const AppServiceProxy_1 = require("./../core/AppServiceProxy"); const ZipStorage_1 = require("../storage/ZipStorage"); const IProjectData_1 = require("../app/IProjectData"); const MinecraftUtilities_1 = require("../minecraft/MinecraftUtilities"); const ProjectUpdateRunner_1 = require("../updates/ProjectUpdateRunner"); const CartoApp_1 = require("./CartoApp"); const HttpStorage_1 = require("../storage/HttpStorage"); const ProjectBuild_1 = require("./ProjectBuild"); const WorldLevelDat_1 = require("../minecraft/WorldLevelDat"); const IProjectItemData_1 = require("./IProjectItemData"); exports.ProjectImportExclusions = [ "build", "node_modules", "dist", "lib", ".env", "*/.*", "out", "*just.config*", "*package-lock*", "*.mjs*", ]; class ProjectExporter { static async generateFlatBetaApisWorldWithPacksZipBytes(carto, project, name) { await Database_1.default.loadContent(); if (Database_1.default.contentFolder === null) { Log_1.default.unexpectedNull(); return undefined; } const mcworld = await this.generateWorldWithPacksAndContent(project, name, undefined, { generator: WorldLevelDat_1.Generator.flat, betaApisExperiment: true, }); if (!mcworld) { return undefined; } const newBytes = await mcworld.getBytes(); return newBytes; } static async syncProjectFromGitHub(isNewProject, carto, gitHubRepoName, gitHubOwner, gitHubBranch, gitHubFolder, projName, project, fileList, messageUpdater, dontOverwriteExistingFiles) { let gh = undefined; const urlExtension = "res/samples/" + gitHubOwner + "/" + gitHubRepoName + "-" + (gitHubBranch ? gitHubBranch : "main") + "/" + gitHubFolder; if (CartoApp_1.default.isWeb) { gh = new HttpStorage_1.default(Utilities_1.default.ensureEndsWithSlash(CartoApp_1.default.contentRoot) + urlExtension); } else { gh = new GitHubStorage_1.default(carto.anonGitHub, gitHubRepoName, gitHubOwner, gitHubBranch, gitHubFolder); //gh = new HttpStorage(Utilities.ensureEndsWithSlash(constants.homeUrl) + urlExtension); } if (!projName) { projName = "local " + gitHubOwner + " " + gitHubRepoName; if (gitHubFolder !== undefined) { projName += " " + gitHubFolder.replace(/\//gi, " "); projName = projName.replace(" behavior_packs", ""); } } const newProjectName = await carto.getNewProjectName(projName); if (!project) { project = await carto.createNewProject(newProjectName, undefined, undefined, undefined, IProjectData_1.ProjectFocus.gameTests, false); } /*if (fileList) { await gh.rootFolder.setStructureFromFileList(fileList); } else {*/ await gh.rootFolder.load(); //} const rootFolder = await project.ensureProjectFolder(); try { await StorageUtilities_1.default.syncFolderTo(gh.rootFolder, rootFolder, false, false, false, exports.ProjectImportExclusions, undefined, messageUpdater, dontOverwriteExistingFiles); } catch (e) { Log_1.default.error("Error synchronizing from GitHub:" + e.toString()); } await rootFolder.saveAll(); if (isNewProject) { await this.renameDefaultFolders(project, projName); project.originalGitHubOwner = gitHubOwner; project.originalGitHubRepoName = gitHubRepoName; project.originalGitHubBranch = gitHubBranch; project.originalGitHubFolder = gitHubFolder; project.originalFileList = fileList; } await project.inferProjectItemsFromFiles(true); const pur = new ProjectUpdateRunner_1.default(project); await pur.updateProject(); await project.save(true); await carto.save(); return project; } static async renameDefaultFolders(project, newTokenName) { const bpFolder = await project.getDefaultBehaviorPackFolder(true); const rpFolder = await project.getDefaultResourcePackFolder(true); newTokenName = MinecraftUtilities_1.default.makeNameFolderSafe(newTokenName); if (bpFolder) { try { await bpFolder.rename(newTokenName); } catch (e) { // perhaps folder could not be renamed because a folder exists; continue in this case. } } if (rpFolder) { try { await rpFolder.rename(newTokenName); } catch (e) { // perhaps folder could not be renamed because a folder exists; continue in this case. } } } static async getPackFolder(folder, seekingResource) { await folder.load(); const manifest = folder.files["manifest.json"]; if (manifest !== undefined) { const parentFolder = folder.parentFolder; let isResource = false; if (parentFolder !== null) { const name = StorageUtilities_1.default.canonicalizeName(parentFolder.name); if (name.indexOf("resource") >= 0) { isResource = true; } } if (seekingResource && isResource) { return folder; } else if (!seekingResource) { return folder; } } else { for (const folderName in folder.folders) { const childFolder = folder.folders[folderName]; if (childFolder !== undefined && !childFolder.errorStatus) { const result = (await ProjectExporter.getPackFolder(childFolder, seekingResource)); if (result !== undefined) { return result; } } } } return undefined; } static async ensureWorldsFolder(rootMinecraftFolder) { let worldsFolder = await rootMinecraftFolder.getFolderFromRelativePath("/minecraftWorlds/"); if (!worldsFolder) { worldsFolder = await rootMinecraftFolder.getFolderFromRelativePath("/worlds/"); } if (!worldsFolder) { worldsFolder = await rootMinecraftFolder.ensureFolderFromRelativePath("/minecraftWorlds/"); } if (!worldsFolder) { Log_1.default.unexpectedUndefined("EWF"); return undefined; } await worldsFolder.ensureExists(); return worldsFolder; } static async ensureMinecraftWorldsFolder(carto) { if (carto.deploymentStorage === null) { Log_1.default.unexpectedUndefined("EMWF"); return undefined; } return await this.ensureWorldsFolder(carto.deploymentStorage.rootFolder); } static async prepareProject(project) { await ProjectExporter.updateProjects(project); await project.save(); const projectBuild = new ProjectBuild_1.default(project); await projectBuild.build(); if (projectBuild.isInErrorState) { project.appendErrors(projectBuild); return undefined; } return projectBuild; } static async deployProject(carto, project, deployTargetFolder) { const ctProjectBuild = await ProjectExporter.prepareProject(project); if (!ctProjectBuild) { return false; } await ProjectExporter.deployProjectPacks(project, ctProjectBuild, deployTargetFolder, undefined, 1 /* FolderDeploy.developmentFolders */); await deployTargetFolder.saveAll(); const targetResourcePacksFolder = deployTargetFolder.ensureFolder("development_resource_packs"); const rpDeployFolderExists = await targetResourcePacksFolder.exists(); if (rpDeployFolderExists) { await project.ensureProjectFolder(); const rpi = await project.getDefaultResourcePackFolder(); if (rpi) { const deployProjectFolder = targetResourcePacksFolder.ensureFolder(project.name); await deployProjectFolder.ensureExists(); await StorageUtilities_1.default.syncFolderTo(rpi, deployProjectFolder, true, true, true, [ "/mcworlds", "/minecraftWorlds", ]); } } return true; } static async deployProjectPacks(project, projectBuild, targetFolder, mcworld, useDeveloperFolders) { const bpGroupFolder = useDeveloperFolders === 2 /* FolderDeploy.noFolders */ ? targetFolder : targetFolder.ensureFolder(useDeveloperFolders === 1 /* FolderDeploy.developmentFolders */ ? "development_behavior_packs" : "behavior_packs"); await bpGroupFolder.ensureExists(); const activeBehaviorPackFolder = await project.getDefaultBehaviorPackFolder(); const scriptsFolder = await project.getMainScriptsFolder(); if (activeBehaviorPackFolder) { const bpTargetFolder = bpGroupFolder.ensureFolder(activeBehaviorPackFolder.ensuredName + (useDeveloperFolders === 2 /* FolderDeploy.noFolders */ ? "_bp" : "")); await bpTargetFolder.ensureExists(); await StorageUtilities_1.default.syncFolderTo(activeBehaviorPackFolder, bpTargetFolder, true, true, false, [ "mcworlds", "db", "level.dat", "level.dat_old", "levelname.txt", "behavior_packs", "resource_packs", ]); await projectBuild.syncToBehaviorPack(bpTargetFolder); if (scriptsFolder && scriptsFolder.parentFolder !== activeBehaviorPackFolder) { const scriptsTargetFolder = bpTargetFolder.ensureFolder("scripts"); await scriptsTargetFolder.ensureExists(); await StorageUtilities_1.default.syncFolderTo(scriptsFolder, scriptsTargetFolder, true, true, false, ["*.ts"]); } if (mcworld) { mcworld.ensureBehaviorPack(project.defaultBehaviorPackUniqueId, project.defaultBehaviorPackVersion, activeBehaviorPackFolder.name); } await bpTargetFolder.saveAll(); } const activeResourcePackFolder = await project.getDefaultResourcePackFolder(); if (activeResourcePackFolder) { const rpGroupFolder = useDeveloperFolders === 2 /* FolderDeploy.noFolders */ ? targetFolder : targetFolder.ensureFolder(useDeveloperFolders === 1 /* FolderDeploy.developmentFolders */ ? "development_resource_packs" : "resource_packs"); await rpGroupFolder.ensureExists(); const rpTargetFolder = rpGroupFolder.ensureFolder(activeResourcePackFolder.ensuredName + (useDeveloperFolders === 2 /* FolderDeploy.noFolders */ ? "_rp" : "")); await rpTargetFolder.ensureExists(); await StorageUtilities_1.default.syncFolderTo(activeResourcePackFolder, rpTargetFolder, true, true, false, [ "mcworlds", "db", "level.dat", "level.dat_old", "levelname.txt", "behavior_packs", "resource_packs", ]); if (mcworld) { mcworld.ensureResourcePack(project.defaultResourcePackUniqueId, project.defaultResourcePackVersion, activeResourcePackFolder.name); await rpTargetFolder.saveAll(); } } } static async deployAsWorldAndTestAssets(carto, project, worldProjectItem, returnZipBytes, deployFolder) { let mcworld; const operId = await carto.notifyOperationStarted("Deploying world '" + worldProjectItem.name + "' and test assets."); await worldProjectItem.load(); if (!worldProjectItem.file && !worldProjectItem.folder) { Log_1.default.unexpectedUndefined("DAWATA"); return; } if (worldProjectItem.folder) { mcworld = await MCWorld_1.default.ensureMCWorldOnFolder(worldProjectItem.folder, project); } else if (worldProjectItem.file) { mcworld = await MCWorld_1.default.ensureOnFile(worldProjectItem.file, project); } if (!mcworld) { Log_1.default.debugAlert("Could not find respective world."); return; } const projectBuild = await ProjectExporter.prepareProject(project); if (!projectBuild) { await carto.notifyOperationEnded(operId, "Packaging the world not be completed.", undefined, true); } const dateNow = new Date(); const title = mcworld.name + " - " + Utilities_1.default.getFriendlySummary(dateNow); let targetFolder; let zipStorage; if (deployFolder) { const worldsFolder = await ProjectExporter.ensureWorldsFolder(deployFolder); if (!worldsFolder) { Log_1.default.unexpectedUndefined("DAWATAB"); return; } targetFolder = worldsFolder.ensureFolder(title); await targetFolder.ensureExists(); } else if (returnZipBytes) { zipStorage = new ZipStorage_1.default(); targetFolder = zipStorage.rootFolder; } else { const worldsFolder = await ProjectExporter.ensureMinecraftWorldsFolder(carto); if (!worldsFolder) { Log_1.default.unexpectedUndefined("DAWATAC"); return; } targetFolder = worldsFolder.ensureFolder(title); await targetFolder.ensureExists(); } await mcworld.syncFolderTo(targetFolder); if (projectBuild) { await ProjectExporter.deployProjectPacks(project, projectBuild, targetFolder, mcworld); } const creatorToolsProject = await Database_1.default.ensureCreatorToolsIngameProject(); if (creatorToolsProject) { const ctProjectBuild = await ProjectExporter.prepareProject(creatorToolsProject); if (ctProjectBuild) { await ProjectExporter.deployProjectPacks(creatorToolsProject, ctProjectBuild, targetFolder, mcworld); } await mcworld.save(); } await targetFolder.saveAll(); const newMcWorld = await MCWorld_1.default.ensureMCWorldOnFolder(targetFolder); if (!newMcWorld) { Log_1.default.debugAlert("Could not build new world."); return; } // newMcWorld.betaApisExperiment = true; await targetFolder.saveAll(); await newMcWorld.save(); await carto.notifyOperationEnded(operId, "World + local test assets deploy completed."); if (zipStorage) { const zipBytes = await zipStorage.generateUint8ArrayAsync(); return zipBytes; } return undefined; } static async deployAsWorld(carto, project, worldProjectItem, returnZipBytes, deployFolder) { let mcworld; const operId = await carto.notifyOperationStarted("Deploying world '" + worldProjectItem.name + "'"); await worldProjectItem.load(); if (!worldProjectItem.file && !worldProjectItem.folder) { Log_1.default.unexpectedUndefined("DAWATA"); return; } if (worldProjectItem.folder) { mcworld = await MCWorld_1.default.ensureMCWorldOnFolder(worldProjectItem.folder, project); } else if (worldProjectItem.file) { mcworld = await MCWorld_1.default.ensureOnFile(worldProjectItem.file, project); } if (!mcworld) { Log_1.default.debugAlert("Could not find respective world."); return; } const projectBuild = await ProjectExporter.prepareProject(project); if (!projectBuild) { await carto.notifyOperationEnded(operId, "Packaging the world not be completed.", undefined, true); } const dateNow = new Date(); const title = mcworld.name + " - " + Utilities_1.default.getFriendlySummary(dateNow); let targetFolder; let zipStorage; if (deployFolder) { const worldsFolder = await ProjectExporter.ensureWorldsFolder(deployFolder); if (!worldsFolder) { Log_1.default.unexpectedUndefined("DAWATAB"); return; } targetFolder = worldsFolder.ensureFolder(title); await targetFolder.ensureExists(); } else if (returnZipBytes) { zipStorage = new ZipStorage_1.default(); targetFolder = zipStorage.rootFolder; } else { const worldsFolder = await ProjectExporter.ensureMinecraftWorldsFolder(carto); if (!worldsFolder) { Log_1.default.unexpectedUndefined("DAWATAC"); return; } targetFolder = worldsFolder.ensureFolder(title); await targetFolder.ensureExists(); } await mcworld.syncFolderTo(targetFolder); await targetFolder.saveAll(); await carto.notifyOperationEnded(operId, "World + local assets deploy completed."); if (zipStorage) { const zipBytes = await zipStorage.generateUint8ArrayAsync(); return zipBytes; } return undefined; } static async updateProjects(project) { const pur = new ProjectUpdateRunner_1.default(project); await pur.updateProject(["SCRIPTMODULE"]); } static async generateWorldWithPacks(carto, project, worldSettings, targetFolder) { const operId = await carto.notifyOperationStarted("Generating world and packs for '" + project.name + "'."); const projectBuild = await ProjectExporter.prepareProject(project); if (projectBuild === undefined) { await carto.notifyOperationEnded(operId); return; } let mcworld = undefined; if (targetFolder === undefined) { mcworld = new MCWorld_1.default(); mcworld.ensureZipStorage(); targetFolder = mcworld.effectiveRootFolder; if (targetFolder === undefined) { Log_1.default.throwUnexpectedUndefined("PEPW"); return; } } else { mcworld = await MCWorld_1.default.ensureMCWorldOnFolder(targetFolder); } if (!mcworld) { Log_1.default.debugAlert("Could not find respective world."); return; } await mcworld.load(false); await mcworld.applyWorldSettings(worldSettings); await ProjectExporter.ensureExperimentsEnabledOnWorld(mcworld, project); if (projectBuild) { await ProjectExporter.deployProjectPacks(project, projectBuild, targetFolder, mcworld); } mcworld.name = project.name; await targetFolder.saveAll(); await mcworld.save(); await carto.notifyOperationEnded(operId, "World + local assets generation for '" + targetFolder.fullPath + "' completed."); return mcworld; } static async deployProjectAndGeneratedWorldTo(carto, project, worldSettings, deployFolder) { const operId = await carto.notifyOperationStarted("Deploying project '" + project.name + "' plus world and test assets."); await project.ensureLoadedProjectFolder(); const title = project.name + " Test World"; let targetFolder; if (deployFolder) { const worldsFolder = await ProjectExporter.ensureWorldsFolder(deployFolder); if (!worldsFolder) { Log_1.default.unexpectedUndefined("DPWATAD"); return; } targetFolder = worldsFolder.ensureFolder(title); await targetFolder.ensureExists(); } else { const worldsFolder = await ProjectExporter.ensureMinecraftWorldsFolder(carto); if (!worldsFolder) { Log_1.default.unexpectedUndefined("DPWATAE"); return; } targetFolder = worldsFolder.ensureFolder(title); await targetFolder.ensureExists(); } const mcworld = await ProjectExporter.generateWorldWithPacks(carto, project, worldSettings, targetFolder); if (mcworld) { await targetFolder.saveAll(); await mcworld.save(); } await carto.notifyOperationEnded(operId, "World + local assets deploy to '" + targetFolder.fullPath + "' completed."); return title; } static async deployAsFlatPackRefWorld(carto, project) { await carto.notifyStatusUpdate("Saving..."); await ProjectExporter.updateProjects(project); await project.save(); await carto.notifyStatusUpdate("Saved"); // only do an explicit deploy here autodeployment is not turned on; otherwise, deployment should happen in the save() above. if ( // project.autoDeploymentMode !== ProjectAutoDeploymentMode.deployOnSave && carto.deploymentStorage !== null && carto.deployBehaviorPacksFolder !== null && carto.activeMinecraft) { await carto.notifyStatusUpdate("Deploying pack add-ons"); carto.activeMinecraft.syncWithDeployment(); await carto.notifyStatusUpdate("Deployed"); } const hash = project.defaultBehaviorPackUniqueId + "|"; if ((project.lastMapDeployedHash === undefined || project.lastMapDeployedHash !== hash) && carto.workingStorage !== null) { ProjectExporter.generateAndInvokeFlatPackRefMCWorld(carto, project); project.lastMapDeployedHash = hash; project.lastMapDeployedDate = new Date(); } } static async convertWorld(carto, project, settings, world) { if (!world) { return; } if (carto.workingStorage === null) { Log_1.default.fail("Did not find expected working storage."); return; } const dtNow = new Date(); const tempWorkingPathName = "WorldConvert" + Utilities_1.default.getDateStr(dtNow); const workingFolder = carto.workingStorage.rootFolder.ensureFolder(tempWorkingPathName); await workingFolder.ensureExists(); if (world) { const inputFolder = workingFolder.ensureFolder("source-" + settings.name); await inputFolder.ensureExists(); await world.copyAsFolderTo(inputFolder); } const jsonContent = JSON.stringify(settings); await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.convertFile, jsonContent, true); await workingFolder.load(true); if (workingFolder.folderExists(settings.name)) { const outputFolder = workingFolder.ensureFolder(settings.name); const zs = new ZipStorage_1.default(); await StorageUtilities_1.default.syncFolderTo(outputFolder, zs.rootFolder, false, false, false); const resultBytes = zs.generateCompressedUint8ArrayAsync(); return resultBytes; } return undefined; } static async syncFlatPackRefWorldTo(carto, project, worldFolder, name) { if (carto.workingStorage === null) { Log_1.default.fail("Did not find expected working storage."); return; } const mcworld = await ProjectExporter.generateFlatGameTestWorldWithPackRefs(project, name); if (mcworld !== undefined) { // Log.debugAlert("Synchronizing '" + worldFolder.name + "' with '" + worldFolder.files.length + "' files"); await mcworld.syncFolderTo(worldFolder); } else { Log_1.default.fail("Could not retrieve flat game test world"); } } static async generateAndInvokeFlatPackRefMCWorld(carto, project) { if (carto.workingStorage === null) { Log_1.default.fail("Did not find expected working storage."); return; } const fileName = project.name + " flatpack.mcworld"; const name = project.name + " Flat"; const mcworld = await ProjectExporter.generateFlatGameTestWorldWithPackRefs(project, name); if (mcworld !== undefined) { const newBytes = await mcworld.getBytes(); if (newBytes !== undefined) { const file = carto.workingStorage.rootFolder.ensureFile(fileName); file.setContent(newBytes); await file.saveContent(); if (AppServiceProxy_1.default.hasAppService) { await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.shellOpenPath, file.fullPath); } } } } static async generateFlatGameTestWorldWithPackRefs(project, worldName) { await Database_1.default.loadContent(); if (Database_1.default.contentFolder === null) { Log_1.default.unexpectedContentState(); return undefined; } const file = Database_1.default.contentFolder.ensureFile("flatcreativegt.mcworld"); await file.loadContent(); if (file.content instanceof Uint8Array) { const mcworld = await this.generateBetaApisWorldWithPackRefs(project, worldName, file.content); return mcworld; } Log_1.default.fail("Unexpectedly could not find default content."); return undefined; } static async generateMCAddonAsZip(carto, project, returnAsBlob) { const operId = await carto.notifyOperationStarted("Exporting '" + project.name + "' as MCPack"); const zipStorage = new ZipStorage_1.default(); const projectBuild = await ProjectExporter.prepareProject(project); if (!projectBuild) { return undefined; } await ProjectExporter.deployProjectPacks(project, projectBuild, zipStorage.rootFolder, undefined, 2 /* FolderDeploy.noFolders */); await zipStorage.rootFolder.saveAll(); if (returnAsBlob) { const zipBinary = await zipStorage.generateBlobAsync(); await carto.notifyOperationEnded(operId, "Export MCPack of '" + project.name + "' created; downloading..."); return zipBinary; } else { const zipBytes = await zipStorage.generateUint8ArrayAsync(); return zipBytes; } } static async generateWorldWithPacksAndContent(project, worldName, worldContent, worldSettings) { await project.ensureLoadedProjectFolder(); const mcworld = new MCWorld_1.default(); if (worldContent) { mcworld.loadFromBytes(worldContent); } else if (!worldSettings) { const levelDat = mcworld.ensureLevelData(); levelDat.ensureDefaults(); } if (worldSettings) { mcworld.applyWorldSettings(worldSettings); } mcworld.project = project; const projectBuild = await ProjectExporter.prepareProject(project); if (!projectBuild) { return undefined; } await this.ensureExperimentsEnabledOnWorld(mcworld, project); mcworld.name = worldName; await ProjectExporter.deployProjectPacks(project, projectBuild, mcworld.storage.rootFolder, mcworld); return mcworld; } static async ensureExperimentsEnabledOnWorld(mcworld, project) { const itemsCopy = project.getItemsCopy(); for (const projectItem of itemsCopy) { if (projectItem.itemType === IProjectItemData_1.ProjectItemType.behaviorPackManifestJson) { await projectItem.ensureFileStorage(); if (projectItem.file) { await projectItem.file.loadContent(); let content = projectItem.file.content; if (typeof content === "string" && content.indexOf("-beta") >= 0) { mcworld.betaApisExperiment = true; } } } else if (projectItem.itemType === IProjectItemData_1.ProjectItemType.resourcePackManifestJson) { await projectItem.ensureFileStorage(); if (projectItem.file) { await projectItem.file.loadContent(); let content = projectItem.file.content; if (typeof content === "string" && content.indexOf("pbr") >= 0 && content.indexOf("capabilities") >= 0) { mcworld.deferredTechnicalPreviewExperiment = true; } } } } } static async generateBetaApisWorldWithPackRefs(project, worldName, worldContent) { const mcworld = new MCWorld_1.default(); mcworld.project = project; await mcworld.loadFromBytes(worldContent); const behaviorPackFolder = await project.getDefaultBehaviorPackFolder(); if (behaviorPackFolder !== null) { mcworld.ensureBehaviorPack(project.defaultBehaviorPackUniqueId, project.defaultBehaviorPackVersion, project.name); } const resourcePackFolder = await project.getDefaultResourcePackFolder(); if (resourcePackFolder !== null) { mcworld.ensureResourcePack(project.defaultResourcePackUniqueId, project.defaultResourcePackVersion, project.name); } mcworld.betaApisExperiment = true; mcworld.name = worldName; return mcworld; } } exports.default = ProjectExporter; //# sourceMappingURL=../maps/app/ProjectExporter.js.map