Files
shacraft-core/client/tests/block-textures.test.js
Emil c7e86663d8
MVP checks / mvp (push) Canceled after 0s
Expand voxel gameplay, lighting, full-height streaming and world imports
Add shared Rust/WASM physics, worker meshing and diagnostics, 64-chunk full-height streaming, atlas texture support, and baseline world import. Document the current implementation and include the supplied in-game lobby screenshot.
2026-09-17 02:10:53 +03:00

107 lines
6.5 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { getBlockFaceTextures, getFaceUV } from "../block-textures.js";
const names = ["stone", "cobblestone", "oak_planks", "oak_log", "oak_log_top", "dirt", "grass_block_top", "grass_block_side", "sand", "gravel", "bricks", "stone_bricks", "glass", "oak_leaves", "diamond_ore", "iron_ore", "coal_ore", "gold_ore", "redstone_ore", "deepslate", "obsidian", "snow", "netherrack", "oak_door_bottom"];
const layers = new Map(names.map((name, index) => [name, index]));
const textureNames = (state, available = layers) =>
getBlockFaceTextures(state, available).map((face) => face ? names[face.layer] : null);
test("partial packs keep missing and unrelated materials on the fallback path", () => {
for (const state of ["minecraft:spruce_planks", "minecraft:stripped_oak_log[axis=y]", "minecraft:mossy_cobblestone", "minecraft:deepslate_diamond_ore", "mod:stone", "minecraft:oak_trapdoor", "minecraft:stonecutter", "", undefined]) {
assert.deepEqual(textureNames(state), Array(6).fill(null), String(state));
}
assert.deepEqual(textureNames("minecraft:stone", new Map()), Array(6).fill(null));
assert.equal(getBlockFaceTextures("minecraft:stone", layers)[0].layer, 0);
assert.deepEqual(textureNames("minecraft:stone", new Map([["stone", -1]])), Array(6).fill(null));
});
test("material variants use their own surface without broad substring matching", () => {
for (const [state, texture] of [["oak_stairs[facing=east,half=bottom]", "oak_planks"], ["cobblestone_wall[north=low]", "cobblestone"], ["stone_brick_slab[type=top]", "stone_bricks"], ["brick_stairs", "bricks"], ["snow_block", "snow"]]) {
assert.deepEqual(textureNames(`minecraft:${state}`), Array(6).fill(texture));
}
});
test("grass uses a tinted top, full-color sides and a dirt bottom independently", () => {
assert.deepEqual(textureNames("minecraft:grass_block[snowy=false]"), ["grass_block_side", "grass_block_side", "grass_block_top", "dirt", "grass_block_side", "grass_block_side"]);
const faces = getBlockFaceTextures("minecraft:grass_block", layers);
assert.ok(faces[2].tint[1] > faces[2].tint[0] && faces[2].tint[0] > faces[2].tint[2]);
assert.deepEqual(faces[0].tint, [1, 1, 1]);
assert.equal(faces[2].cutout, false);
assert.deepEqual(textureNames("minecraft:grass_block[snowy=true]"), [null, null, "grass_block_top", "dirt", null, null]);
const missingSide = new Map(layers);
missingSide.delete("grass_block_side");
assert.deepEqual(textureNames("minecraft:grass_block", missingSide), [null, null, "grass_block_top", "dirt", null, null]);
});
test("log end grain follows every axis while oak wood remains bark on all faces", () => {
for (const [axis, caps] of [["x", [0, 1]], ["y", [2, 3]], ["z", [4, 5]]]) {
assert.deepEqual(textureNames(`minecraft:oak_log[axis=${axis}]`), Array.from({ length: 6 }, (_, face) => caps.includes(face) ? "oak_log_top" : "oak_log"));
}
assert.deepEqual(textureNames("minecraft:oak_log"), textureNames("minecraft:oak_log[axis=y]"));
assert.deepEqual(textureNames("minecraft:oak_wood[axis=x]"), Array(6).fill("oak_log"));
});
test("cutout textures preserve full-color glass and tint grayscale leaves", () => {
const glass = getBlockFaceTextures("minecraft:glass", layers);
const leaves = getBlockFaceTextures("minecraft:oak_leaves[persistent=true]", layers);
assert.ok(glass.every((face) => face.cutout));
assert.ok(leaves.every((face) => face.cutout));
assert.deepEqual(glass[0].tint, [1, 1, 1]);
assert.ok(leaves[0].tint[1] > leaves[0].tint[0] && leaves[0].tint[0] > leaves[0].tint[2]);
});
test("doors use lower artwork only on the lower broad faces, respecting open rotation", () => {
const alongZ = ["oak_planks", "oak_planks", "oak_planks", "oak_planks", "oak_door_bottom", "oak_door_bottom"];
const alongX = ["oak_door_bottom", "oak_door_bottom", "oak_planks", "oak_planks", "oak_planks", "oak_planks"];
for (const facing of ["north", "south", "east", "west"]) {
const x = ["east", "west"].includes(facing);
assert.deepEqual(textureNames(`minecraft:oak_door[half=lower,facing=${facing},open=false]`), x ? alongX : alongZ);
assert.deepEqual(textureNames(`minecraft:oak_door[half=lower,facing=${facing},open=true]`), x ? alongZ : alongX);
assert.deepEqual(textureNames(`minecraft:oak_door[half=upper,facing=${facing},open=false]`), Array(6).fill(null));
}
});
test("face UVs orient a top-left source consistently from outside each cube face", () => {
const corners = [
[[1, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]],
[[0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0]],
[[0, 1, 1], [1, 1, 1], [1, 1, 0], [0, 1, 0]],
[[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1]],
[[0, 0, 1], [1, 0, 1], [1, 1, 1], [0, 1, 1]],
[[1, 0, 0], [0, 0, 0], [0, 1, 0], [1, 1, 0]],
];
for (let face = 0; face < 6; face++) {
assert.deepEqual(corners[face].map((pos) => getFaceUV(face, pos)), [[0, 1], [1, 1], [1, 0], [0, 0]]);
}
assert.deepEqual(getFaceUV(4, [0.25, 0.5, 1]), [0.25, 0.5]);
assert.deepEqual(getFaceUV(0, [1, 1.5, 0.25]), [0.75, -0.5]);
assert.throws(() => getFaceUV(6, [0, 0, 0]), RangeError);
});
test("horizontal log bark follows the log axis through a proper cube rotation", () => {
const vertical = [0.25, 0.75, 0.125];
// Rotate the same point and normal with the complete cube, then compare UVs.
const horizontalX = [vertical[1], 1 - vertical[0], vertical[2]];
const horizontalZ = [vertical[0], 1 - vertical[2], vertical[1]];
const faceFromVerticalX = [3, 2, 0, 1, 4, 5];
const faceFromVerticalZ = [0, 1, 4, 5, 3, 2];
for (const block of ["oak_log", "oak_wood"]) {
for (let face = 0; face < 6; face++) {
const expected = getFaceUV(face, vertical);
assert.deepEqual(getFaceUV(faceFromVerticalX[face], horizontalX, `minecraft:${block}[axis=x]`), expected);
assert.deepEqual(getFaceUV(faceFromVerticalZ[face], horizontalZ, `minecraft:${block}[axis=z]`), expected);
assert.deepEqual(getFaceUV(face, vertical, `minecraft:${block}[axis=y]`), expected);
}
}
for (const [axis, sideFaces] of [["x", [2, 3, 4, 5]], ["z", [0, 1, 2, 3]]]) {
for (const face of sideFaces) {
const point = [0.25, 0.5, 0.75];
const coordinate = axis === "x" ? point[0] : point[2];
assert.equal(getFaceUV(face, point, `minecraft:oak_log[axis=${axis}]`)[1], 1 - coordinate);
}
}
assert.deepEqual(getFaceUV(4, vertical, "minecraft:deepslate[axis=x]"), getFaceUV(4, vertical));
assert.deepEqual(getFaceUV(4, vertical, "mod:oak_log[axis=x]"), getFaceUV(4, vertical));
});