UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

446 lines (445 loc) 17.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const CreatorTools_1 = require("../app/CreatorTools"); const IMinecraft_1 = require("../app/IMinecraft"); const AppServiceProxy_1 = __importStar(require("../core/AppServiceProxy")); const ste_events_1 = require("ste-events"); const Log_1 = __importDefault(require("../core/Log")); const Utilities_1 = __importDefault(require("../core/Utilities")); const ProjectExporter_1 = __importDefault(require("../app/ProjectExporter")); const GameStateManager_1 = __importDefault(require("../minecraft/GameStateManager")); const ICreatorToolsData_1 = require("../app/ICreatorToolsData"); const Status_1 = require("../app/Status"); class ProcessHostedMinecraft { _creatorTools; _project; _gameStateManager; errorStatus; errorMessage; state; dedicatedServerStorage; _dsDeployBehaviorPacksFolder; worldFolder; projectFolder; worldContentStorage; worldProject; _onWorldStorageReady = new ste_events_1.EventDispatcher(); _onProjectStorageReady = new ste_events_1.EventDispatcher(); _onMessage = new ste_events_1.EventDispatcher(); _onStateChanged = new ste_events_1.EventDispatcher(); _onRefreshed = new ste_events_1.EventDispatcher(); // Debug event dispatchers for IPC-bridged debug data _onDebugConnected = new ste_events_1.EventDispatcher(); _onDebugDisconnected = new ste_events_1.EventDispatcher(); _onDebugStats = new ste_events_1.EventDispatcher(); _onDebugPaused = new ste_events_1.EventDispatcher(); _onDebugResumed = new ste_events_1.EventDispatcher(); _onDebugProfilerState = new ste_events_1.EventDispatcher(); _onProfilerCapture = new ste_events_1.EventDispatcher(); get onWorldFolderReady() { return this._onWorldStorageReady.asEvent(); } get onProjectFolderReady() { return this._onProjectStorageReady.asEvent(); } get onDebugConnected() { return this._onDebugConnected.asEvent(); } get onDebugDisconnected() { return this._onDebugDisconnected.asEvent(); } get onDebugStats() { return this._onDebugStats.asEvent(); } get onDebugPaused() { return this._onDebugPaused.asEvent(); } get onDebugResumed() { return this._onDebugResumed.asEvent(); } get onDebugProfilerState() { return this._onDebugProfilerState.asEvent(); } get onProfilerCapture() { return this._onProfilerCapture.asEvent(); } get onMessage() { return this._onMessage.asEvent(); } get gameStateManager() { return this._gameStateManager; } get onRefreshed() { return this._onRefreshed.asEvent(); } get onStateChanged() { return this._onStateChanged.asEvent(); } get activeProject() { return this._project; } set activeProject(newProject) { this._project = newProject; } get canDeployFiles() { return true; } constructor(creatorTools) { this._creatorTools = creatorTools; this._gameStateManager = new GameStateManager_1.default(this._creatorTools); this.dedicatedServerStorage = null; this.state = CreatorTools_1.CreatorToolsMinecraftState.none; this._dsDeployBehaviorPacksFolder = null; this.updateStatus(); } async updateStatus() { const result = await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.getDedicatedServerStatus, ""); if (result) { let resultNum = -1; try { resultNum = parseInt(result); } catch (e) { } if (resultNum >= 0) { if (resultNum === 1) { this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.stopped); } else if (resultNum === 2) { this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.initializing); } else if (resultNum === 3) { this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.preparing); } else if (resultNum === 4) { this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.starting); } else if (resultNum === 5) { this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.started); } } } return this.state; } async prepare(force) { } processExternalMessage(command, data) { switch (command) { case "dedicatedServerStarted": this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.started); if (!this._creatorTools.successfullyStartedMinecraftServer) { this._creatorTools.successfullyStartedMinecraftServer = true; this._creatorTools.save(); } this._initWorldFolderOnStart(); break; case "dedicatedServerRefreshed": this.notifyRefreshed(); break; case "dedicatedServerStopped": this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.stopped); break; case "dedicatedServerGameEvents": this.notifyGameEvents(data); break; case "dedicatedServerMessage": this._creatorTools.notifyStatusUpdate("Server: " + data, Status_1.StatusTopic.minecraft); break; case "dedicatedServerError": this._creatorTools.notifyStatusUpdate("Server Error: " + data, Status_1.StatusTopic.minecraft); break; case "dedicatedServerDebugConnected": try { const connBody = JSON.parse(data); this._onDebugConnected.dispatch(this, connBody); } catch (e) { Log_1.default.debug("Failed to parse debugConnected IPC: " + e); } break; case "dedicatedServerDebugDisconnected": try { const discBody = JSON.parse(data); this._onDebugDisconnected.dispatch(this, discBody); } catch (e) { Log_1.default.debug("Failed to parse debugDisconnected IPC: " + e); } break; case "dedicatedServerDebugStats": try { const statsBody = JSON.parse(data); this._onDebugStats.dispatch(this, statsBody); } catch (e) { Log_1.default.debug("Failed to parse debugStats IPC: " + e); } break; case "dedicatedServerDebugPaused": try { const pauseBody = JSON.parse(data); this._onDebugPaused.dispatch(this, pauseBody); } catch (e) { Log_1.default.debug("Failed to parse debugPaused IPC: " + e); } break; case "dedicatedServerDebugResumed": try { const resumeBody = JSON.parse(data); this._onDebugResumed.dispatch(this, resumeBody); } catch (e) { Log_1.default.debug("Failed to parse debugResumed IPC: " + e); } break; case "dedicatedServerDebugProfilerState": try { const profStateBody = JSON.parse(data); this._onDebugProfilerState.dispatch(this, profStateBody); } catch (e) { Log_1.default.debug("Failed to parse debugProfilerState IPC: " + e); } break; case "dedicatedServerProfilerCapture": try { const captBody = JSON.parse(data); this._onProfilerCapture.dispatch(this, captBody); } catch (e) { Log_1.default.debug("Failed to parse profilerCapture IPC: " + e); } break; } } async initialize() { await this.start(); } get dedicatedServerBehaviorPacksFolder() { return this._dsDeployBehaviorPacksFolder; } notifyGameEvents(data) { let obj = undefined; try { obj = JSON.parse(data); } catch (e) { } if (!obj || !obj.length) { return; } for (let i = 0; i < obj.length; i++) { const event = obj[i]; this._gameStateManager?.handleEvent(event); } } _updateDedicatedServerStorage() { if (this._creatorTools.ensureLocalFolder === undefined || !AppServiceProxy_1.default.hasAppService || this._creatorTools.dedicatedServerPath === undefined) { return; } const folder = this._creatorTools.ensureLocalFolder(this._creatorTools.dedicatedServerPath); this.dedicatedServerStorage = folder.storage; if (this.dedicatedServerStorage != null) { this._dsDeployBehaviorPacksFolder = this.dedicatedServerStorage.rootFolder.ensureFolder("development_behavior_packs"); } else { this._dsDeployBehaviorPacksFolder = null; } } /** * Send a debug pause command to the main process. */ async debugPause() { await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.debugPause, ""); } /** * Send a debug resume command to the main process. */ async debugResume() { await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.debugResume, ""); } /** * Send a debug start profiler command to the main process. */ async debugStartProfiler() { await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.debugStartProfiler, ""); } /** * Send a debug stop profiler command to the main process. */ async debugStopProfiler() { await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.debugStopProfiler, ""); } /** * When the dedicated server starts, query the main process for the world folder path * via IPC so that the world map and debug stats panels appear in MinecraftDisplay * immediately, without requiring a deploy operation first. */ async _initWorldFolderOnStart() { if (this.worldFolder) { return; // Already set from a previous deploy } // Ask the main process for the world folder path - this works regardless of // whether dedicatedServerPath is set (auto mode vs manual mode) const worldPath = await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.getDedicatedServerWorldDeployDir, ""); if (worldPath && worldPath.length > 0 && this._creatorTools.ensureLocalFolder) { const worldFolder = this._creatorTools.ensureLocalFolder(worldPath); this.worldFolder = worldFolder; this._onWorldStorageReady.dispatch(this, worldFolder); } } notifyStateChanged(newVal) { this.state = newVal; this._onStateChanged.dispatch(this, newVal); } notifyRefreshed(newVal) { if (newVal) { this.state = newVal; } this._onRefreshed.dispatch(this, this.state); } async start() { const path = this.getDedicatedServerSyntax(); this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.starting); await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.startDedicatedServer, path); } async prepareDedicatedServer(project) { await this.syncWithDeployment(); return await this.deployDedicatedServerWorld(project); } async restartDedicatedServer(project) { await this.stop(); await this.prepareDedicatedServer(project); await this.start(); } canPrepare() { return true; } async prepareAndStart(push) { let worldName = undefined; if (this._project) { worldName = await this.prepareDedicatedServer(this._project); } await this.start(); return { type: IMinecraft_1.PrepareAndStartResultType.started, worldName: worldName, }; } async syncWithDeployment() { if (this._creatorTools.ensureLocalFolder == null) { throw new Error("This instance doesn't support deployment"); } if (!this._project) { return; } const folderPath = await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.getDedicatedServerProjectDeployDir, ""); if (folderPath && folderPath.length > 0) { const deployFolder = this._creatorTools.ensureLocalFolder(folderPath); const deployFolderExists = deployFolder; if (deployFolderExists) { await ProjectExporter_1.default.deployProject(this._creatorTools, this._project, deployFolder); } } } async runCommand(command) { const result = await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.dedicatedServerCommand, command); return result; } async runActionSet(actionSet) { return undefined; } async deployDedicatedServerWorld(project) { if (this.dedicatedServerStorage === null) { return; } const worldFolderName = project.deployWorldId; const worldDisplayName = project.name + " _mct"; const worldFolder = this.dedicatedServerStorage.rootFolder.ensureFolder("worlds").ensureFolder(worldFolderName); await worldFolder.ensureExists(); await ProjectExporter_1.default.syncFlatPackRefWorldTo(this._creatorTools, project, worldFolder, worldDisplayName); await worldFolder.saveAll(); await project.save(); this.worldFolder = worldFolder; this._onWorldStorageReady.dispatch(this, worldFolder); return worldDisplayName; } getDedicatedServerSyntax() { if (!this._creatorTools.worldSettings) { Log_1.default.debugAlert("World settings are not defined."); throw new Error(); } if (this._creatorTools.dedicatedServerMode !== ICreatorToolsData_1.DedicatedServerMode.auto && (this._creatorTools.dedicatedServerPath === null || this._creatorTools.dedicatedServerPath === undefined)) { Log_1.default.debugAlert("Server folder path is not defined, and the path cannot be set."); throw new Error(); } let path = this._creatorTools.dedicatedServerPath; if (!path) { path = ""; } let worldSettings = this._creatorTools.worldSettings; if (this._project && this._project.worldSettings) { if (this._project.worldSettings.useCustomSettings) { worldSettings = this._project.worldSettings; } } if (!worldSettings.name) { worldSettings.name = "world"; } const mess = { path: Utilities_1.default.ensureEndsWithBackSlash(path), iagree: this._creatorTools .iAgreeToTheMinecraftEndUserLicenseAgreementAndPrivacyStatementAtMinecraftDotNetSlashEula ? true : false, mode: this._creatorTools.dedicatedServerMode, track: this._creatorTools.track, worldSettings: worldSettings, }; return JSON.stringify(mess); } async stop() { const path = this.getDedicatedServerSyntax(); this.notifyStateChanged(CreatorTools_1.CreatorToolsMinecraftState.stopping); await AppServiceProxy_1.default.sendAsync(AppServiceProxy_1.AppServiceProxyCommands.stopDedicatedServer, path); } } exports.default = ProcessHostedMinecraft;