sots-engine/src/mars/stream/shapes.h

1585 lines
48 KiB
C++

// 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 <cstdint>
#include <optional>
#include <string>
#include <vector>
#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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<PlayerInfo> players;
Session session;
int32_t mapShape = 0;
float incMod = 0, resMod = 0;
bool alliances = false, teams = false, encounters = false;
std::string scenario;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Planet> planets; // VectorHelper<SystemParams>
std::vector<std::vector<int32_t>> players; // "." count, n x "." frame{ "." count, n x "." int }
std::vector<Node> nodePaths; // VectorHelper<SimpleNodePath>, empty in the real saves
std::vector<Node> extra;
template <class Ar>
void io(Ar& ar) {
ar.i32(R("mapType"), mapType);
ar.carr(R("planets"), planets);
ar.narr(R("players"), players, [](Ar& a, std::vector<int32_t>& e) { a.carr(R("."), e); });
ar.carr(R("nodePaths"), nodePaths);
ar.rest(extra);
}
};
struct ScriptParam {
std::string spsn, sppn, sppv;
template <class Ar>
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<ScriptParam> params;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<PopG> groups;
std::vector<Node> extra;
template <class Ar>
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 <class Ar>
void io(Ar& ar) {
ar.i32(A("msp"), msp);
ar.i32(A("mv"), mv);
}
};
struct Morale {
static constexpr const char* kStreamName = "";
std::vector<MoraleEntry> entries;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<BuildOrder> orders;
bool ordersFramed = true;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<int32_t> 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<Node> extra;
template <class Ar>
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 <class Ar>
void io(Ar& ar) {
ar.i32(A("haltt"), haltt);
ar.b(A("haltv"), haltv);
}
};
struct AdctEntry {
int32_t ads = 0, adt = 0;
template <class Ar>
void io(Ar& ar) {
ar.i32(A("ads"), ads);
ar.i32(A("adt"), adt);
}
};
struct PlagueEntry {
int32_t plgT = 0;
Node plg;
template <class Ar>
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 <class Ar>
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 <class Ar>
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 <class Ar>
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<float> iSuit;
float suit = 0;
int32_t res = 0;
std::optional<int32_t> 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<HaltEntry> 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<MoraleEvent> cme2;
bool cme2Framed = true;
Node spies2;
int32_t pid = 0, defF = 0, defSF = 0;
std::optional<BuildQueue> bq;
std::vector<AdctEntry> adct;
std::vector<PlagueEntry> plagues;
std::vector<int32_t> fleets, gates, stations, monitors;
std::vector<Colony> colonies;
std::vector<NveEntry> nve;
std::vector<ViewEntry> views;
bool hindi = false;
IndependenceInfo indi;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> sections;
template <class Ar>
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 <class Ar>
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 <class Ar>
void io(Ar& ar) {
ar.i32(A("DesID"), desID);
ar.obj(A("Des"), des);
}
};
struct PrEntry {
float prm = 0;
int32_t prbt = 0;
template <class Ar>
void io(Ar& ar) {
ar.f32(A("PRm"), prm);
ar.i32(A("PRBt"), prbt);
}
};
struct SprjEntry {
int32_t sprjT = 0;
Node sprj;
template <class Ar>
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 <class Ar>
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<float> sensMod;
std::optional<int32_t> 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<int32_t> lcid;
int32_t lcid2 = 0;
std::string resTNm;
bool resErrRoll = false;
ConMods conMods;
bool conModsFramed = false;
std::vector<int32_t> owners;
std::vector<DesignEntry> designs, legacyDesigns;
std::vector<Note> notes;
std::vector<PrEntry> pr;
bool hasAIR = false;
Node air;
bool cta = false;
Node aiEnf;
std::vector<SprjEntry> specialProjects;
std::vector<NexpEntry> nexp;
std::vector<int32_t> weapXcl;
Node ojvs;
std::vector<DipStat> dipstats;
Node comms;
std::vector<Prep> preps;
std::vector<Odes> odes;
std::vector<Owep> owep;
std::vector<Otch> otch;
Node aid;
std::vector<Node> defLayouts, raidTargets;
int32_t tnc = 0;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Waypoint> wpts;
bool wptsFramed = true;
float fpsp2 = 0;
int32_t fpeta2 = 0;
Vec3 fpogn2, fpdpos;
int32_t pnd = 0;
std::vector<Node> extra;
template <class Ar>
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 <class Ar>
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<PrisonerEntry> prisoners;
std::vector<Node> extra;
template <class Ar>
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 <class Ar>
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<Thruster> thrusters;
std::vector<Node> extra;
template <class Ar>
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 <class Ar>
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<int32_t> sysID, trdID;
bool hfPlan = false;
FlightPlan fplan;
std::string ftName;
std::optional<int32_t> caps, gtTrf;
std::optional<float> ftSens;
std::optional<int32_t> 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<ShipEntry> ships;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<CrepPrep> prep;
bool prepFramed = true;
std::vector<Wrep> wrep;
bool wrepFramed = true;
std::vector<Node> extra;
template <class Ar>
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<Node> extra;
template <class Ar>
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<NodePath> paths;
bool pathsFramed = true;
int32_t nextId = 0;
std::vector<Node> extra;
template <class Ar>
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<int32_t> others;
std::vector<Node> extra;
template <class Ar>
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 <class Ar>
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<SystemEvent> sacq, slost;
int32_t trn = 0, almem = 0, inc = 0, tdinc = 0, sav = 0, col = 0, bat = 0, tch = 0;
std::vector<ClassStats> classes;
std::vector<Node> extra;
template <class Ar>
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<PlayerTurnStats> stats; // no count: until the frame END
template <class Ar>
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 <class Ar>
void io(Ar& ar) {
ar.i32(A("ply"), ply);
ar.obj(A("hist"), hist);
}
};
struct TurnStats {
static constexpr const char* kStreamName = "turnstats";
std::vector<TurnHistoryEntry> players;
std::vector<Node> extra;
template <class Ar>
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 <class Ar>
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 <class Ar>
void io(Ar& ar) {
ar.str(A("ISsp"), issp);
ar.f32(A("ISsu"), issu);
}
};
struct PlayerEntry {
int32_t playerID = 0;
Player player;
template <class Ar>
void io(Ar& ar) {
ar.i32(A("PlayerID"), playerID);
ar.obj(A("Player"), player);
}
};
struct SysEntry {
int32_t sysID = 0;
Sys sys;
template <class Ar>
void io(Ar& ar) {
ar.i32(A("SysID"), sysID);
ar.obj(A("Sys"), sys);
}
};
struct FleetEntry {
int32_t fltID = 0;
Fleet flt;
template <class Ar>
void io(Ar& ar) {
ar.i32(A("FltID"), fltID);
ar.obj(A("Flt"), flt);
}
};
struct ZoneDefence {
int32_t zdsi = 0, zdst = 0;
template <class Ar>
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<int32_t> playerIds, designIds, systemIds, fleetIds, shipIds, tradeIds;
int32_t modCount = 0, frame = 0, gameID = 0;
std::optional<int32_t> aiDifficultyID;
Node attrib;
std::optional<int32_t> 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<bool> randEnc;
bool enAl = false, enTm = false;
int32_t goTurn = 0;
std::vector<int32_t> goWinPly;
int32_t npcm = 0, npco = 0, npci = 0, npcv = 0, npca = 0;
std::optional<int32_t> npc;
float szadj = 0, rsadj = 0, suadj = 0;
Node sprjs;
float randEncAdj = 0;
int32_t cmbtid = 0;
TurnStats turnstats;
std::vector<Crep> combatReports;
std::vector<Invasion> invasions;
std::vector<IntPair> exclusions3, exclusions2, exclusionsCF;
std::vector<PlayerEntry> players;
std::vector<Species> species;
std::vector<SysEntry> systems;
NodeGrid ndGr2;
Node trdmgr, spymgr;
std::vector<FleetEntry> fleets;
std::vector<int32_t> acts;
std::optional<Node> svSctOb;
std::vector<ZoneDefence> zoneDefence;
std::vector<Node> extra;
template <class Ar>
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<std::string> ids;
std::vector<Node> extra;
template <class Ar>
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<Node> customData;
template <class Ar>
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