Files
2026-10-30 23:54:07 +07:00

53 lines
2.1 KiB
JavaScript

import * as s from './stages.mjs';
const e=s.primitive;
export function audit(client, dump, assembly, roles, evidence){
const codec=new s.Codec(e.readText(dump), assembly, e.path.join(evidence, 'native')),
assets=new s.Assets(client),
[raw, proof]=assets.get('BakedConfig/ExcelOutputGameCore/SpecialAvatar.bytes'),
cur=new e.Cursor(raw),
count=cur.length(1000000),
typ='RPG.GameCore.SpecialAvatarRow',
schema=codec.schema(typ);
if(schema.length!==codec.fields(typ).size)e.fail('Incomplete SpecialAvatar native schema');
const rows=Array.from({
length:count
}, ()=>codec.record(cur, typ)),
encoded=e.cat(e.encode_varint(2*count), rows.map(r=>codec.encode_record(r, typ)));
if(cur.at!==raw.length||!encoded.equals(raw))e.fail('Whole SpecialAvatar table failed native round trip');
const index=e.lookup(rows, r=>[r.SpecialAvatarID??0, r.WorldLevel??0].join(':'), 'SpecialAvatar identity'),
verified=[];
for(const role of e.loadJSON(roles)){
const trial=role.raw.SpecialAvatarID??0,
row=index.get(trial+':6');
if(!trial||!row||(row.AvatarID??0)!==role.avatar_id||(row.Type??0)!==1)e.fail('Role '+role.id+' cannot resolve as a world-level-6 trial');
verified.push({
role_id:role.id,
season_id:role.raw.SeasonID,
trial_id:trial,
avatar_id:row.AvatarID,
world_level:6
});
}
const report={
round_trip:true,
special_avatar_rows:count,
roles_checked:verified.length,
gameplay_verified:false,
assembly_sha256:e.sha256_file(assembly),
dump_sha256:e.sha256_file(dump),
roles_sha256:e.sha256_file(roles),
table:proof,
catalogues:assets.catalogues,
schema,
roles:verified
};
e.atomic_json(e.path.join(evidence, 'trial-avatar-audit.json'), report, 2, true);
return report;
}
export function main(){
const a=e.cli(['client', 'dump', 'assembly', 'roles', 'evidence']),
r=audit(a.client, a.dump, a.assembly, a.roles, a.evidence);
console.log(`Native round trip: ${r.special_avatar_rows} rows; ${r.roles_checked} role identities verified`);
}
e.runMain(import.meta.url, main);