Files

42 lines
2.9 KiB
JavaScript
Raw Permalink Normal View History

2026-10-30 23:54:07 +07:00
// Fresh native inputs for equipment, augment grants and scoring; never reuse an older catalog.
import * as e from './extract.mjs';
import * as s from './stages.mjs';
import {table_bindings} from './rounds.mjs';
import {text_rows} from './ui_names.mjs';
import {fixpoint} from './trait_effects.mjs';
export const TYPES=['GridFightRoleRecommendEquipConfigRow','GridFightSPSilverWolfChooseConfigRow',
'GridFightClaraEnhanceConfigRow','GridFightClaraLinkRelationConfigRow','GridFightPhanionUniqueTraitConfigRow',
'GridFightForgeConfigRow','GridFightSeasonExpScoreRow','GridFightScoreRewardConfigRow',
'GridFightDivisionStageRow','GridFightTraitElationTemplateConfigRow',
'GridFightBonfireHealConfigRow','GridFightBonfireEventRow','GridFightShopPriceConfigRow',
'GridFightFormationWaveConfigRow','GridFightStageLevelValueConfigRow','GridFightPenaltyRuleConfigRow',
'GridFightEnemyDifficultyLvConfigRow','GridFightBonusRuleConfigRow','GridFightBinaryNodeRuleConfigRow',
'GridFightLevelBaseValueConfigRow'];
export function enrich(value,texts){
if(Array.isArray(value))return value.map(v=>enrich(v,texts));
if(!value||typeof value!=='object')return value;
if('hash'in value&&'hash64'in value)return {text:texts[value.hash64]??'',text_id:value};
if('wire'in value)return {...value,value:fixpoint(value.wire)};
return Object.fromEntries(Object.entries(value).map(([k,v])=>[k,enrich(v,texts)]));
}
export function main(){
const a=e.cli(['client','dump','identity','literals','english','items','output']),ctx=s.extractionContext(a),
literals=new Map(e.loadJSON(a.literals).map(r=>[Number(BigInt(r.Address)),r.Value])),
texts=text_rows(e.fs.readFileSync(a.english)),raw=e.loadJSON(a.items),proofs=[];
for(const name of TYPES){
const [asset]=table_bindings(ctx.codec,literals,'RPG.GameCore.'+name),
match=asset.match(/^BakedConfig\/ExcelOutput(GameCore)?\/(\w+)\.bytes$/);
if(!match)e.fail('Unsupported native table path: '+asset);
const [rows,proof]=s.table(ctx.assets,ctx.codec,name,match[1]??'',match[2]);
if(ctx.codec.schema('RPG.GameCore.'+name).length!==ctx.codec.fields('RPG.GameCore.'+name).size)e.fail('Incomplete catalog schema: '+name);
raw[name]=rows;proofs.push(proof);console.log(`${name}: ${rows.length} byte-exact rows`);
}
const tables=enrich(raw,texts),eq=new Map(tables.GridFightEquipConfigRow.map(r=>[r.ID,r])),
seasons=Object.fromEntries([...new Set(raw.GridFightSeasonItemConfigRow.map(r=>r.SeasonID))].map(id=>[id,{
items:raw.GridFightSeasonItemConfigRow.filter(r=>r.SeasonID===id).map(r=>({id:r.ItemID,config_id:r.ConfigID,equipment:eq.get(r.ConfigID)??null,raw_link:r}))
}]));
s.publish(a,ctx,raw,proofs,{'catalog.json':{identity:ctx.identity,tables,seasons},'catalog.raw.json':raw},'catalog',{
textmap:{file:e.path.basename(a.english),sha256:e.sha256_file(a.english)},gameplay_verified:false
});
}
e.runMain(import.meta.url,main);