65 lines
3.3 KiB
C++
65 lines
3.3 KiB
C++
// Hook descriptor for the per-system colony turn (B4):
|
|
//
|
|
// Game::ServerSystem::ProcessTurn(this)
|
|
//
|
|
// A verified `__thiscall` with **no stack arguments** and no return value, so it goes through
|
|
// Hook<> with CallConv::Thiscall. It is called once per system per turn from
|
|
// StrategyServer::ProcessTurn -- about 28 calls on the reference save's End Turn.
|
|
//
|
|
// Why it is worth a compare even though it is a dispatcher: the words the function body writes
|
|
// itself are a real, self-contained slice of a colony turn (the unowned infrastructure decay,
|
|
// both bonus pools, the long-stability accrual, the turn's resource reset, the growth-halt
|
|
// clear and the two per-player countdown sweeps), and they are exactly the ones our
|
|
// `sim::ProcessColonyTurn` models. Everything the callees write is left undeclared, so the
|
|
// harness never compares it.
|
|
//
|
|
// The generator is a declared region as well. A colony turn's only RNG consumer is
|
|
// ProcessRebellion (ProcessPlague, the civilian growth pass and ProcessSlaves were each swept
|
|
// to call depth one and are draw-free), so on a system with no rebellion the post-call state
|
|
// must be **identical** -- and any movement of it names the system whose rebellion fired.
|
|
// COVERAGE STATEMENT (for meta.hooks[H].coverage once HookPolicy carries the field; the
|
|
// harness audit lane owns that struct change, so this lives as text until it lands).
|
|
// state: "partial"
|
|
// unmodelled:
|
|
// - what: "the whole plague pass (ProcessPlague), imperial and civilian population growth,
|
|
// the resource debit (AdjustResources), the in-orbit refuel, ProcessSlaves and
|
|
// ProcessRebellion"
|
|
// risk: high mitigation: "none - those fields are not declared regions at all"
|
|
// - what: "the addiction sweep's morale events: ours computes the {species, event id,
|
|
// delta} list but nothing applies it, so the system's Morale int[7] and its
|
|
// morale-event vector are never written or compared"
|
|
// risk: high why: "this is exactly B3's failure mode - a list append outside every
|
|
// declared region" mitigation: "guard:morale (not yet declared)"
|
|
// - what: "the independent-colony imperial<->civilian pop drift (0x007514f0), called
|
|
// between the bonus pools and the stability check"
|
|
// risk: medium mitigation: "none"
|
|
// - what: "TnsOH, the build queue's own list, and every ship the queue creates"
|
|
// risk: medium mitigation: "none"
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
#include "shim/trace/hook.h"
|
|
|
|
namespace shim::hooks {
|
|
|
|
struct ServerSystemProcessTurnHook {
|
|
static constexpr const char* name = "Game::ServerSystem::ProcessTurn";
|
|
static constexpr trace::CallConv conv = trace::CallConv::Thiscall;
|
|
using Ret = void;
|
|
using Args = std::tuple<void*>; // this (ServerSystem*)
|
|
|
|
static void describe_args(std::vector<trace::Tv>& out, void* self);
|
|
static void regions(std::vector<trace::Region>& out, void* self);
|
|
static Args rebind(trace::Scratch& s, void* self);
|
|
static void ours(void* self);
|
|
static trace::HookPolicy policy() { return trace::HookPolicy{}; }
|
|
};
|
|
|
|
// Process facts the hook needs (exe base for the RVAs, a line logger). Call once before
|
|
// installing.
|
|
void init_colony_turn(std::uintptr_t exe_base, void (*log_line)(const char* line));
|
|
|
|
} // namespace shim::hooks
|