//go:build ignore package main import ( "encoding/json" "flag" "fmt" pb "gac-hkrpg-go/protocol/proto" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "os" "path/filepath" ) func main() { beforePath := flag.String("before", "", "before-battle GetData JSON") afterPath := flag.String("after", "", "after-battle GetData JSON") roundPath := flag.String("round", "", "after-next-RoundBegin GetData JSON") syncGlob := flag.String("sync", "", "native notification capture glob") output := flag.String("output", "", "resource output") flag.Parse() read := func(path string) *pb.MPIMAEMCEFH { raw, e := os.ReadFile(path) if e != nil { panic(e) } var d pb.GridFightGetDataScRsp if e = protojson.Unmarshal(raw, &d); e != nil { panic(e) } if d.DHFOFLFCLAH == nil { panic("run missing") } return d.DHFOFLFCLAH } before, after, round := read(*beforePath), read(*afterPath), read(*roundPath) stageOf := func(r *pb.MPIMAEMCEFH) *pb.BEEFLEJAOCN { for _, c := range r.NAGDJGMMCBE { if v := c.GetKLCPAAHDPJF(); v != nil { return v } } panic("stage missing") } b, a := stageOf(before), stageOf(after) if b.EMOHLJHPOPC != a.EMOHLJHPOPC || after.FMIGOKIDKJL == nil || after.FMIGOKIDKJL.GetNNDGEJFLGGF() == nil { panic("transition identity differs") } var node *pb.OHMDHKGAEMM for _, n := range b.OOMMIIKPHBC { if n.DCAHJELNJNP == b.DCAHJELNJNP && n.SectionId == b.SectionId { node = n.DisplayValue } } if node == nil { panic("before node absent") } files, e := filepath.Glob(*syncGlob) if e != nil { panic(e) } var level *pb.AINFNFIDGFF for _, file := range files { raw, e := os.ReadFile(file) if e != nil { panic(e) } var n pb.GridFightSyncUpdateResultScNotify if e = proto.Unmarshal(raw, &n); e != nil { panic(e) } for _, r := range n.GCPNIHHBGGD { for _, u := range r.JKPJFKCBIEM { if l := u.GetOOICHLAMNIG(); l != nil && l.DCAHJELNJNP == a.DCAHJELNJNP && l.SectionId == a.SectionId && l.IMPNAHBCADN != nil { if level != nil && !proto.Equal(level, l) { panic("conflicting layer recipes") } level = l } } } } if level == nil { panic("next layer capture missing") } marshal := func(m proto.Message) []byte { v, e := proto.Marshal(m) if e != nil { panic(e) } return v } entry := map[string]any{"route_id": b.EMOHLJHPOPC, "chapter_id": b.DCAHJELNJNP, "section_id": b.SectionId, "stage_id": node.StageId, "penalty_id": node.IFIIOIIKJHO, "division_id": before.DivisionId, "is_overclock": before.IsOverlock, "next_level_wire": marshal(level), "next_pending_wire": marshal(after.FMIGOKIDKJL), "round_pending_wire": marshal(round.FMIGOKIDKJL)} raw, e := os.ReadFile("resources/CurrencyWarsInitialRuns.json") if e != nil { panic(e) } var identity map[string]json.RawMessage if e = json.Unmarshal(raw, &identity); e != nil { panic(e) } result := map[string]any{"format_version": 1, "scope": "Captured Standard first-node transition only. Reuses enemy layer/pending definitions; never replaces the player's team or inventory.", "entries": []any{entry}} for _, key := range []string{"target_client_version", "target_assembly_sha256", "source_binary_sha256"} { result[key] = identity[key] } raw, e = json.MarshalIndent(result, "", " ") if e != nil { panic(e) } if e = os.WriteFile(*output, append(raw, '\n'), 0644); e != nil { panic(e) } fmt.Println("Exported node transition", b.DCAHJELNJNP, b.SectionId, "->", a.DCAHJELNJNP, a.SectionId) }