// mars::stream — typed shapes of the SotS 1.8 save stream. // // Field orders and types follow verify/save-reader/SAVE_FORMAT.md (the // confirmed format). A("x") tags are on-disk names; R("x") fields are written // by the game with a NULL name ("." on disk) or carry a reference name whose // disk spelling differs, and are matched by position. Bodies the format keeps // opaque (TechTree, Events, ShipRecs, spy2, civr, comms, Ojvs, Attrib, sprjs, // SvSctOb, trdmgr, spymgr, CD, ...) are held as generic Nodes so a shape can // be re-emitted byte-for-byte. #pragma once #include #include #include #include #include "archive.h" namespace mars::stream::shapes { // Game::PlayerColorID — "." int index; iff -1 the three "." ints r,g,b follow. struct PlayerColor { static constexpr const char* kStreamName = ""; int32_t idx = 0; int32_t r = 0, g = 0, b = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("idx"), idx); ar.when(idx == -1, [&](Ar& a) { a.i32(R("r"), r); a.i32(R("g"), g); a.i32(R("b"), b); }); ar.rest(extra); } }; // ---- Summary (StrategyGameInfo) --------------------------------------------- struct PlayerSettings { // StrategyPlayerGameSettings: 4 x "." int static constexpr const char* kStreamName = "Settings"; int32_t treasury = 0, colonies = 0, techs = 0, difficulty = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("treasury"), treasury); ar.i32(R("colonies"), colonies); ar.i32(R("techs"), techs); ar.i32(R("difficulty"), difficulty); ar.rest(extra); } }; struct Slot { // SlotDef static constexpr const char* kStreamName = "Slot"; bool isPlay = false, isDead = false, isReq = false, isRec = false; bool isFxNm = false; std::string fxNm; bool isFxSp = false; int32_t fxSp = 0; bool isFxCr = false; PlayerColor fxCrID; bool isFxBd = false; std::string fxBd; bool isFxAv = false; std::string fxAv; int32_t tag = 0; std::string pwd; int32_t team = 0; PlayerSettings settings; std::vector extra; template void io(Ar& ar) { ar.b(A("IsPlay"), isPlay); ar.b(A("IsDead"), isDead); ar.b(A("IsReq"), isReq); ar.b(A("IsRec"), isRec); ar.b(A("IsFxNm"), isFxNm); ar.str(A("FxNm"), fxNm); ar.b(A("IsFxSp"), isFxSp); ar.i32(A("FxSp"), fxSp); ar.b(A("IsFxCr"), isFxCr); ar.obj(A("FxCrID"), fxCrID); ar.b(A("IsFxBd"), isFxBd); ar.str(A("FxBd"), fxBd); ar.b(A("IsFxAv"), isFxAv); ar.str(A("FxAv"), fxAv); ar.i32(A("Tag"), tag); ar.str(A("Pwd"), pwd); ar.i32(A("Team"), team); ar.obj(A("Settings"), settings); ar.rest(extra); } }; struct PlayerInfo { // element of Summary.Players ("." frame) static constexpr const char* kStreamName = ""; Slot slot; int32_t rank = 0; std::vector extra; template void io(Ar& ar) { ar.obj(A("Slot"), slot); ar.i32(A("Rank"), rank); ar.rest(extra); } }; struct Tmrs { static constexpr const char* kStreamName = "TMRS"; float tstl = 0, tctl = 0, tqtl = 0, tqtle = 0; std::vector extra; template void io(Ar& ar) { ar.f32(A("TSTL"), tstl); ar.f32(A("TCTL"), tctl); ar.f32(A("TQTL"), tqtl); ar.f32(A("TQTLE"), tqtle); ar.rest(extra); } }; struct Session { static constexpr const char* kStreamName = "Session"; Tmrs tmrs; std::vector extra; template void io(Ar& ar) { ar.obj(A("TMRS"), tmrs); ar.rest(extra); } }; struct Summary { static constexpr const char* kStreamName = "Summary"; std::string gameName; int32_t turn = 0, numSys = 0, checksum = 0; std::vector players; Session session; int32_t mapShape = 0; float incMod = 0, resMod = 0; bool alliances = false, teams = false, encounters = false; std::string scenario; std::vector extra; template void io(Ar& ar) { ar.str(A("GameName"), gameName); ar.i32(A("Turn"), turn); ar.i32(A("NumSys"), numSys); ar.i32(A("Checksum"), checksum); ar.carr(A("Players"), players); ar.obj(A("Session"), session); ar.i32(A("MapShape"), mapShape); ar.f32(A("IncMod"), incMod); ar.f32(A("ResMod"), resMod); ar.b(A("Alliances"), alliances); ar.b(A("Teams"), teams); ar.b(A("Encounters"), encounters); ar.str(A("Scenario"), scenario); ar.rest(extra); } }; // ---- CreateParams (StrategyGameCreateParams) ---------------------------------- struct Planet { // SystemParams element, all tags "." static constexpr const char* kStreamName = ""; Vec3 pos; int32_t p1 = 0, p2 = 0, p3 = 0; float p4 = 0; std::vector extra; template void io(Ar& ar) { ar.vec3(R("pos"), pos); ar.i32(R("p1"), p1); ar.i32(R("p2"), p2); ar.i32(R("p3"), p3); ar.f32(R("p4"), p4); ar.rest(extra); } }; struct MapP { // StarMapParams, all tags "." static constexpr const char* kStreamName = "MapP"; int32_t mapType = 0; std::vector planets; // VectorHelper std::vector> players; // "." count, n x "." frame{ "." count, n x "." int } std::vector nodePaths; // VectorHelper, empty in the real saves std::vector extra; template void io(Ar& ar) { ar.i32(R("mapType"), mapType); ar.carr(R("planets"), planets); ar.narr(R("players"), players, [](Ar& a, std::vector& e) { a.carr(R("."), e); }); ar.carr(R("nodePaths"), nodePaths); ar.rest(extra); } }; struct ScriptParam { std::string spsn, sppn, sppv; template void io(Ar& ar) { ar.str(A("spsn"), spsn); ar.str(A("sppn"), sppn); ar.str(A("sppv"), sppv); } }; struct Scrp { // StrategyScriptParams static constexpr const char* kStreamName = "scrp"; std::vector params; std::vector extra; template void io(Ar& ar) { ar.narr(A("spc"), params, [](Ar& a, ScriptParam& e) { e.io(a); }); ar.rest(extra); } }; struct CreateParams { static constexpr const char* kStreamName = "CreateParams"; std::string name; int32_t id = 0, rseed = 0, aid = 0; std::string key; MapP mapP; int32_t mapS = 0; std::string mapF; int32_t nSys = 0; float rEnc = 0, sDist = 0, sSize = 0, sRes = 0, sSuit = 0; int32_t maxP = 0, aSpec = 0; bool bAlly = false; int32_t nTeam = 0; bool tmgrp = false; int32_t pSav = 0, pCol = 0, pTech = 0; float incM = 0, resM = 0; Scrp scrp; std::vector extra; template void io(Ar& ar) { ar.str(A("Name"), name); ar.i32(A("ID"), id); ar.i32(A("RSeed"), rseed); ar.i32(A("AID"), aid); ar.str(A("Key"), key); ar.obj(A("MapP"), mapP); ar.i32(A("MapS"), mapS); ar.str(A("MapF"), mapF); ar.i32(A("NSys"), nSys); ar.f32(A("REnc"), rEnc); ar.f32(A("SDist"), sDist); ar.f32(A("SSize"), sSize); ar.f32(A("SRes"), sRes); ar.f32(A("SSuit"), sSuit); ar.i32(A("MaxP"), maxP); ar.i32(A("ASpec"), aSpec); ar.b(A("bAlly"), bAlly); ar.i32(A("NTeam"), nTeam); ar.b(A("tmgrp"), tmgrp); ar.i32(A("PSav"), pSav); ar.i32(A("PCol"), pCol); ar.i32(A("PTech"), pTech); ar.f32(A("IncM"), incM); ar.f32(A("ResM"), resM); ar.obj(A("scrp"), scrp); ar.rest(extra); } }; // ---- shared sim types --------------------------------------------------------- struct PopG { static constexpr const char* kStreamName = "PopG"; int32_t popT = 0, popS = 0; int64_t popC = 0; std::vector extra; template void io(Ar& ar) { ar.i32(A("PopT"), popT); ar.i32(A("PopS"), popS); ar.i64(A("PopC"), popC); ar.rest(extra); } }; struct Population { static constexpr const char* kStreamName = ""; std::vector groups; std::vector extra; template void io(Ar& ar) { ar.narr(A("PopNG"), groups, [](Ar& a, PopG& e) { a.obj(A("PopG"), e); }); ar.rest(extra); } }; struct MoraleEntry { int32_t msp = 0, mv = 0; template void io(Ar& ar) { ar.i32(A("msp"), msp); ar.i32(A("mv"), mv); } }; struct Morale { static constexpr const char* kStreamName = ""; std::vector entries; std::vector extra; template void io(Ar& ar) { ar.narr(A("mnsp"), entries, [](Ar& a, MoraleEntry& e) { e.io(a); }); ar.rest(extra); } }; struct MoraleEvent { static constexpr const char* kStreamName = ""; int32_t mid = 0, mtr = 0, mn = 0, mtp = 0; Morale mfx; std::string mdsc; std::vector extra; template void io(Ar& ar) { ar.i32(A("mid"), mid); ar.i32(A("mtr"), mtr); ar.i32(A("mn"), mn); ar.i32(A("mtp"), mtp); ar.obj(A("mfx"), mfx); ar.str(A("mdsc"), mdsc); ar.rest(extra); } }; struct BuildOrder { static constexpr const char* kStreamName = ""; int32_t desID = 0, con = 0, conleft = 0, sav = 0, ordID = 0; std::vector extra; template void io(Ar& ar) { ar.i32(A("desID"), desID); ar.i32(A("con"), con); ar.i32(A("conleft"), conleft); ar.i32(A("sav"), sav); ar.i32(A("ordID"), ordID); ar.rest(extra); } }; struct BuildQueue { static constexpr const char* kStreamName = "BQ"; std::vector orders; bool ordersFramed = true; std::vector extra; template void io(Ar& ar) { ar.carr_flex(R("ords", "ords"), orders, ordersFramed); ar.rest(extra); } }; struct IndependenceInfo { static constexpr const char* kStreamName = "indi"; int32_t indsp = 0; PlayerColor indcl; std::string indnm, indav, indba; std::vector extra; template void io(Ar& ar) { ar.i32(A("indsp"), indsp); ar.obj(A("indcl"), indcl); ar.str(A("indnm"), indnm); ar.str(A("indav"), indav); ar.str(A("indba"), indba); ar.rest(extra); } }; struct Rts { static constexpr const char* kStreamName = "Rts"; float srs = 0, srt = 0, srsc = 0, srtf = 0, sri = 0, sroh = 0; int32_t srnr = 0; std::vector extra; template void io(Ar& ar) { ar.f32(A("SRs"), srs); ar.f32(A("SRt"), srt); ar.f32(A("SRsc"), srsc); ar.f32(A("SRtf"), srtf); ar.f32(A("SRi"), sri); ar.f32(A("SRoh"), sroh); ar.i32(A("SRnr"), srnr); ar.rest(extra); } }; struct PlayerView { static constexpr const char* kStreamName = "pview"; int32_t vtrn = 0, pop = 0; Population pop2; float infra = 0, suit = 0; int32_t res = 0; std::optional aRes; int32_t aRes2 = 0, mRes = 0; bool noRebAI = false; int32_t pbon = 0; Population pbon2; float ibon = 0; int32_t terrFl = 0; bool footer = false; std::vector extra; template void io(Ar& ar) { ar.i32(A("VTrn"), vtrn); ar.i32(A("Pop"), pop); ar.obj(A("Pop2"), pop2); ar.f32(A("Infra"), infra); ar.f32(A("Suit"), suit); ar.i32(A("Res"), res); ar.opt_i32(A("ARes"), aRes); ar.i32(A("ARes2"), aRes2); ar.i32(A("MRes"), mRes); ar.b(A("NoRebAI"), noRebAI); ar.i32(A("pbon"), pbon); ar.obj(A("pbon2"), pbon2); ar.f32(A("ibon"), ibon); ar.i32(A("TerrFl"), terrFl); ar.b(A("footer"), footer); ar.rest(extra); } }; // ---- star system (ServerSystem) ----------------------------------------------- struct HaltEntry { int32_t haltt = 0; bool haltv = false; template void io(Ar& ar) { ar.i32(A("haltt"), haltt); ar.b(A("haltv"), haltv); } }; struct AdctEntry { int32_t ads = 0, adt = 0; template void io(Ar& ar) { ar.i32(A("ads"), ads); ar.i32(A("adt"), adt); } }; struct PlagueEntry { int32_t plgT = 0; Node plg; template void io(Ar& ar) { ar.i32(A("PlgT"), plgT); ar.any(A("Plg"), plg); } }; struct Colony { // NVO entry; indi is an inline member, always present int32_t pid = 0, tshn = 0, oid = 0; bool isind = false; IndependenceInfo indi; template void io(Ar& ar) { ar.i32(A("PID"), pid); ar.i32(A("TShn"), tshn); ar.i32(A("OID"), oid); ar.b(A("isind"), isind); ar.obj(A("indi"), indi); } }; struct NveEntry { int32_t ePid = 0, ets = 0, eid = 0; template void io(Ar& ar) { ar.i32(A("EPid"), ePid); ar.i32(A("ETS"), ets); ar.i32(A("Eid"), eid); } }; struct ViewEntry { int32_t pid = 0; PlayerView pview; template void io(Ar& ar) { ar.i32(R("pid"), pid); ar.obj(R("pview", "pview"), pview); } }; struct Sys { static constexpr const char* kStreamName = "Sys"; Vec3 pos; float r = 0, g = 0, b = 0, a = 0; int32_t idx = 0, size = 0; std::optional iSuit; float suit = 0; int32_t res = 0; std::optional aRes; int32_t aRes2 = 0, mRes = 0; bool noRebAI = false; int32_t tRes = 0, pop = 0; Population pop2; float infra = 0; int32_t pvPop = 0; Population pvPop2; float pvInfra = 0, pvSuit = 0; int32_t pvRes = 0, pvARes2 = 0, pvMRes = 0; bool pvNoRebAI = false; Rts rts; bool abdn = false, dstyd = false; int32_t tnsOH = 0; float outMod = 0, repCur = 0, repMax = 0; int32_t ntdev = 0, pbon = 0; Population pbon2; float ibon = 0; int32_t ltis = 0, rbfl = 0, rbtn = 0, rbfr = 0, rbwn = 0; bool hsrg = false; std::vector halt; bool vnh = false; bool vnd = false, vnex3 = false, vnpex3 = false; std::string name; int32_t vFlags = 0, eFlags = 0, aFlags = 0, fFlags = 0, gFlags = 0; int64_t bats2 = 0, rcex = 0; int32_t mnRFlags = 0, rfRFlags = 0, clkFlags = 0; int32_t eggScio = 0, terrFl = 0, tAcq = 0, tfAcq = 0, tDst = 0; Population dcs; float dsu = 0; Morale cm, pvCM; std::vector cme2; bool cme2Framed = true; Node spies2; int32_t pid = 0, defF = 0, defSF = 0; std::optional bq; std::vector adct; std::vector plagues; std::vector fleets, gates, stations, monitors; std::vector colonies; std::vector nve; std::vector views; bool hindi = false; IndependenceInfo indi; std::vector extra; template void io(Ar& ar) { ar.vec3(A("Pos"), pos); ar.f32(A("R"), r); ar.f32(A("G"), g); ar.f32(A("B"), b); ar.f32(A("A"), a); ar.i32(A("Idx"), idx); ar.i32(A("Size"), size); ar.opt_f32(A("ISuit"), iSuit); ar.f32(A("Suit"), suit); ar.i32(A("Res"), res); ar.opt_i32(A("ARes"), aRes); ar.i32(A("ARes2"), aRes2); ar.i32(A("MRes"), mRes); ar.b(A("NoRebAI"), noRebAI); ar.i32(A("TRes"), tRes); ar.i32(A("Pop"), pop); ar.obj(A("Pop2"), pop2); ar.f32(A("Infra"), infra); ar.i32(A("PvPop"), pvPop); ar.obj(A("PvPop2"), pvPop2); ar.f32(A("PvInfra"), pvInfra); ar.f32(A("PvSuit"), pvSuit); ar.i32(A("PvRes"), pvRes); ar.i32(A("PvARes2"), pvARes2); ar.i32(A("PvMRes"), pvMRes); ar.b(A("PvNoRebAI"), pvNoRebAI); ar.obj(A("Rts"), rts); ar.b(A("Abdn"), abdn); ar.b(A("Dstyd"), dstyd); ar.i32(A("TnsOH"), tnsOH); ar.f32(A("OutMod"), outMod); ar.f32(A("RepCur"), repCur); ar.f32(A("RepMax"), repMax); ar.i32(A("ntdev"), ntdev); ar.i32(A("pbon"), pbon); ar.obj(A("pbon2"), pbon2); ar.f32(A("ibon"), ibon); ar.i32(A("ltis"), ltis); ar.i32(A("rbfl"), rbfl); ar.i32(A("rbtn"), rbtn); ar.i32(A("rbfr"), rbfr); ar.i32(A("rbwn"), rbwn); ar.b(A("hsrg"), hsrg); ar.narr(A("haltc"), halt, [](Ar& a, HaltEntry& e) { e.io(a); }); ar.b(A("vnh"), vnh); ar.when(vnh, [&](Ar& a) { a.b(A("vnd"), vnd); a.b(A("vnex3"), vnex3); a.b(A("vnpex3"), vnpex3); }); ar.str(A("Name"), name); ar.i32(A("VFlags"), vFlags); ar.i32(A("EFlags"), eFlags); ar.i32(A("AFlags"), aFlags); ar.i32(A("FFlags"), fFlags); ar.i32(A("GFlags"), gFlags); ar.i64(A("Bats2"), bats2); ar.i64(A("rcex"), rcex); ar.i32(A("MnRFlags"), mnRFlags); ar.i32(A("RfRFlags"), rfRFlags); ar.i32(A("ClkFlags"), clkFlags); ar.i32(A("EggScio"), eggScio); ar.i32(A("TerrFl"), terrFl); ar.i32(A("TAcq"), tAcq); ar.i32(A("TFAcq"), tfAcq); ar.i32(A("TDst"), tDst); ar.obj(A("dcs"), dcs); ar.f32(A("dsu"), dsu); ar.obj(A("cm"), cm); ar.obj(A("PvCM"), pvCM); ar.carr_flex(A("cme2"), cme2, cme2Framed); ar.any(A("spies2"), spies2); ar.i32(A("PID"), pid); ar.i32(A("DefF"), defF); ar.i32(A("DefSF"), defSF); ar.opt_obj(A("BQ"), bq); ar.narr(A("nadct"), adct, [](Ar& a, AdctEntry& e) { e.io(a); }); ar.narr(A("NumPlgs2"), plagues, [](Ar& a, PlagueEntry& e) { e.io(a); }); ar.narr(A("NumFlts"), fleets, [](Ar& a, int32_t& e) { a.i32(A("Flt"), e); }); ar.narr(A("NumGFs"), gates, [](Ar& a, int32_t& e) { a.i32(A("GF"), e); }); ar.narr(A("NumSnF"), stations, [](Ar& a, int32_t& e) { a.i32(A("SnF"), e); }); ar.narr(A("NumMnF"), monitors, [](Ar& a, int32_t& e) { a.i32(A("MnF"), e); }); ar.narr(A("NVO"), colonies, [](Ar& a, Colony& e) { e.io(a); }); ar.narr(A("NVE"), nve, [](Ar& a, NveEntry& e) { e.io(a); }); ar.narr(A("NVs"), views, [](Ar& a, ViewEntry& e) { e.io(a); }); ar.b(A("hindi"), hindi); ar.when(hindi, [&](Ar& a) { a.obj(A("indi"), indi); }); ar.rest(extra); } }; // ---- player / empire ------------------------------------------------------------ struct Alliances { // the second "Team" item in Player static constexpr const char* kStreamName = "Team"; int32_t alid = 0, al = 0, na = 0, cf = 0; std::vector extra; template void io(Ar& ar) { ar.i32(A("ALid"), alid); ar.i32(A("AL"), al); ar.i32(A("NA"), na); ar.i32(A("CF"), cf); ar.rest(extra); } }; struct DipStat { static constexpr const char* kStreamName = ""; int32_t other = 0; int32_t lastnap = 0, lastnapbty = 0, bknnap = 0, btynap = 0; int32_t lastally = 0, lastallybty = 0, bknally = 0, btyally = 0; int32_t lastcf = 0, lastcfbty = 0, bkncf = 0, btycf = 0; int32_t deadhome = 0; std::vector extra; template void io(Ar& ar) { ar.i32(A("other"), other); ar.i32(A("lastnap"), lastnap); ar.i32(A("lastnapbty"), lastnapbty); ar.i32(A("bknnap"), bknnap); ar.i32(A("btynap"), btynap); ar.i32(A("lastally"), lastally); ar.i32(A("lastallybty"), lastallybty); ar.i32(A("bknally"), bknally); ar.i32(A("btyally"), btyally); ar.i32(A("lastcf"), lastcf); ar.i32(A("lastcfbty"), lastcfbty); ar.i32(A("bkncf"), bkncf); ar.i32(A("btycf"), btycf); ar.i32(A("deadhome"), deadhome); ar.rest(extra); } }; struct Prep { static constexpr const char* kStreamName = ""; int32_t oid = 0, pid = 0, flds = 0, sav = 0, home = 0, ncol = 0, mpwr = 0, mcls = 0, mmsl = 0, nshp = 0, nsat = 0; std::vector extra; template void io(Ar& ar) { ar.i32(A("oid"), oid); ar.i32(A("pid"), pid); ar.i32(A("flds"), flds); ar.i32(A("sav"), sav); ar.i32(A("home"), home); ar.i32(A("ncol"), ncol); ar.i32(A("mpwr"), mpwr); ar.i32(A("mcls"), mcls); ar.i32(A("mmsl"), mmsl); ar.i32(A("nshp"), nshp); ar.i32(A("nsat"), nsat); ar.rest(extra); } }; struct Odes { static constexpr const char* kStreamName = ""; int32_t ontF = 0, otnL = 0, odid = 0, opid = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("ontF", "otnF"), ontF); ar.i32(R("otnL", "otnL"), otnL); ar.i32(R("odid", "odid"), odid); ar.i32(R("opid", "opid"), opid); ar.rest(extra); } }; struct Owep { static constexpr const char* kStreamName = ""; int32_t ontF = 0, otnL = 0, odet = 0; std::string owep; int32_t owith = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("ontF", "otnF"), ontF); ar.i32(R("otnL", "otnL"), otnL); ar.i32(R("odet", "odet"), odet); ar.str(R("owep", "owep"), owep); ar.i32(R("owith", "owith"), owith); ar.rest(extra); } }; struct Otch { static constexpr const char* kStreamName = ""; int32_t ontF = 0, otnL = 0, odet = 0; std::string otch; int32_t owith = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("ontF", "otnF"), ontF); ar.i32(R("otnL", "otnL"), otnL); ar.i32(R("odet", "odet"), odet); ar.str(R("otch", "otch"), otch); ar.i32(R("owith", "owith"), owith); ar.rest(extra); } }; struct Note { static constexpr const char* kStreamName = "Nts"; int32_t ntSys = 0; std::string ntTxt; int32_t ntTrn = 0; std::vector extra; template void io(Ar& ar) { ar.i32(A("NtSys"), ntSys); ar.str(A("NtTxt"), ntTxt); ar.i32(A("NtTrn"), ntTrn); ar.rest(extra); } }; struct Design { // on-disk tags are case variants of the reference names (FAIDes, DHide, DWep, DName) static constexpr const char* kStreamName = "Des"; bool faiDes = false, dHide = false; int32_t dWep = 0; std::string dName; std::vector sections; template void io(Ar& ar) { ar.b(R("faiDes", "FAIDes"), faiDes); ar.b(R("dHide", "DHide"), dHide); ar.i32(R("dWep", "DWep"), dWep); ar.str(R("dName", "DName"), dName); ar.rest(sections); } }; struct ConMods { static constexpr const char* kStreamName = "ConMods"; float conMod0 = 0, savMod0 = 0, conMod1 = 0, savMod1 = 0, conMod2 = 0, savMod2 = 0; template void io(Ar& ar) { ar.f32(A("ConMod"), conMod0); ar.f32(A("SavMod"), savMod0); ar.f32(A("ConMod"), conMod1); ar.f32(A("SavMod"), savMod1); ar.f32(A("ConMod"), conMod2); ar.f32(A("SavMod"), savMod2); } }; struct DesignEntry { int32_t desID = 0; Design des; template void io(Ar& ar) { ar.i32(A("DesID"), desID); ar.obj(A("Des"), des); } }; struct PrEntry { float prm = 0; int32_t prbt = 0; template void io(Ar& ar) { ar.f32(A("PRm"), prm); ar.i32(A("PRBt"), prbt); } }; struct SprjEntry { int32_t sprjT = 0; Node sprj; template void io(Ar& ar) { ar.i32(A("SprjT"), sprjT); ar.any(A("Sprj"), sprj); } }; struct NexpEntry { int32_t xid = 0, xmin = 0, xmax = 0; float xper = 0; template void io(Ar& ar) { ar.i32(A("xid"), xid); ar.i32(A("xmin"), xmin); ar.i32(A("xmax"), xmax); ar.f32(A("xper"), xper); } }; struct Player { static constexpr const char* kStreamName = "Player"; Node techTree; int32_t homeSys = 0, plyrIdx = 0; std::string plryName; int32_t species = 0; PlayerColor clrID; std::string bdg, avt; int32_t team = 0, sav = 0; float idealSuit = 0, suitTol = 0, maxOH = 0, resRate = 0, resMod = 0, resScl = 0, trm = 0; int32_t trp = 0, tra = 0; float outMod = 0, rebOutMod = 0, scOutMod = 0, incMod = 0; std::optional sensMod; std::optional exPopSys; float popMod = 0, terraMod = 0; bool aMine = false; float minPure = 0, minRate = 0; int32_t nGts = 0, prGtTrf = 0, gTraf = 0; float cstR = 0, cstE = 0, cstT = 0; int32_t maint = 0; float shrm = 0; int32_t status = 0; bool elim = false, npc = false, rebAI = false, reqCL = false; Alliances alliances; int32_t hasVac = 0, hasImm = 0, npTrk = 0, hasDisc = 0, hasDiscSp = 0, hasDiscCl = 0, hasEnc = 0, hasEng = 0; Node events, fng; int32_t pvSav = 0; bool pvMA = false, aiBn = false, cnTrd = false, cnRad = false, hgs = false, hadvs = false, harcc = false, cnVItl = false; float pddm = 0; int32_t bnkWrn = 0, bnkTrn = 0, bnkPr = 0, bnkEl = 0; Node shipRecs; int32_t nextPrjID = 0, plcy = 0; std::string pswd; int32_t lret = 0, nmeid = 0; bool cdp = false; Node spy2, civr; int32_t aidf = 0; bool srn = false; int32_t srnTo = 0, lboid = 0; std::optional lcid; int32_t lcid2 = 0; std::string resTNm; bool resErrRoll = false; ConMods conMods; bool conModsFramed = false; std::vector owners; std::vector designs, legacyDesigns; std::vector notes; std::vector pr; bool hasAIR = false; Node air; bool cta = false; Node aiEnf; std::vector specialProjects; std::vector nexp; std::vector weapXcl; Node ojvs; std::vector dipstats; Node comms; std::vector preps; std::vector odes; std::vector owep; std::vector otch; Node aid; std::vector defLayouts, raidTargets; int32_t tnc = 0; std::vector extra; template void io(Ar& ar) { ar.any(A("TechTree"), techTree); ar.i32(A("HomeSys"), homeSys); ar.i32(A("PlyrIdx"), plyrIdx); ar.str(A("PlryName"), plryName); ar.i32(A("Species"), species); ar.obj(A("ClrID"), clrID); ar.str(A("Bdg"), bdg); ar.str(A("Avt"), avt); ar.i32(A("Team"), team); ar.i32(A("Sav"), sav); ar.f32(A("IdealSuit"), idealSuit); ar.f32(A("SuitTol"), suitTol); ar.f32(A("MaxOH"), maxOH); ar.f32(A("ResRate"), resRate); ar.f32(A("ResMod"), resMod); ar.f32(A("ResScl"), resScl); ar.f32(A("TRM"), trm); ar.i32(A("TRP"), trp); ar.i32(A("TRA"), tra); ar.f32(A("OutMod"), outMod); ar.f32(A("RebOutMod"), rebOutMod); ar.f32(A("ScOutMod"), scOutMod); ar.f32(A("IncMod"), incMod); ar.opt_f32(A("SensMod"), sensMod); ar.opt_i32(A("ExPopSys"), exPopSys); ar.f32(A("PopMod"), popMod); ar.f32(A("TerraMod"), terraMod); ar.b(A("AMine"), aMine); ar.f32(A("MinPure"), minPure); ar.f32(A("MinRate"), minRate); ar.i32(A("NGts"), nGts); ar.i32(A("PrGtTrf"), prGtTrf); ar.i32(A("GTraf"), gTraf); ar.f32(A("CstR"), cstR); ar.f32(A("CstE"), cstE); ar.f32(A("CstT"), cstT); ar.i32(A("Maint"), maint); ar.f32(A("shrm"), shrm); ar.i32(A("Status"), status); ar.b(A("Elim"), elim); ar.b(A("NPC"), npc); ar.b(A("RebAI"), rebAI); ar.b(A("ReqCL"), reqCL); ar.obj(A("Team"), alliances); ar.i32(A("HasVac"), hasVac); ar.i32(A("HasImm"), hasImm); ar.i32(A("NPTrk"), npTrk); ar.i32(A("HasDisc"), hasDisc); ar.i32(A("HasDiscSp"), hasDiscSp); ar.i32(A("HasDiscCl"), hasDiscCl); ar.i32(A("HasEnc"), hasEnc); ar.i32(A("HasEng"), hasEng); ar.any(A("Events"), events); ar.any(A("FNG"), fng); ar.i32(A("PvSav"), pvSav); ar.b(A("PvMA"), pvMA); ar.b(A("AIBn"), aiBn); ar.b(A("CnTrd"), cnTrd); ar.b(A("CnRad"), cnRad); ar.b(A("hgs"), hgs); ar.b(A("hadvs"), hadvs); ar.b(A("harcc"), harcc); ar.b(A("CnVItl"), cnVItl); ar.f32(A("pddm"), pddm); ar.i32(A("BnkWrn"), bnkWrn); ar.i32(A("BnkTrn"), bnkTrn); ar.i32(A("BnkPr"), bnkPr); ar.i32(A("BnkEl"), bnkEl); ar.any(A("ShipRecs"), shipRecs); ar.i32(A("NextPrjID"), nextPrjID); ar.i32(A("plcy"), plcy); ar.str(A("pswd"), pswd); ar.i32(A("lret"), lret); ar.i32(A("nmeid"), nmeid); ar.b(A("cdp"), cdp); ar.any(A("spy2"), spy2); ar.any(A("civr"), civr); ar.i32(A("aidf"), aidf); ar.b(A("Srn"), srn); ar.i32(A("SrnTo"), srnTo); ar.i32(A("lboid"), lboid); ar.opt_i32(A("lcid"), lcid); ar.i32(A("lcid2"), lcid2); ar.str(A("ResTNm"), resTNm); ar.b(A("ResErrRoll"), resErrRoll); ar.obj_flex(R("conMods", "ConMods"), conMods, conModsFramed); ar.narr(A("NumOwn"), owners, [](Ar& a, int32_t& e) { a.i32(A("OwnId"), e); }); ar.narr(A("NumDes"), designs, [](Ar& a, DesignEntry& e) { e.io(a); }); ar.narr(A("NumLeg"), legacyDesigns, [](Ar& a, DesignEntry& e) { e.io(a); }); ar.narr(A("NumNotes"), notes, [](Ar& a, Note& e) { a.obj(A("Nts"), e); }); ar.narr(A("NumPR"), pr, [](Ar& a, PrEntry& e) { e.io(a); }); ar.b(A("HasAIR"), hasAIR); ar.when(hasAIR, [&](Ar& a) { a.any(A("AIR"), air); }); ar.b(A("cta"), cta); ar.any(A("AIEnf"), aiEnf); ar.narr(A("NSprj"), specialProjects, [](Ar& a, SprjEntry& e) { e.io(a); }); ar.narr(A("Nexp"), nexp, [](Ar& a, NexpEntry& e) { e.io(a); }); ar.narr(A("NWeapXcl"), weapXcl, [](Ar& a, int32_t& e) { a.i32(A("WeapXcl"), e); }); ar.any(A("Ojvs"), ojvs); ar.carr(A("dipstats"), dipstats); ar.any(A("comms"), comms); ar.carr(A("preps"), preps); ar.carr(A("odes"), odes); ar.carr(A("owep"), owep); ar.carr(A("otch"), otch); ar.any(A("aid"), aid); ar.narr(A("ndeflay"), defLayouts, [](Ar& a, Node& e) { a.any(A("deflay"), e); }); ar.narr(A("rdtc"), raidTargets, [](Ar& a, Node& e) { a.any(A("rdt"), e); }); ar.i32(A("tnc"), tnc); ar.rest(extra); } }; // ---- fleets & ships -------------------------------------------------------------- struct NodeRoute { static constexpr const char* kStreamName = "nrt"; int32_t nrp = 0, nrf = 0, nrt = 0; std::vector extra; template void io(Ar& ar) { ar.i32(A("nrp"), nrp); ar.i32(A("nrf"), nrf); ar.i32(A("nrt"), nrt); ar.rest(extra); } }; struct Waypoint { static constexpr const char* kStreamName = ""; int32_t wpt = 0, tp = 0; NodeRoute nrt; bool nrtFramed = true; std::vector extra; template void io(Ar& ar) { ar.i32(A("Wpt"), wpt); ar.i32(A("Tp"), tp); ar.obj_flex(R("nrt", "nrt"), nrt, nrtFramed); ar.rest(extra); } }; struct FlightPlan { static constexpr const char* kStreamName = "FPlan"; std::vector wpts; bool wptsFramed = true; float fpsp2 = 0; int32_t fpeta2 = 0; Vec3 fpogn2, fpdpos; int32_t pnd = 0; std::vector extra; template void io(Ar& ar) { ar.carr_flex(R("wpts", "wpts"), wpts, wptsFramed); ar.f32(A("FPsp2"), fpsp2); ar.i32(A("FPeta2"), fpeta2); ar.vec3(A("FPogn2"), fpogn2); ar.vec3(A("FPdpos"), fpdpos); ar.i32(A("pnd"), pnd); ar.rest(extra); } }; struct PrisonerEntry { int32_t prSp = 0, prNum = 0; template void io(Ar& ar) { ar.i32(A("PrSp"), prSp); ar.i32(A("PrNum"), prNum); } }; struct PrisonerHold { static constexpr const char* kStreamName = "PrisH"; int32_t prMax = 0; std::vector prisoners; std::vector extra; template void io(Ar& ar) { ar.i32(A("PrMax"), prMax); ar.when(prMax > 0, [&](Ar& a) { a.narr(A("PrNSp"), prisoners, [](Ar& b, PrisonerEntry& e) { e.io(b); }); }); ar.rest(extra); } }; struct Thruster { float th = 0, thm = 0; template void io(Ar& ar) { ar.f32(A("TH"), th); ar.f32(A("THM"), thm); } }; struct Ship { static constexpr const char* kStreamName = "Ship"; int32_t desID = 0, fltID = 0, plrID = 0; float range = 0; Vec3 health; int32_t conCap = 0; float refCap = 0, repCap = 0; int32_t mineCap = 0, plg = 0, act = 0; bool dep = false, atq = false; int32_t encID = 0; PrisonerHold prisH; int32_t lct = 0, tsd = 0, atsp = 0, tblt = 0; bool hbq = false; BuildQueue bq2; bool hsp = false; Population pop, ppop; std::vector thrusters; std::vector extra; template void io(Ar& ar) { ar.i32(A("DesID"), desID); ar.i32(A("FltID"), fltID); ar.i32(A("PlrID"), plrID); ar.f32(A("Range"), range); ar.vec3(A("Health"), health); ar.i32(A("ConCap"), conCap); ar.f32(A("RefCap"), refCap); ar.f32(A("RepCap"), repCap); ar.i32(A("MineCap"), mineCap); ar.i32(A("Plg"), plg); ar.i32(A("Act"), act); ar.b(A("Dep"), dep); ar.b(A("Atq"), atq); ar.i32(A("EncID"), encID); ar.obj(A("PrisH"), prisH); ar.i32(A("LCT"), lct); ar.i32(A("tsd"), tsd); ar.i32(A("atsp"), atsp); ar.i32(A("tblt"), tblt); ar.b(A("hbq"), hbq); ar.when(hbq, [&](Ar& a) { a.obj(A("BQ2"), bq2); }); ar.b(A("hsp"), hsp); ar.when(hsp, [&](Ar& a) { a.obj(A("pop"), pop); a.obj(A("ppop"), ppop); }); ar.narr(A("NTH"), thrusters, [](Ar& a, Thruster& e) { e.io(a); }); ar.rest(extra); } }; struct ShipEntry { int32_t shipID = 0; Ship ship; template void io(Ar& ar) { ar.i32(A("ShipID"), shipID); ar.obj(A("Ship"), ship); } }; struct Fleet { static constexpr const char* kStreamName = "Flt"; Vec3 pos; int32_t pid = 0, locID = 0; std::optional sysID, trdID; bool hfPlan = false; FlightPlan fplan; std::string ftName; std::optional caps, gtTrf; std::optional ftSens; std::optional ftInc; int32_t ftTrans = 0; Vec3 ftOrig; int32_t ftFlg = 0, ftae = 0, ftpae = 0, ftEnc = 0, ftMS = 0; bool perm = false; Vec3 prvPos; bool hLay = false; Node lay; std::vector ships; std::vector extra; template void io(Ar& ar) { ar.vec3(A("Pos"), pos); ar.i32(A("PID"), pid); ar.i32(A("LocID"), locID); ar.opt_i32(A("SysID"), sysID); ar.opt_i32(A("TrdID"), trdID); ar.b(A("HFPlan"), hfPlan); ar.when(hfPlan, [&](Ar& a) { a.obj(A("FPlan"), fplan); }); ar.str(A("FtName"), ftName); ar.opt_i32(A("Caps"), caps); ar.opt_i32(A("GtTrf"), gtTrf); ar.opt_f32(A("FtSens"), ftSens); ar.opt_i32(A("FtInc"), ftInc); ar.i32(A("FtTrans"), ftTrans); ar.vec3(A("FtOrig"), ftOrig); ar.i32(A("FtFlg"), ftFlg); ar.i32(A("Ftae"), ftae); ar.i32(A("Ftpae"), ftpae); ar.i32(A("FtEnc"), ftEnc); ar.i32(A("FtMS"), ftMS); ar.b(A("Perm"), perm); ar.vec3(A("PrvPos"), prvPos); ar.b(A("HLay"), hLay); ar.when(hLay, [&](Ar& a) { a.any(A("Lay"), lay); }); ar.narr(A("NShips"), ships, [](Ar& a, ShipEntry& e) { e.io(a); }); ar.rest(extra); } }; // ---- combat reports, node grid --------------------------------------------------- struct Dams { static constexpr const char* kStreamName = "dams"; int32_t dams = 0, damp = 0, dami = 0, damt = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("dams", "dams"), dams); ar.i32(R("damp", "damp"), damp); ar.i32(R("dami", "dami"), dami); ar.i32(R("damt", "damt"), damt); ar.rest(extra); } }; struct Wrep { static constexpr const char* kStreamName = ""; std::string wep; Dams dams; bool damsFramed = true; std::vector extra; template void io(Ar& ar) { ar.str(R("wep", "wep"), wep); ar.obj_flex(R("dams", "dams"), dams, damsFramed); ar.rest(extra); } }; struct CrepPrep { static constexpr const char* kStreamName = ""; int32_t plr = 0; bool ai = false; int32_t ally = 0, status = 0, mxeng = 0, mxcls = 0, mxmsl = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("plr", "plr"), plr); ar.b(R("ai", "ai"), ai); ar.i32(R("ally", "ally"), ally); ar.i32(R("status", "status"), status); ar.i32(R("mxeng", "mxeng"), mxeng); ar.i32(R("mxcls", "mxcls"), mxcls); ar.i32(R("mxmsl", "mxmsl"), mxmsl); ar.rest(extra); } }; struct Crep { static constexpr const char* kStreamName = "crep"; int32_t cid = 0, trn = 0; Vec3 pos; int32_t sid = 0, autoF = 0, dur = 0, cow = 0, cdst = 0, cpk = 0, cpt = 0, cdt = 0, cdi = 0; std::vector prep; bool prepFramed = true; std::vector wrep; bool wrepFramed = true; std::vector extra; template void io(Ar& ar) { ar.i32(R("cid", "cid"), cid); ar.i32(R("trn", "trn"), trn); ar.vec3(R("pos", "pos"), pos); ar.i32(R("sid", "sid"), sid); ar.i32(R("auto", "auto"), autoF); ar.i32(R("dur", "dur"), dur); ar.i32(R("cow", "cow"), cow); ar.i32(R("cdst", "cdst"), cdst); ar.i32(R("cpk", "cpk"), cpk); ar.i32(R("cpt", "cpt"), cpt); ar.i32(R("cdt", "cdt"), cdt); ar.i32(R("cdi", "cdi"), cdi); ar.carr_flex(R("prep", "prep"), prep, prepFramed); ar.carr_flex(R("wrep", "wrep"), wrep, wrepFramed); ar.rest(extra); } }; struct NodePath { static constexpr const char* kStreamName = ""; int32_t npt = 0, npid = 0, npfr = 0, npto = 0, npctm = 0, npcby = 0, npdtn = 0, npdtf = 0, npenp = 0, npuse = 0, nptf = 0; std::vector extra; template void io(Ar& ar) { ar.i32(R("npt", "npt"), npt); ar.i32(R("npid", "npid"), npid); ar.i32(R("npfr", "npfr"), npfr); ar.i32(R("npto", "npto"), npto); ar.i32(R("npctm", "npctm"), npctm); ar.i32(R("npcby", "npcby"), npcby); ar.i32(R("npdtn", "npdtn"), npdtn); ar.i32(R("npdtf", "npdtf"), npdtf); ar.i32(R("npenp", "npenp"), npenp); ar.i32(R("npuse", "npuse"), npuse); ar.i32(R("nptf", "nptf"), nptf); ar.rest(extra); } }; struct NodeGrid { static constexpr const char* kStreamName = "NdGr2"; std::vector paths; bool pathsFramed = true; int32_t nextId = 0; std::vector extra; template void io(Ar& ar) { ar.carr_flex(R("paths", "paths"), paths, pathsFramed); ar.i32(R("nextId", "nextid"), nextId); ar.rest(extra); } }; // ---- turn statistics --------------------------------------------------------------- struct SystemEvent { static constexpr const char* kStreamName = ""; int32_t set = 0, ses = 0, seop = 0, senp = 0; std::vector others; std::vector extra; template void io(Ar& ar) { ar.i32(A("set"), set); ar.i32(A("ses"), ses); ar.i32(A("seop"), seop); ar.i32(A("senp"), senp); ar.narr(A("seno2"), others, [](Ar& a, int32_t& e) { a.i32(A("seot2"), e); }); ar.rest(extra); } }; struct ClassStats { int32_t cls = 0, shpt = 0, shpl = 0, shpk = 0, satt = 0, satl = 0, satk = 0; template void io(Ar& ar) { ar.i32(A("cls"), cls); ar.i32(A("shpt"), shpt); ar.i32(A("shpl"), shpl); ar.i32(A("shpk"), shpk); ar.i32(A("satt"), satt); ar.i32(A("satl"), satl); ar.i32(A("satk"), satk); } }; struct PlayerTurnStats { static constexpr const char* kStreamName = "stats"; int64_t pop = 0; std::vector sacq, slost; int32_t trn = 0, almem = 0, inc = 0, tdinc = 0, sav = 0, col = 0, bat = 0, tch = 0; std::vector classes; std::vector extra; template void io(Ar& ar) { ar.i64(A("pop"), pop); ar.carr(A("sacq"), sacq); ar.carr(A("slost"), slost); ar.i32(A("trn"), trn); ar.i32(A("almem"), almem); ar.i32(A("inc"), inc); ar.i32(A("tdinc"), tdinc); ar.i32(A("sav"), sav); ar.i32(A("col"), col); ar.i32(A("bat"), bat); ar.i32(A("tch"), tch); ar.narr(A("ncls"), classes, [](Ar& a, ClassStats& e) { e.io(a); }); ar.rest(extra); } }; struct PlayerTurnHistory { static constexpr const char* kStreamName = "hist"; int32_t ply = 0; std::vector stats; // no count: until the frame END template void io(Ar& ar) { ar.i32(A("ply"), ply); ar.repeat("stats", stats, [](Ar& a, PlayerTurnStats& e) { a.obj(A("stats"), e); }); } }; struct TurnHistoryEntry { int32_t ply = 0; PlayerTurnHistory hist; template void io(Ar& ar) { ar.i32(A("ply"), ply); ar.obj(A("hist"), hist); } }; struct TurnStats { static constexpr const char* kStreamName = "turnstats"; std::vector players; std::vector extra; template void io(Ar& ar) { ar.narr(A("nply"), players, [](Ar& a, TurnHistoryEntry& e) { e.io(a); }); ar.rest(extra); } }; // ---- Sim block (StrategyServer) ------------------------------------------------------ struct Invasion { int32_t invs = 0, inve = 0, invt = 0, invtb = 0; template void io(Ar& ar) { ar.i32(A("invs"), invs); ar.i32(A("inve"), inve); ar.i32(A("invt"), invt); ar.i32(A("invtb"), invtb); } }; struct IntPair { int32_t a = 0, b = 0; }; struct Species { std::string issp; float issu = 0; template void io(Ar& ar) { ar.str(A("ISsp"), issp); ar.f32(A("ISsu"), issu); } }; struct PlayerEntry { int32_t playerID = 0; Player player; template void io(Ar& ar) { ar.i32(A("PlayerID"), playerID); ar.obj(A("Player"), player); } }; struct SysEntry { int32_t sysID = 0; Sys sys; template void io(Ar& ar) { ar.i32(A("SysID"), sysID); ar.obj(A("Sys"), sys); } }; struct FleetEntry { int32_t fltID = 0; Fleet flt; template void io(Ar& ar) { ar.i32(A("FltID"), fltID); ar.obj(A("Flt"), flt); } }; struct ZoneDefence { int32_t zdsi = 0, zdst = 0; template void io(Ar& ar) { ar.i32(A("zdsi"), zdsi); ar.i32(A("zdst"), zdst); } }; struct Sim { static constexpr const char* kStreamName = "Sim"; std::string keyPath; int32_t nmSz = 0, nmLc = 0, nmnx = 0; std::vector playerIds, designIds, systemIds, fleetIds, shipIds, tradeIds; int32_t modCount = 0, frame = 0, gameID = 0; std::optional aiDifficultyID; Node attrib; std::optional rand; Node rng; // opaque MT19937 blob: frame with one "." raw item (mt[624] + left, 3 pad bytes) std::string gameName; int32_t map = 0; float incMod = 0, resMod = 0; std::optional randEnc; bool enAl = false, enTm = false; int32_t goTurn = 0; std::vector goWinPly; int32_t npcm = 0, npco = 0, npci = 0, npcv = 0, npca = 0; std::optional npc; float szadj = 0, rsadj = 0, suadj = 0; Node sprjs; float randEncAdj = 0; int32_t cmbtid = 0; TurnStats turnstats; std::vector combatReports; std::vector invasions; std::vector exclusions3, exclusions2, exclusionsCF; std::vector players; std::vector species; std::vector systems; NodeGrid ndGr2; Node trdmgr, spymgr; std::vector fleets; std::vector acts; std::optional svSctOb; std::vector zoneDefence; std::vector extra; template void io(Ar& ar) { auto idlist = [](Ar& a, int32_t& e) { a.i32(R("."), e); }; ar.str(A("KeyPath"), keyPath); ar.i32(A("NMSz"), nmSz); ar.i32(A("NMLc"), nmLc); ar.i32(A("NMnx"), nmnx); ar.narr(A("PlayerIDs"), playerIds, idlist); ar.narr(A("DesignIDs"), designIds, idlist); ar.narr(A("SystemIDs"), systemIds, idlist); ar.narr(A("FleetIDs"), fleetIds, idlist); ar.narr(A("ShipIDs"), shipIds, idlist); ar.narr(A("TradeIDs"), tradeIds, idlist); ar.i32(A("ModCount"), modCount); ar.i32(A("Frame"), frame); ar.i32(A("GameID"), gameID); ar.opt_i32(A("AIDifficultyID"), aiDifficultyID); ar.any(A("Attrib"), attrib); ar.opt_i32(A("Rand"), rand); ar.raw_frame(A("RNG"), rng); ar.str(A("GameName"), gameName); ar.i32(A("Map"), map); ar.f32(A("IncMod"), incMod); ar.f32(A("ResMod"), resMod); ar.opt_b(A("RandEnc"), randEnc); ar.b(A("EnAl"), enAl); ar.b(A("EnTm"), enTm); ar.i32(A("GOTurn"), goTurn); ar.carr(A("GOWinPly"), goWinPly); ar.i32(A("NPCm"), npcm); ar.i32(A("NPCo"), npco); ar.i32(A("NPCi"), npci); ar.i32(A("NPCv"), npcv); ar.i32(A("NPCa"), npca); ar.opt_i32(A("NPC"), npc); ar.f32(A("szadj"), szadj); ar.f32(A("rsadj"), rsadj); ar.f32(A("suadj"), suadj); ar.any(A("sprjs"), sprjs); ar.f32(A("RandEncAdj"), randEncAdj); ar.i32(A("cmbtid"), cmbtid); ar.obj(A("turnstats"), turnstats); ar.narr(A("numcreps"), combatReports, [](Ar& a, Crep& e) { a.obj(A("crep"), e); }); ar.narr(A("ninv"), invasions, [](Ar& a, Invasion& e) { e.io(a); }); auto excl = [](Ar& a, IntPair& e) { a.i32(A("AllExc"), e.a); a.i32(A("AllExc"), e.b); }; ar.narr(A("AllExc"), exclusions3, excl); ar.narr(A("AllExc"), exclusions2, excl); ar.narr(A("AllExcCF"), exclusionsCF, [](Ar& a, IntPair& e) { a.i32(A("AllExcCFp"), e.a); a.i32(A("AllExcCFp"), e.b); }); ar.narr(A("NumPlrs"), players, [](Ar& a, PlayerEntry& e) { e.io(a); }); ar.repeat("ISsp", species, [](Ar& a, Species& e) { e.io(a); }); // 7 pairs, no count ar.narr(A("NumSys"), systems, [](Ar& a, SysEntry& e) { e.io(a); }); ar.obj(A("NdGr2"), ndGr2); ar.any(A("trdmgr"), trdmgr); ar.any(A("spymgr"), spymgr); ar.narr(A("NumFlts"), fleets, [](Ar& a, FleetEntry& e) { e.io(a); }); ar.narr(A("NumActs"), acts, [](Ar& a, int32_t& e) { a.i32(A("Act"), e); }); ar.opt_any(A("SvSctOb"), svSctOb); // only if the pointer was non-NULL ar.narr(A("zdsc"), zoneDefence, [](Ar& a, ZoneDefence& e) { e.io(a); }); ar.rest(extra); } }; // ---- custom-data table + file root ----------------------------------------------------- struct CdTable { static constexpr const char* kStreamName = "CDT"; std::vector ids; std::vector extra; template void io(Ar& ar) { ar.narr(A("NumIDs"), ids, [](Ar& a, std::string& e) { a.str(A("ID"), e); }); ar.rest(extra); } }; struct SaveGame { // root: Summary, CreateParams, Sim, CDT, then one opaque CD frame per id with data static constexpr const char* kStreamName = ""; Summary summary; CreateParams createParams; Sim sim; CdTable cdTable; std::vector customData; template void io(Ar& ar) { ar.obj(A("Summary"), summary); ar.obj(A("CreateParams"), createParams); ar.obj(A("Sim"), sim); ar.obj(A("CDT"), cdTable); ar.repeat("CD", customData, [](Ar& a, Node& e) { a.any(A("CD"), e); }); } }; } // namespace mars::stream::shapes