@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
148 lines (147 loc) • 7.54 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 });
exports.ContentWriter = void 0;
const StorageUtilities_1 = __importDefault(require("../storage/StorageUtilities"));
const Log_1 = __importDefault(require("../core/Log"));
/**
* Extract the filename from a relative path like "entities/orc.json" → "orc.json".
*/
function getFilename(filePath) {
const parts = filePath.split("/");
return parts[parts.length - 1];
}
/**
* Serialize a generated file's content to a string or Uint8Array suitable for writing.
*/
function serializeContent(generatedFile) {
if (generatedFile.content instanceof Uint8Array) {
return generatedFile.content;
}
if (typeof generatedFile.content === "string") {
return generatedFile.content;
}
return JSON.stringify(generatedFile.content, null, 2);
}
/**
* Write a list of generated files to a specific subfolder within a pack folder.
*/
function writeFilesToSubfolder(packFolder, subfolderName, files) {
if (files.length === 0)
return;
const subfolder = packFolder.ensureFolder(subfolderName);
for (const file of files) {
StorageUtilities_1.default.writeFileIfNew(subfolder, getFilename(file.path), serializeContent(file));
}
}
/**
* Write a singleton JSON file (terrain_texture.json, item_texture.json, blocks.json, etc.)
* by deep-merging with any existing content so that previously-added entries are preserved.
*/
function writeSingletonJsonMerging(folder, fileName, newContent) {
const file = folder.ensureFile(fileName);
if (file.isContentLoaded || folder.fileExists(fileName)) {
const existing = StorageUtilities_1.default.getJsonObject(file);
if (existing && typeof existing === "object") {
const merged = StorageUtilities_1.default.deepMergeJsonObjects(existing, newContent);
file.setContent(JSON.stringify(merged, null, 2));
return;
}
}
file.setContent(JSON.stringify(newContent, null, 2));
}
class ContentWriter {
/**
* Write all generated content files to a project's behavior pack and resource pack folders.
*
* @param project The project to write content into.
* @param content The generated content from ContentGenerator.generate().
*/
static async writeGeneratedContent(project, content) {
const bpFolder = await project.ensureDefaultBehaviorPackFolder();
const rpFolder = await project.ensureDefaultResourcePackFolder();
// === Behavior Pack ===
if (bpFolder) {
writeFilesToSubfolder(bpFolder, "entities", content.entityBehaviors);
writeFilesToSubfolder(bpFolder, "blocks", content.blockBehaviors);
writeFilesToSubfolder(bpFolder, "items", content.itemBehaviors);
writeFilesToSubfolder(bpFolder, "loot_tables", content.lootTables);
writeFilesToSubfolder(bpFolder, "recipes", content.recipes);
writeFilesToSubfolder(bpFolder, "spawn_rules", content.spawnRules);
}
// === Resource Pack ===
if (rpFolder) {
writeFilesToSubfolder(rpFolder, "entity", content.entityResources);
// Render controllers
writeFilesToSubfolder(rpFolder, "render_controllers", content.renderControllers);
// Geometries — determine subfolder from path (e.g., "models/blocks/slab.geo.json" → "blocks")
for (const geometryFile of content.geometries) {
const pathParts = geometryFile.path.split("/");
const subfolderName = pathParts.length >= 2 ? pathParts[pathParts.length - 2] : "entity";
const modelsFolder = rpFolder.ensureFolder("models");
const subFolder = modelsFolder.ensureFolder(subfolderName);
StorageUtilities_1.default.writeFileIfNew(subFolder, getFilename(geometryFile.path), serializeContent(geometryFile));
}
// Textures — determine subfolder from path and handle binary content
for (const textureFile of content.textures) {
const pathParts = textureFile.path.split("/");
const subfolderName = pathParts.length >= 2 ? pathParts[pathParts.length - 2] : "entity";
const texturesFolder = rpFolder.ensureFolder("textures");
const subFolder = texturesFolder.ensureFolder(subfolderName);
const fileName = getFilename(textureFile.path);
if (subFolder.fileExists(fileName)) {
Log_1.default.debug(`Skipping texture "${fileName}" — file already exists`);
continue;
}
const file = subFolder.ensureFile(fileName);
if (textureFile.content instanceof Uint8Array) {
file.setContent(textureFile.content);
}
else if (Array.isArray(textureFile.content)) {
file.setContent(new Uint8Array(textureFile.content));
}
else if (typeof textureFile.content === "string") {
file.setContent(textureFile.content);
}
else {
Log_1.default.debug(`WARNING: Texture content is object, will serialize as JSON`);
file.setContent(JSON.stringify(textureFile.content, null, 2));
}
}
// terrain_texture.json — block texture atlas (merge with existing)
if (content.terrainTextures) {
const texturesFolder = rpFolder.ensureFolder("textures");
writeSingletonJsonMerging(texturesFolder, "terrain_texture.json", content.terrainTextures.content);
}
// item_texture.json — item texture atlas (merge with existing)
if (content.itemTextures) {
const texturesFolder = rpFolder.ensureFolder("textures");
writeSingletonJsonMerging(texturesFolder, "item_texture.json", content.itemTextures.content);
}
// blocks.json — block resource catalog (merge with existing)
if (content.blocksCatalog) {
writeSingletonJsonMerging(rpFolder, getFilename(content.blocksCatalog.path), content.blocksCatalog.content);
}
// sound_definitions.json (merge with existing)
if (content.soundDefinitions) {
writeSingletonJsonMerging(rpFolder, getFilename(content.soundDefinitions.path), content.soundDefinitions.content);
}
// music_definitions.json (merge with existing)
if (content.musicDefinitions) {
writeSingletonJsonMerging(rpFolder, getFilename(content.musicDefinitions.path), content.musicDefinitions.content);
}
// Additional sounds (singleton files that should be merged)
for (const soundFile of content.sounds) {
const pathParts = soundFile.path.split("/");
const targetFolder = pathParts.length >= 2 ? rpFolder.ensureFolder(pathParts.slice(0, -1).join("/")) : rpFolder;
writeSingletonJsonMerging(targetFolder, getFilename(soundFile.path), soundFile.content);
}
}
await project.save();
}
}
exports.ContentWriter = ContentWriter;