@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
208 lines (207 loc) • 7.95 kB
TypeScript
/**
* ModelDesignUtilities
*
* Converts MCP model design format to Minecraft .geo.json format
* and generates texture atlases from per-face SVG/color specifications.
*/
import { IMcpModelDesign, IMcpFaceContent, IMcpColorRGBA, IMcpTextureDefinition, IMcpNoiseConfig, IMcpTexturedRectangle, IMcpPixelArt } from "./IMcpModelDesign";
import IModelGeometry from "./IModelGeometry";
/**
* Represents a region in the texture atlas for a cube face
*/
export interface IAtlasRegion {
x: number;
y: number;
width: number;
height: number;
content: IMcpFaceContent;
faceName: string;
cubeIndex: number;
boneIndex: number;
/** Context string for deterministic noise seeding (e.g., "bone0:cube1:north") */
contextString?: string;
/** If true, this region shares atlas space with another region and should not be rendered */
isDuplicate?: boolean;
}
/**
* Result from converting an MCP design to geometry
*/
export interface IModelDesignConversionResult {
/**
* The converted Minecraft geometry JSON
*/
geometry: IModelGeometry;
/**
* Atlas regions for generating the texture
*/
atlasRegions: IAtlasRegion[];
/**
* Total texture size [width, height]
*/
textureSize: [number, number];
/**
* Pixels per Minecraft unit used for texture generation.
* Needed by pixel art renderer to scale properly.
*/
pixelsPerUnit: number;
/**
* Any warnings during conversion
*/
warnings: string[];
/**
* Map from content hash to atlas region index, for texture deduplication
*/
textureDeduplicationMap?: Map<string, number>;
}
/**
* Resolved face content after texture ID lookup.
* Contains the actual svg/color/background to render (textureId is resolved away).
*/
export interface IResolvedFaceContent {
/** @deprecated Use background with type:'solid' instead */
color?: string | IMcpColorRGBA;
svg?: string;
/** @deprecated Use background instead */
noise?: IMcpNoiseConfig;
/** Background fill using a textured rectangle (unified color/noise format) */
background?: IMcpTexturedRectangle;
/** Pixel art overlays to render on top of background and svg */
pixelArt?: IMcpPixelArt[];
/** Post-processing effects to apply to the face texture */
effects?: import("./TextureEffects").ITextureEffects;
rotation?: number;
/** The original textureId if this was resolved from a reference */
sourceTextureId?: string;
}
/**
* Bounding box for a model design
*/
export interface IModelBounds {
minX: number;
minY: number;
minZ: number;
maxX: number;
maxY: number;
maxZ: number;
/** Maximum dimension (width, height, or depth) */
maxDimension: number;
/** Center point of the bounding box */
center: {
x: number;
y: number;
z: number;
};
}
/**
* Utility class for working with MCP model designs
*/
export default class ModelDesignUtilities {
/**
* Calculate the bounding box of a model design.
* Iterates through all bones and cubes to find the min/max extents.
*/
static calculateModelBounds(design: IMcpModelDesign): IModelBounds;
/**
* Parse a color string or object to RGBA values (0-255)
*/
static parseColor(color: string | IMcpColorRGBA | undefined): IMcpColorRGBA;
/**
* Convert color to hex string
*/
static colorToHex(color: IMcpColorRGBA): string;
/**
* Resolve face content by looking up textureId references.
* Returns the actual svg/color content to render.
* Priority: textureId > svg > color
*
* @param faceContent The face content which may contain a textureId reference
* @param textures The texture dictionary from the model design
* @param warnings Array to collect any warnings (e.g., missing texture references)
* @returns Resolved content with svg/color, or undefined if face should be transparent
*/
static resolveFaceContent(faceContent: IMcpFaceContent | undefined, textures: {
[textureId: string]: IMcpTextureDefinition;
} | undefined, warnings: string[]): IResolvedFaceContent | undefined;
/**
* Generate a content hash for a resolved face content.
* Used for texture deduplication - faces with identical content can share atlas regions.
* Note: rotation is NOT included in hash since it's applied at UV time, not texture time.
* Note: backgrounds with undefined/random seed create unique textures per face (not deduplicated).
*/
static getContentHash(content: IResolvedFaceContent): string;
/**
* Get the effective pixels per unit for a design.
* Returns the design's pixelsPerUnit if specified, otherwise DEFAULT_PIXELS_PER_UNIT.
*/
static getPixelsPerUnit(design: IMcpModelDesign): number;
/**
* Calculate the texture size needed for a face based on cube dimensions.
* @param cubeSize The cube dimensions [width, height, depth] in Minecraft units
* @param faceName The face to calculate texture size for
* @param pixelsPerUnit Pixels per Minecraft unit (default: DEFAULT_PIXELS_PER_UNIT)
*/
static getFaceTextureSize(cubeSize: [number, number, number], faceName: string, pixelsPerUnit?: number): {
width: number;
height: number;
};
/**
* Check if a texture size is sufficient for a design by doing a dry-run pack.
* Returns true if the texture needs to be larger.
* Takes into account texture deduplication - identical textures at same size share atlas space.
*/
private static _checkNeedsLargerTexture;
/**
* Convert an MCP model design to Minecraft geometry JSON format
*/
static convertToGeometry(design: IMcpModelDesign): IModelDesignConversionResult;
/**
* Generate SVG for a solid color face
*/
static generateColorSvg(color: IMcpColorRGBA, width: number, height: number): string;
/**
* Get the SVG content for a face, either from explicit SVG, noise, or generating from color.
*
* Priority order:
* 1. If noise is specified, generate noise background
* 2. If svg is specified, overlay it on top of noise (or use as primary if no noise)
* 3. If only color is specified, generate solid color
*
* @param content Face content configuration
* @param width Texture width in pixels
* @param height Texture height in pixels
* @param contextString Optional context for deterministic noise seeding
*/
static getFaceSvg(content: IMcpFaceContent, width: number, height: number, contextString?: string): string;
/**
* Generate a complete SVG document representing the texture atlas
* This can be rasterized to PNG using a rendering engine
*/
static generateAtlasSvg(atlasRegions: IAtlasRegion[], textureSize: [number, number]): string;
/**
* Check if an SVG string contains non-rect elements that are not Minecraft-style
* Returns array of warning messages about non-Minecraft-style SVG elements
*/
private static validateSvgStyle;
/**
* Validate pixel art configuration and return any errors or warnings.
* Returns array of error/warning messages about invalid pixel art
*/
private static validatePixelArt;
/**
* Validate an MCP model design and return any errors or warnings.
* Errors are blocking issues that prevent model generation.
* Warnings (prefixed with "WARNING:") are style suggestions for better Minecraft compatibility.
*/
static validateDesign(design: IMcpModelDesign): string[];
/**
* Create a simple unit cube model design (for testing)
*/
static createUnitCubeDesign(identifier: string, faceColors: {
north?: string;
south?: string;
east?: string;
west?: string;
up?: string;
down?: string;
}): IMcpModelDesign;
}