The app used to always generate a world straight from planet.cfg on launch and F5 always overwrote a single fixed planet.save. Now it opens on a full-screen Main Menu (Home / Settings / Load World) so every PlanetConfig field, the seed, starting a new world, and browsing saves are all reachable without hand-editing planet.cfg, and saves are timestamped so nothing is silently overwritten. A toolbar button reopens the menu later without disturbing a running world. The settings editor is generic (no per-field UI code): configFieldTable() reuses the existing CONFIG_FIELDS X-macro to build a runtime field table, grouped into 25 categories via an explicit name->category lookup (a "first field of each section" boundary scan was tried first and is wrong, since CONFIG_FIELDS emits all doubles, then all ints, then the seed -- not struct declaration order, so most categories aren't contiguous in that order). Save v25 adds the viewer's colour-mode/overlay state, kept out of Planet::writeState/readState's signature so it touches none of the existing headless tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TMfyZv91tonDnPJqbaTVJE
81 lines
3.6 KiB
C++
81 lines
3.6 KiB
C++
// Headless checks for the v25 viewer colour-mode/overlay save block (no window needed).
|
|
// Modeled on test_events.cpp.
|
|
|
|
#include "Viewer.hpp"
|
|
#include <cstdio>
|
|
#include <fstream>
|
|
#include <string>
|
|
|
|
static int failures = 0;
|
|
static void check(bool cond, const char* what) {
|
|
std::printf(" [%s] %s\n", cond ? "PASS" : "FAIL", what);
|
|
if (!cond) ++failures;
|
|
}
|
|
|
|
int main() {
|
|
std::printf("Viewer state: v25 colour-mode/overlay save/load round-trip\n");
|
|
Viewer v;
|
|
PlanetConfig cfg; cfg.subdivisions = 2; cfg.seed = 777;
|
|
v.cfg = cfg;
|
|
v.planet.generate(cfg);
|
|
|
|
// Set every overlay to a value that differs from the Viewer's own defaults, plus a non-default
|
|
// colour mode, so a bug that left fields untouched (rather than round-tripped) would show up.
|
|
v.mode = ColorMode::Biome;
|
|
v.showBorders = false; // default true
|
|
v.showDrift = false; // default true
|
|
v.showRivers = false; // default true
|
|
v.showGrat = true; // default false
|
|
v.dayNightOn = false; // default true
|
|
v.showTides = true; // default false
|
|
v.showCurrents = true; // default false
|
|
v.showClouds = false; // default true
|
|
v.showVolcanoes = false; // default true
|
|
v.showNames = true; // default false
|
|
v.showSettlements = false; // default true
|
|
v.showDiplomacy = false; // default true
|
|
v.showRealms = true; // default false
|
|
|
|
const char* path = "/tmp/fanworgen_viewerstate_test.save";
|
|
v.saveGame(path);
|
|
|
|
Viewer r;
|
|
r.loadGame(path);
|
|
check(r.mode == ColorMode::Biome, "v25 save/load restores the colour mode");
|
|
check(r.showBorders == false, "v25 restores showBorders");
|
|
check(r.showDrift == false, "v25 restores showDrift");
|
|
check(r.showRivers == false, "v25 restores showRivers");
|
|
check(r.showGrat == true, "v25 restores showGrat");
|
|
check(r.dayNightOn == false, "v25 restores dayNightOn");
|
|
check(r.showTides == true, "v25 restores showTides");
|
|
check(r.showCurrents == true, "v25 restores showCurrents");
|
|
check(r.showClouds == false, "v25 restores showClouds");
|
|
check(r.showVolcanoes == false, "v25 restores showVolcanoes");
|
|
check(r.showNames == true, "v25 restores showNames");
|
|
check(r.showSettlements == false, "v25 restores showSettlements");
|
|
check(r.showDiplomacy == false, "v25 restores showDiplomacy");
|
|
check(r.showRealms == true, "v25 restores showRealms");
|
|
check(r.screen == AppScreen::World, "loadGame() switches the app screen to World");
|
|
check(r.menuState.worldEverGenerated, "loadGame() marks a world as having been generated");
|
|
|
|
// Negative test: patch the save's version back to 24 (pre-v25, no mode/overlay block) and load
|
|
// into a fresh Viewer whose defaults differ from the saved-but-truncated values above -- must
|
|
// not crash, and must leave mode/overlays exactly at the fresh Viewer's own pre-load values.
|
|
{
|
|
std::fstream fs(path, std::ios::in | std::ios::out | std::ios::binary);
|
|
uint32_t oldVer = 24;
|
|
fs.seekp(4);
|
|
fs.write((char*)&oldVer, 4);
|
|
}
|
|
Viewer old;
|
|
ColorMode preLoadMode = old.mode;
|
|
bool preLoadBorders = old.showBorders, preLoadRealms = old.showRealms;
|
|
old.loadGame(path);
|
|
check(old.mode == preLoadMode, "pre-v25 saves leave the colour mode at its pre-load value");
|
|
check(old.showBorders == preLoadBorders, "pre-v25 saves leave showBorders at its pre-load value");
|
|
check(old.showRealms == preLoadRealms, "pre-v25 saves leave showRealms at its pre-load value");
|
|
|
|
std::printf(failures ? "\nFAILURES: %d\n" : "\nALL VIEWER STATE CHECKS PASSED\n", failures);
|
|
return failures ? 1 : 0;
|
|
}
|