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
Unique identifier for the updater (e.g., “FORMATVER”, “MANIF”).
title
Human-readable name describing what the updater fixes.
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.
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
- Always backup: Consider project state before modifications
- Return meaningful results: Describe exactly what changed
- Handle errors gracefully: Use
internalProcessingError for failures
- Test thoroughly: Updaters modify user projects
- Be idempotent: Running twice should be safe
- Validate changes: Ensure updates actually fix the issue
- Provide clear titles: Help users understand what will happen
- 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
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;
}