Implement playable Mac client and rendering validation

This commit is contained in:
shen
2026-09-11 14:58:22 +08:00
parent 1ab68bd06e
commit 374d4165d8
233 changed files with 6546 additions and 284 deletions
+43
View File
@@ -0,0 +1,43 @@
import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import {execFileSync} from 'node:child_process';
const assets = process.argv[2] ?? 'assets';
const output = process.argv[3];
const manifest = JSON.parse(fs.readFileSync(path.join(assets, 'TreeGeometry/manifest.json')));
const normalize = s => s.replaceAll('\\', '/').toLowerCase().replace(/^.*?ymir work\//, 'ymir work/');
const converted = new Set(Object.values(manifest.trees).map(r => normalize(r.source)));
const list = pattern => execFileSync('rg', ['--files', assets, '-g', pattern], {encoding: 'utf8', maxBuffer: 8 * 1024 * 1024}).trim().split('\n').filter(Boolean);
const references = new Set();
const propertyReferences = new Map();
for (const file of list('*.prt')) {
const source = fs.readFileSync(file, 'utf8');
for (const match of source.matchAll(/^\s*treefile\s+"([^"]+)"/gmi)) {
const reference = normalize(match[1]);
references.add(reference);
propertyReferences.set(source.split(/\r?\n/)[1].trim(), reference);
}
}
const placedReferences = new Set();
for (const file of list('areadata.txt')) {
const source = fs.readFileSync(file, 'utf8');
for (const match of source.matchAll(/^Start Object\d+\r?\n[^\n]*\n\s*(\d+)/gm)) {
const reference = propertyReferences.get(match[1]);
if (reference) placedReferences.add(reference);
}
}
const unmatched = [];
let matched = 0;
for (const file of list('*.spt')) {
const hash = crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
if (manifest.trees[hash]) matched++;
else unmatched.push({file, source_sha256: hash, referenced_by_property: references.has(normalize(file))});
}
const missing_referenced = [...references].filter(r => !converted.has(r)).sort();
const missing_placed = [...placedReferences].filter(r => !converted.has(r)).sort();
const report = {matched_spt_files: matched, converted_species: converted.size, referenced_species: references.size,
placed_species: placedReferences.size, missing_placed,
missing_referenced, unconverted_spt: unmatched, scope: 'SPT inventory and text PRT/AreaData references; six-map runtime validation is separate'};
if (output) fs.writeFileSync(output, JSON.stringify(report, null, 2) + '\n');
console.log(JSON.stringify({matched, converted: converted.size, referenced: references.size, placed: placedReferences.size, missing_placed, missing_referenced, unconverted: unmatched.length}));
if (!placedReferences.size || missing_placed.length) process.exitCode = 1;