feat: upgrade city stay exploration

This commit is contained in:
2026-07-28 00:12:10 +09:00
parent 9d67e0ae1d
commit 1a81ce5689
18 changed files with 1733 additions and 218 deletions

View File

@@ -21,11 +21,14 @@ const expectedBaseMappings = {
'unit-shu-infantry': 'exploration-shu-infantry'
};
const expectedNamedTextureFallbacks = {
'exploration-huang-quan': 'unit-shu-officer',
'exploration-jian-yong': 'unit-shu-officer',
'exploration-mi-zhu': 'unit-shu-officer',
'exploration-zhuge-liang': 'unit-shu-officer',
'exploration-zhuo-recruiting-clerk': 'unit-shu-officer',
'exploration-zhuo-villager': 'unit-shu-infantry',
'exploration-zhuo-quartermaster': 'unit-shu-officer',
'exploration-zou-jing': 'unit-shu-officer',
'exploration-jian-yong': 'unit-shu-officer'
'exploration-zou-jing': 'unit-shu-officer'
};
const expectedSceneNpcTextureKeys = [
{
@@ -136,17 +139,22 @@ assert.deepEqual(
deployedFiles.forEach((fileName) => {
const path = join(characterDirectory, fileName);
const dimensions = webpDimensions(path);
const inspection = inspectWebp(path);
assert.equal(
dimensions.width,
inspection.width,
expectedWidth,
`${path}: expected ${expectedWidth}px width for 16 frames per direction.`
);
assert.equal(
dimensions.height,
inspection.height,
expectedHeight,
`${path}: expected ${expectedHeight}px height for four direction rows.`
);
assert.equal(
inspection.hasAlpha,
true,
`${path}: exploration character sheets must preserve transparent backgrounds.`
);
});
console.log(
@@ -172,7 +180,7 @@ function readStringMap(source, mappingName) {
return mappings;
}
function webpDimensions(path) {
function inspectWebp(path) {
const bytes = readFileSync(path);
assert(
bytes.subarray(0, 4).toString('ascii') === 'RIFF' &&
@@ -181,6 +189,8 @@ function webpDimensions(path) {
);
let offset = 12;
let dimensions;
let hasAlpha = false;
while (offset + 8 <= bytes.length) {
const chunkType = bytes.subarray(offset, offset + 4).toString('ascii');
const chunkSize = bytes.readUInt32LE(offset + 4);
@@ -191,20 +201,22 @@ function webpDimensions(path) {
);
if (chunkType === 'VP8X') {
return {
dimensions = {
width: bytes.readUIntLE(payloadOffset + 4, 3) + 1,
height: bytes.readUIntLE(payloadOffset + 7, 3) + 1
};
}
if (chunkType === 'VP8L') {
hasAlpha ||= (bytes[payloadOffset] & 0x10) !== 0;
} else if (chunkType === 'ALPH') {
hasAlpha = true;
} else if (chunkType === 'VP8L') {
const bits = bytes.readUInt32LE(payloadOffset + 1);
return {
dimensions ??= {
width: (bits & 0x3fff) + 1,
height: ((bits >>> 14) & 0x3fff) + 1
};
}
if (chunkType === 'VP8 ') {
return {
hasAlpha ||= (bits & 0x10000000) !== 0;
} else if (chunkType === 'VP8 ') {
dimensions ??= {
width: bytes.readUInt16LE(payloadOffset + 6) & 0x3fff,
height: bytes.readUInt16LE(payloadOffset + 8) & 0x3fff
};
@@ -213,5 +225,6 @@ function webpDimensions(path) {
offset = payloadOffset + chunkSize + (chunkSize % 2);
}
throw new Error(`${path}: could not read WebP dimensions.`);
assert(dimensions, `${path}: could not read WebP dimensions.`);
return { ...dimensions, hasAlpha };
}