Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/mojang/minecraft-creator-tools/llms.txt

Use this file to discover all available pages before exploring further.

Project updaters provide automated fixes for issues found during validation. They modify project files to resolve specific problems.

IProjectUpdater Interface

interface IProjectUpdater {
  update(project: Project, updateId: number): Promise<ProjectUpdateResult[]>;

  id: string;
  title: string;

  getUpdateIds(): number[];
  getUpdaterData(updaterId: number): IProjectUpdaterData;
}

Properties

id

Unique identifier for the updater (e.g., “FORMATVER”, “MANIF”).
id: string;

title

Human-readable name describing what the updater fixes.
title: string;

Methods

update()

Performs the update operation on a project.
update(
  project: Project,
  updateId: number
): Promise<ProjectUpdateResult[]>
Parameters:
  • project - The project to update
  • updateId - Specific update to perform (from getUpdateIds())
Returns: Array of update results describing what changed Example:
async update(project: Project, updateId: number): Promise<ProjectUpdateResult[]> {
  const results: ProjectUpdateResult[] = [];

  switch (updateId) {
    case 100:
      // Perform specific update
      const result = await this.fixManifestVersion(project);
      results.push(result);
      break;
  }

  return results;
}

getUpdateIds()

Returns all update IDs supported by this updater.
getUpdateIds(): number[]
Returns: Array of numeric update identifiers Example:
getUpdateIds(): number[] {
  return [100, 101, 102];  // Three different updates
}

getUpdaterData()

Returns metadata for a specific update.
getUpdaterData(updaterId: number): IProjectUpdaterData
Parameters:
  • updaterId - The update ID to get data for
Returns: Metadata describing the update
interface IProjectUpdaterData {
  title: string;  // Description of what this specific update does
}
Example:
getUpdaterData(updaterId: number): IProjectUpdaterData {
  switch (updaterId) {
    case 100:
      return { title: "Update manifest format version" };
    case 101:
      return { title: "Fix UUID format" };
    default:
      return { title: "Unknown update" };
  }
}

Update Results

Updaters return ProjectUpdateResult objects describing changes:
const result = new ProjectUpdateResult(
  UpdateResultType.updatedFile,     // Result type
  "MYUPDATER",                      // Updater ID
  100,                              // Update index
  "Fixed manifest version",         // Description
  projectItem,                      // Optional: affected item
  "1.20.0",                         // Optional: additional data
  "manifest",                       // Optional: item identifier
  "{\"format_version\": ...}"       // Optional: content before update
);

Update Result Types

enum UpdateResultType {
  updatedFile = 1,              // File was modified
  noChange = 0,                 // No changes needed
  internalProcessingError = 99  // Error occurred during update
}

Example Updater Implementation

export default class CustomUpdater implements IProjectUpdater {
  id = "CUSTOM";
  title = "Custom Fixes";

  getUpdateIds(): number[] {
    return [100, 101];
  }

  getUpdaterData(updaterId: number): IProjectUpdaterData {
    switch (updaterId) {
      case 100:
        return { title: "Fix component formatting" };
      case 101:
        return { title: "Update deprecated fields" };
      default:
        return { title: "Unknown" };
    }
  }

  async update(
    project: Project,
    updateId: number
  ): Promise<ProjectUpdateResult[]> {
    const results: ProjectUpdateResult[] = [];

    switch (updateId) {
      case 100:
        results.push(...await this.fixComponentFormatting(project));
        break;
      case 101:
        results.push(...await this.updateDeprecatedFields(project));
        break;
    }

    return results;
  }

  private async fixComponentFormatting(
    project: Project
  ): Promise<ProjectUpdateResult[]> {
    const results: ProjectUpdateResult[] = [];

    // Find items that need fixing
    const items = project.getItemsCopy();

    for (const item of items) {
      if (item.itemType === ProjectItemType.entityTypeBehavior) {
        await item.ensureStorage();
        const file = item.file;

        if (file) {
          // Read current content
          const content = await file.loadContent();
          const json = JSON.parse(content);

          // Make changes
          let modified = false;
          if (json["minecraft:entity"]?.components) {
            // Fix something
            modified = true;
          }

          if (modified) {
            // Write back
            await file.setContent(JSON.stringify(json, null, 2));

            results.push(
              new ProjectUpdateResult(
                UpdateResultType.updatedFile,
                this.id,
                100,
                `Fixed formatting in ${item.name}`,
                item
              )
            );
          } else {
            results.push(
              new ProjectUpdateResult(
                UpdateResultType.noChange,
                this.id,
                100,
                `No changes needed for ${item.name}`,
                item
              )
            );
          }
        }
      }
    }

    return results;
  }

  private async updateDeprecatedFields(
    project: Project
  ): Promise<ProjectUpdateResult[]> {
    // Similar implementation
    return [];
  }
}

Running Updaters

Updaters are executed through the ProjectUpdateRunner:
const runner = new ProjectUpdateRunner(project);

// Run a specific update
const results = await runner.update("CUSTOM", 100);

// Run all updates from specific updaters
const allResults = await runner.updateProject(
  ["CUSTOM", "FORMATVER"],  // Include these
  ["DEPRECATED"]            // Exclude these
);

Linking Updaters to Validation

Connect updaters to validation issues through topic data:
// In your info generator
getTopicData(topicId: number): IProjectInfoTopicData {
  return {
    title: "Component Formatting Issue",
    updaters: [
      {
        updaterId: "CUSTOM",    // Updater ID
        updaterIndex: 100,      // Update ID
        action: "Fix formatting" // User-facing action
      }
    ]
  };
}
This allows the UI to offer “Fix” buttons for validation errors.

Registering Updaters

Add your updater to the registration list:
// In GeneratorRegistrations.ts
static updaters = [
  new FormatVersionUpdater(),
  new CustomUpdater(),  // Your updater
  // ...
];

Best Practices

  1. Always backup: Consider project state before modifications
  2. Return meaningful results: Describe exactly what changed
  3. Handle errors gracefully: Use internalProcessingError for failures
  4. Test thoroughly: Updaters modify user projects
  5. Be idempotent: Running twice should be safe
  6. Validate changes: Ensure updates actually fix the issue
  7. Provide clear titles: Help users understand what will happen
  8. Log operations: Track what was changed for debugging

Safety Considerations

Updaters modify project files. Always:
  • Test with sample projects first
  • Validate JSON before writing
  • Check file permissions
  • Handle concurrent access
  • Preserve file formatting when possible

Example: Format Version Updater

A typical updater might fix format versions in manifests:
async update(project: Project, updateId: number): Promise<ProjectUpdateResult[]> {
  const results: ProjectUpdateResult[] = [];
  
  const manifests = project.getItemsByType(ProjectItemType.manifest);
  
  for (const manifest of manifests) {
    const file = manifest.file;
    if (!file) continue;
    
    const content = await file.loadContent();
    const json = JSON.parse(content);
    
    const oldVersion = json.format_version;
    const newVersion = 2; // Current format
    
    if (oldVersion !== newVersion) {
      json.format_version = newVersion;
      await file.setContent(JSON.stringify(json, null, 2));
      
      results.push(
        new ProjectUpdateResult(
          UpdateResultType.updatedFile,
          this.id,
          updateId,
          `Updated format version from ${oldVersion} to ${newVersion}`,
          manifest,
          `${oldVersion}${newVersion}`
        )
      );
    }
  }
  
  return results;
}

Build docs developers (and LLMs) love