Skip to main content
Minecraft Creator Tools provides a ServerManager for running local Minecraft servers to test your add-ons and worlds in a controlled environment.

Overview

The ServerManager handles:
  • Local Minecraft server lifecycle
  • Project deployment to test environments
  • HTTP web services for editor communication
  • World backup management
  • Port allocation for multiple servers
Reference: app/src/local/ServerManager.ts:1

Server Manager Setup

Initialization

import ServerManager from "./local/ServerManager";
import LocalEnvironment from "./local/LocalEnvironment";
import CreatorTools from "./app/CreatorTools";

// Create environment and manager
const env = new LocalEnvironment(utilities);
const creatorTools = new CreatorTools();
const serverManager = new ServerManager(env, creatorTools);

// Configure features
serverManager.features = ServerManagerFeatures.all;

Server Features

Control which features are enabled:
enum ServerManagerFeatures {
  all = 0,              // All features enabled
  allWebServices = 1,   // All web services
  basicWebServices = 2  // Basic web services only
}

Working with Servers

Starting the HTTP Server

The HTTP server enables communication between the editor and Minecraft:
// Ensure HTTP server is running
const httpServer = serverManager.ensureHttpServer();

// The server is accessible at:
// http://localhost:{port}
The HTTP server is used for live reload, debugging, and editor integration features.

Port Management

Servers use a slot-based port allocation system:
// Default Minecraft server port is 19132 (slot 0)
const basePort = serverManager.getBasePortForSlot(0); // 19132

// Additional servers use incremental slots
const slot1Port = serverManager.getBasePortForSlot(1); // 19196 (19132 + 64)
const slot2Port = serverManager.getBasePortForSlot(2); // 19260 (19132 + 128)
Port Allocation Formula:
port = 19132 + (slotNumber * 64)

Preview vs. Release Tracks

Choose which Minecraft version to use:
import { MinecraftTrack } from "./app/ICreatorToolsData";

// Use preview builds
serverManager.usePreview = true;

// Or use release builds
serverManager.usePreview = false;

// Check effective track
if (serverManager.effectiveIsUsingPreview) {
  console.log("Using Minecraft Preview");
}

Deploying Projects

Deploy to Development Folders

Deploy directly to Minecraft’s development folders:
import ProjectExporter from "./app/ProjectExporter";
import { FolderDeploy } from "./app/ProjectExporter";

// Deploy to development_behavior_packs and development_resource_packs
await ProjectExporter.deployProject(
  creatorTools,
  project,
  deployTargetFolder
);
1

Prepare the project

Build and validate the project:
const projectBuild = await ProjectExporter.prepareProject(project);

if (!projectBuild) {
  console.error("Project has build errors");
  return;
}
2

Deploy packs

Copy packs to target folder:
await ProjectExporter.deployProjectPacks(
  project,
  projectBuild,
  deployTargetFolder,
  undefined,
  FolderDeploy.developmentFolders
);
3

Save changes

Ensure all files are written:
await deployTargetFolder.saveAll();

Folder Deploy Options

enum FolderDeploy {
  retailFolders = 0,      // behavior_packs, resource_packs
  developmentFolders = 1, // development_behavior_packs, development_resource_packs  
  noFolders = 2          // No subfolder structure
}

Working with Worlds

Deploy as Test World

Create a world with your add-ons for testing:
import { Generator } from "./minecraft/WorldLevelDat";

// Generate a flat world with beta APIs enabled
const worldSettings = {
  generator: Generator.flat,
  betaApisExperiment: true
};

const mcworld = await ProjectExporter.generateWorldWithPacks(
  creatorTools,
  project,
  worldSettings,
  targetFolder
);

Deploy World with Project

Deploy an existing world with your test assets:
await ProjectExporter.deployAsWorldAndTestAssets(
  creatorTools,
  project,
  worldProjectItem,
  false, // returnZipBytes
  deployFolder
);
  • The world data (level.dat, db/, etc.)
  • Your behavior pack (in world’s behavior_packs/)
  • Your resource pack (in world’s resource_packs/)
  • Pack references in world manifests
  • Enabled experiments (like beta APIs)

World Settings

Customize world generation and features:
interface IWorldSettings {
  generator?: Generator;           // flat, infinite, etc.
  betaApisExperiment?: boolean;   // Enable beta APIs
  seed?: string;                  // World seed
  gameType?: number;              // Survival, creative, etc.
  difficulty?: number;            // Peaceful, easy, etc.
}

Live Development Workflow

Hot Reload Setup

1

Start HTTP server

const httpServer = serverManager.ensureHttpServer();
2

Deploy to development folders

await ProjectExporter.deployProject(
  creatorTools,
  project,
  deployTargetFolder
);
3

Watch for changes

Monitor project files and redeploy on changes:
// Pseudo-code for file watching
fileWatcher.on('change', async (file) => {
  await project.inferProjectItemsFromFiles(true);
  await ProjectExporter.deployProject(
    creatorTools,
    project,
    deployTargetFolder
  );
});

Auto-deployment on Save

// Configure auto-deployment
project.autoDeploymentMode = ProjectAutoDeploymentMode.deployOnSave;

// When you save, deployment happens automatically
await project.save();
// Packs are deployed to Minecraft folder

Backup Management

The server manager can back up world files:
// Store world file listings for backup
serverManager.backupWorldFileListings = {
  "world_name": {
    files: ["level.dat", "db/000123.ldb", ...],
    folders: ["db", "behavior_packs", ...]
  }
};

Practical Examples

Example 1: Quick Test Deploy

async function quickDeploy(project: Project) {
  // Prepare project
  const projectBuild = await ProjectExporter.prepareProject(project);
  if (!projectBuild) {
    throw new Error("Project build failed");
  }
  
  // Get deployment target
  const deployTarget = creatorTools.defaultDeploymentTarget;
  if (!deployTarget) {
    throw new Error("No deployment target configured");
  }
  
  // Deploy to development folders
  await ProjectExporter.deployProjectPacks(
    project,
    projectBuild,
    deployTarget.deployBehaviorPacksFolder!,
    undefined,
    FolderDeploy.developmentFolders
  );
  
  console.log("Deployed successfully!");
}

Example 2: Create Test World

async function createTestWorld(project: Project, worldName: string) {
  // Define world settings
  const worldSettings = {
    generator: Generator.flat,
    betaApisExperiment: true,
    gameType: 1, // Creative
    difficulty: 0 // Peaceful
  };
  
  // Get worlds folder
  const worldsFolder = await ProjectExporter.ensureMinecraftWorldsFolder(
    creatorTools
  );
  
  if (!worldsFolder) {
    throw new Error("Cannot access worlds folder");
  }
  
  // Create world folder
  const worldFolder = worldsFolder.ensureFolder(worldName);
  await worldFolder.ensureExists();
  
  // Generate world with packs
  const mcworld = await ProjectExporter.generateWorldWithPacks(
    creatorTools,
    project,
    worldSettings,
    worldFolder
  );
  
  await mcworld?.save();
  console.log(`Test world created: ${worldName}`);
}

Example 3: Deploy and Launch

async function deployAndLaunch(project: Project) {
  // Deploy project
  await quickDeploy(project);
  
  // Create flat test world
  await createTestWorld(project, `${project.name} Test`);
  
  // On desktop, could launch Minecraft here
  if (AppServiceProxy.hasAppService) {
    await AppServiceProxy.sendAsync(
      AppServiceProxyCommands.launchMinecraft,
      worldName
    );
  }
}

Example 4: Multi-Project Testing

async function deployMultipleProjects(
  projects: Project[],
  worldName: string
) {
  // Create shared test world
  const worldFolder = await createWorldFolder(worldName);
  const mcworld = new MCWorld();
  mcworld.folder = worldFolder;
  
  // Deploy each project to the world
  for (const project of projects) {
    const projectBuild = await ProjectExporter.prepareProject(project);
    if (!projectBuild) continue;
    
    await ProjectExporter.deployProjectPacks(
      project,
      projectBuild,
      worldFolder,
      mcworld,
      FolderDeploy.noFolders
    );
    
    // Add pack references to world
    mcworld.ensureBehaviorPack(
      project.defaultBehaviorPackUniqueId,
      project.defaultBehaviorPackVersion,
      project.name
    );
  }
  
  await mcworld.save();
  await worldFolder.saveAll();
}

Server Lifecycle

Shutdown Handling

// Subscribe to shutdown events
serverManager.onShutdown.subscribe((manager, message) => {
  console.log(`Server shutting down: ${message}`);
  // Clean up resources
});

// Trigger shutdown
await serverManager.shutdown("User requested shutdown");

Cleanup

// Stop web server
serverManager.stopWebServer();

// Full shutdown with cleanup
await serverManager.shutdown("Application closing");

Best Practices

Use development folders

Deploy to development_* folders to avoid conflicts with retail packs.

Enable experiments

Always enable betaApisExperiment when testing beta script APIs.

Validate before deploy

Run validation to catch errors before deployment.

Clean deploys

Delete old deployment folders before deploying to avoid stale files.

Troubleshooting

Ensure creatorTools.defaultDeploymentStorage is configured:
const available = await creatorTools.defaultDeploymentStorage?.getAvailable();
if (!available) {
  console.error("Deployment storage not available");
}
Check:
  • World was deployed to correct folder (minecraftWorlds)
  • level.dat exists and is valid
  • World manifest is properly formatted
  • Minecraft was restarted after deployment
Verify:
  • Pack references in world_behavior_packs.json
  • Pack UUIDs match manifest.json
  • Packs are in correct folders within world
  • Experiments are enabled if needed
Use a different slot:
const port = serverManager.getBasePortForSlot(1);
Or check for conflicts with other services.

Build docs developers (and LLMs) love