@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
171 lines (170 loc) • 7.23 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Database_1 = __importDefault(require("../minecraft/Database"));
const Utilities_1 = __importDefault(require("../core/Utilities"));
/**
* Utility class for managing info generator topic data from form.json files.
* Topic metadata (titles, descriptions, updaters) is stored in form.json files
* in the public/data/forms/mctoolsval/ folder, with each generator having its own form file.
*/
class InfoGeneratorTopicUtilities {
static _topicFormsByGeneratorId = {};
static _loadingPromises = {};
/**
* Gets topic data for a specific generator and topic ID from form.json files.
* Returns undefined if no form file exists for the generator or if the topic is not found.
* @param generatorId The ID of the generator (e.g., "CADDONREQ", "MCFUNCTION")
* @param topicId The numeric topic ID (typically from an enum like 101, 102, etc.)
* @returns The topic data including title and optional updaters, or undefined if not found
*/
static async getTopicData(generatorId, topicId) {
const form = await this.ensureFormLoaded(generatorId);
if (!form) {
return undefined;
}
return this.getTopicDataFromForm(form, topicId);
}
/**
* Gets topic data synchronously from already-loaded form data.
* Returns undefined if the form hasn't been loaded yet or if the topic is not found.
* @param generatorId The ID of the generator
* @param topicId The numeric topic ID
* @returns The topic data or undefined
*/
static getTopicDataSync(generatorId, topicId) {
const normalizedId = generatorId.toLowerCase();
const form = this._topicFormsByGeneratorId[normalizedId];
if (!form || form === null) {
return undefined;
}
return this.getTopicDataFromForm(form, topicId);
}
/**
* Extracts topic data from a form definition for a given topic ID.
* For summary items (topicId 0 or 1), returns the form's root title/description if no specific field is found.
*/
static getTopicDataFromForm(form, topicId) {
if (!form.fields) {
// If no fields but we have form-level title, return it for summary items
if ((topicId === 0 || topicId === 1) && form.title) {
return {
title: form.title,
description: form.description,
};
}
return undefined;
}
const topicIdStr = topicId.toString();
for (const field of form.fields) {
if (field.id === topicIdStr) {
const result = {
title: field.title || Utilities_1.default.humanifyJsName(field.id || ""),
};
// Extract description, howToUse, and technicalDescription if present
if (field.description) {
result.description = field.description;
}
if (field.howToUse) {
result.howToUse = field.howToUse;
}
if (field.technicalDescription) {
result.technicalDescription = field.technicalDescription;
}
// Extract suggestedLineToken for diagnostic line location hints
if (field.suggestedLineToken) {
result.suggestedLineToken = field.suggestedLineToken;
}
// Extract suggestedLineShouldHaveData for data-based line matching
if (field.suggestedLineShouldHaveData) {
result.suggestedLineShouldHaveData = field.suggestedLineShouldHaveData;
}
// Extract updaters from field metadata if present
if (field.matchedValues && Array.isArray(field.matchedValues)) {
const updaters = [];
for (const val of field.matchedValues) {
if (val && typeof val === "object" && "updaterId" in val) {
updaters.push(val);
}
}
if (updaters.length > 0) {
result.updaters = updaters;
}
}
return result;
}
}
// For summary items (topicId 0 or 1 - fail/success), return the form's root title if available
if ((topicId === 0 || topicId === 1) && form.title) {
return {
title: form.title,
description: form.description,
};
}
return undefined;
}
/**
* Ensures that the form.json file for a generator is loaded.
* @param generatorId The ID of the generator
* @returns The form definition or undefined if not found
*/
static async ensureFormLoaded(generatorId) {
const normalizedId = generatorId.toLowerCase();
// Check if already loaded (null means "checked and not found")
if (normalizedId in this._topicFormsByGeneratorId) {
return this._topicFormsByGeneratorId[normalizedId] ?? undefined;
}
// Check if currently loading
const loadingPromise = this._loadingPromises[normalizedId];
if (loadingPromise) {
const result = await loadingPromise;
return result ?? undefined;
}
// Start loading
this._loadingPromises[normalizedId] = this.loadForm(normalizedId);
const form = await this._loadingPromises[normalizedId];
// Cache result: store null for missing forms to avoid re-fetching
this._topicFormsByGeneratorId[normalizedId] = form ?? null;
delete this._loadingPromises[normalizedId];
return form ?? undefined;
}
/**
* Loads a form.json file for a generator.
*/
static async loadForm(generatorId) {
try {
const form = await Database_1.default.ensureFormLoaded("mctoolsval", generatorId);
return form ?? null;
}
catch {
// Form file doesn't exist for this generator - that's OK
return null;
}
}
/**
* Checks if a form is loaded for a generator.
*/
static isFormLoaded(generatorId) {
return this._topicFormsByGeneratorId[generatorId.toLowerCase()] !== undefined;
}
/**
* Preloads forms for all known generators.
* This can be called at startup to ensure all forms are available synchronously later.
*/
static async preloadAllForms(generatorIds) {
const loadPromises = generatorIds.map((id) => this.ensureFormLoaded(id));
await Promise.all(loadPromises);
}
/**
* Clears all cached forms. Useful for testing or hot-reloading.
*/
static clearCache() {
this._topicFormsByGeneratorId = {};
this._loadingPromises = {};
}
}
exports.default = InfoGeneratorTopicUtilities;