UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

153 lines (152 loc) 6.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isRegionVisible = isRegionVisible; exports.getSkinTargetByUniquePixelLocations = getSkinTargetByUniquePixelLocations; exports.getSkinTargetFromName = getSkinTargetFromName; exports.isHighResolutionSkinPackTexture = isHighResolutionSkinPackTexture; exports.isOuterAreaIsBlank = isOuterAreaIsBlank; exports.getSegmentsVisibilities = getSegmentsVisibilities; const Database_1 = __importDefault(require("../Database")); const Skin_1 = require("../skins/Skin"); const TextureDefinition_1 = __importDefault(require("../TextureDefinition")); const ModelSegments_1 = require("./ModelSegments"); // Generally, steve == custom and alex == customSlim const CustomSlimGeometryTags = new Set(["a", "alex", "slim", "customslim"]); const CustomGeometryTags = new Set(["s", "steve", "custom"]); class TextureUtilities { static _custom = { name: "custom", allowedTextures: undefined, allowedTexturesHighRes: undefined, geometryName: "geometry.humanoid.custom", segments: [ModelSegments_1.Head, ModelSegments_1.RightArmCustom, ModelSegments_1.LeftArmCustom, ModelSegments_1.LeftLeg, ModelSegments_1.RightLeg], }; static _customSlim = { name: "customSlim", allowedTextures: undefined, allowedTexturesHighRes: undefined, geometryName: "geometry.humanoid.customSlim", segments: [ModelSegments_1.Head, ModelSegments_1.RightArmSlim, ModelSegments_1.LeftArmSlim, ModelSegments_1.LeftLeg, ModelSegments_1.RightLeg], }; static _isLoaded = false; static getBySize(size) { switch (size) { case Skin_1.SkinModelTarget.Custom: return this._custom; case Skin_1.SkinModelTarget.CustomSlim: return this._customSlim; default: throw new Error(`Unknown skin size: ${size}`); } } static async getTextureDefinititionForContent(filePath) { const contentFile = await Database_1.default.getContentFolderFile(filePath); if (!contentFile) { return undefined; } if (!contentFile.isContentLoaded) { await contentFile.loadContent(); } if (!(contentFile.content instanceof Uint8Array)) { return undefined; } let textDef = await TextureDefinition_1.default.ensureOnFile(contentFile); if (!textDef) { return undefined; } if (!textDef.isContentProcessed) { await textDef.processContent(); } return textDef; } static async load() { if (this._isLoaded) { return; } this._custom.allowedTextures = await TextureUtilities.getTextureDefinititionForContent("textures/Custom_AllowedPixels_64.png"); this._custom.allowedTexturesHighRes = await TextureUtilities.getTextureDefinititionForContent("textures/Custom_AllowedPixels_128.png"); this._customSlim.allowedTextures = await TextureUtilities.getTextureDefinititionForContent("textures/CustomSlim_AllowedPixels_64.png"); this._customSlim.allowedTexturesHighRes = await TextureUtilities.getTextureDefinititionForContent("textures/CustomSlim_AllowedPixels_128.png"); this._isLoaded = true; } } exports.default = TextureUtilities; function isRegionVisible(texture, area) { const multiplier = isHighResolutionSkinPackTexture(texture) ? 2 : 1; const maxX = Math.floor(area.x2) * multiplier; const maxY = Math.floor(area.y2) * multiplier; if (texture.imageData) { for (let x = area.x1 * multiplier; x <= maxX; x++) { for (let y = area.y1 * multiplier; y <= maxY; y++) { if (texture.getPixel(x, y).a !== 0) { return true; } } } } return false; } function getSkinTargetByUniquePixelLocations(texture) { const hasCustomSkinPixels = isRegionVisible(texture, ModelSegments_1.RightArmCustomDifference) || isRegionVisible(texture, ModelSegments_1.LeftArmCustomDifference); return hasCustomSkinPixels ? Skin_1.SkinModelTarget.Custom : Skin_1.SkinModelTarget.CustomSlim; } function getSkinTargetFromName(textureName) { const tokens = textureName.split(/[._]/); if (tokens.length > 2) { const prefix = tokens[0]?.toLowerCase(); const suffix = tokens[tokens.length - 2]?.toLowerCase(); if (CustomGeometryTags.has(prefix) || CustomGeometryTags.has(suffix)) { return Skin_1.SkinModelTarget.Custom; } if (CustomSlimGeometryTags.has(prefix) || CustomSlimGeometryTags.has(suffix)) { return Skin_1.SkinModelTarget.CustomSlim; } } return undefined; } function isHighResolutionSkinPackTexture(textureDefinition) { return textureDefinition.width === 128; } async function isOuterAreaIsBlank(texture, size) { await TextureUtilities.load(); if (texture.width === undefined || texture.height === undefined) { throw new Error("Texture width or height is undefined"); } const allowedAlphaMask = isHighResolutionSkinPackTexture(texture) ? TextureUtilities.getBySize(size).allowedTexturesHighRes : TextureUtilities.getBySize(size).allowedTextures; if (!allowedAlphaMask) { throw new Error("Could not find reference for texture"); } if (texture.imageData) { for (let x = 0; x < texture.width; ++x) { for (let y = 0; y < texture.height; ++y) { const texIsVisibleInDisallowedSpot = allowedAlphaMask.getPixel(x, y).a === 0 && texture.getPixel(x, y).a > 0; if (texIsVisibleInDisallowedSpot) { return false; } } } } return true; } function getSegmentsVisibilities(texture, size) { const values = TextureUtilities.getBySize(size); return values.segments.map((segment) => checkTextureVisibilityForSegment(texture, segment)); } function checkTextureVisibilityForSegment(texture, segment) { return { segmentName: segment.name, visibilities: { top: isRegionVisible(texture, segment.parts.top), front: isRegionVisible(texture, segment.parts.front), left: isRegionVisible(texture, segment.parts.left), right: isRegionVisible(texture, segment.parts.right), bottom: isRegionVisible(texture, segment.parts.bottom), back: isRegionVisible(texture, segment.parts.back), }, }; }