@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
153 lines (152 loc) • 6.7 kB
JavaScript
;
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),
},
};
}