Files
Currency-War-SR/tools/gridfight-extract-node/install_rounds.mjs
T
2026-10-30 23:54:07 +07:00

90 lines
4.9 KiB
JavaScript

import * as r from './install_common.mjs';
const {
e
} =r;
export const NAMES=['rounds.json', 'tutorial.json', 'levels.json', 'rounds_raw.json', 'levels_raw.json'];
export const replace=r.replace;
export function install(a){
const provenance=e.loadJSON(e.path.join(a.stage, 'provenance.json'));
return r.withLock(a['launcher-root'], ()=>{
const launcher=a['launcher-root'],
registryPath=e.path.join(launcher, 'client-profiles.json'),
registry=e.loadJSON(registryPath),
profile=registry.beta,
bundle=profile.bundle_dir,
runtime=profile.runtime_dir,
version=profile.version,
client=profile.client_dir,
identity=e.loadJSON(e.path.join(bundle, 'dump/client.json'));
if(e.json(identity)!==e.json(provenance.client)||identity.version!==version||!version.includes('BETA'))e.fail('Extraction is not for the installed BETA profile');
r.verify_bundle(bundle, version);
r.verify_client(bundle, client, version, 'beta');
r.verify_runtime(runtime, bundle, version);
for(const name of NAMES)if(r.digest(e.path.join(a.stage, name))!==provenance.outputs[name])e.fail('Extracted resource hash changed');
const proofs=new Map([...provenance.collections, provenance.node_textmap].map(p=>[p.blob, p]));
for(const proof of proofs.values())if(r.digest(e.path.join(client, 'StarRail_Data', proof.blob))!==proof.blob_sha256)e.fail('Client DesignData changed after extraction');
for(const proof of provenance.catalogues)if(r.digest(e.path.join(client, proof.path))!==proof.sha256)e.fail('Installed active DesignV changed');
const token=r.token(),
backup=e.path.join(launcher, '.pearl-cache/gridfight-data-backups', token),
roots={
source:e.path.join(a['server-root'], 'resources/grid_fight'),
bundle:e.path.join(bundle, 'server/resources/grid_fight'),
runtime:e.path.join(runtime, 'resources/grid_fight')
},
targets=Object.entries(roots).flatMap(([area, root])=>NAMES.map(n=>[area, e.path.join(root, n), e.path.join(a.stage, n)]));
targets.push(['bundle', e.path.join(bundle, 'SHA256SUMS'), null]);
const excluded=new Set(targets.map(([, p])=>p)),
bundleBefore=r.snapshot(bundle, excluded),
runtimeBefore=r.snapshot(e.path.join(runtime, 'resources'), excluded),
binaries=Object.fromEntries(['gameserver', 'dispatch'].map(n=>[n, r.digest(e.path.join(runtime, 'zig-out/bin', n))])),
registryBefore=r.digest(registryPath),
liveBundle=registry.live.bundle_dir,
liveBefore=r.snapshot(liveBundle, excluded);
r.transaction(targets, backup, write=>{
for(const [, p, incoming]of targets)if(incoming)write(p, e.fs.readFileSync(incoming));
write(e.path.join(bundle, 'SHA256SUMS'), r.manifest(bundle));
}, ()=>{
r.verify_bundle(bundle, version);
r.verify_runtime(runtime, bundle, version);
for(const name of NAMES)if(new Set(Object.values(roots).map(root=>r.digest(e.path.join(root, name)))).size!==1||r.digest(e.path.join(roots.source, name))!==provenance.outputs[name])e.fail('Source/bundle/runtime resource mismatch');
if(!r.equal(r.snapshot(bundle, excluded), bundleBefore)||!r.equal(r.snapshot(e.path.join(runtime, 'resources'), excluded), runtimeBefore))e.fail('An unrelated managed resource changed');
if(!r.equal(r.snapshot(liveBundle, excluded), liveBefore)||r.digest(registryPath)!==registryBefore)e.fail('LIVE bundle or profile registry changed');
for(const [name, d]of Object.entries(binaries))if(r.digest(e.path.join(runtime, 'zig-out/bin', name))!==d)e.fail('Runtime binaries changed');
}, 'gridfight-data');
const cache=e.path.join(launcher, '.pearl-cache/gridfight-rounds', version, token);
e.fs.cpSync(a.stage, cache, {
recursive:true,
errorOnExist:true,
force:false
});
const evidence=e.path.join(a['server-root'], 'tools/gridfight-extract-node/evidence/rounds');
e.fs.cpSync(e.path.join(a.stage, 'evidence'), evidence, {
recursive:true
});
for(const name of ['schemas.json', 'provenance.json'])r.replace(e.path.join(evidence, name), e.fs.readFileSync(e.path.join(a.stage, name)));
const report={
version,
token,
outputs:provenance.outputs,
counts:provenance.counts,
backup:e.path.relative(launcher, backup),
bundle_manifest_verified:true,
source_bundle_runtime_match:true,
beta_non_target_resources_preserved:Object.keys(runtimeBefore).length,
live_bundle_files_preserved:Object.keys(liveBefore).length,
runtime_binaries_preserved:true,
registry_preserved:true,
processes_started_or_stopped:0,
gameplay_verified:false
};
e.atomic_json(e.path.join(evidence, 'validation.json'), report, 2, true);
e.atomic_json(e.path.join(cache, 'install.json'), report, 2, true);
console.log(e.json(report));
return report;
});
}
export function main(){
install(e.cli(['server-root', 'launcher-root', 'stage']));
}
e.runMain(import.meta.url, main);