1585 lines
48 KiB
C++
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
|