Commit graph

4 commits

Author SHA1 Message Date
WiseDev
81d6fe3922 take the checksum from before the closing checkpoint
LogicGameMode::encode reads its return value out of getCheckSum() and
only then writes it:

  v15 = ChecksumEncoder::getCheckSum(a2);
  (...vptr+88)(a2, v15);        // the checkpoint vint
  return v15;

we were reading ours after that write, so the closing checkpoint was
folded into the number we compared. the two could never match, whatever
the simulation did - which is why tick 41 disagreed with six untouched
towers on the field.

write() now hands back the value it wrote, the way encode() does.
2026-08-23 15:04:51 +03:00
WiseDev
ade049b29d write the tick the client writes
the leading vint of the game mode is not a field of its own. the client
loads it straight out of LogicTime at gameMode+0x60 and then encodes
LogicTime immediately after, so the same number goes out twice and the
two cannot drift. we kept a separate server_tick that the session never
advanced, so it stayed at zero while the clock ran - a divergence in the
checksum that had nothing to do with the simulation. the field is gone
and the tick comes from LogicTime.
2026-08-23 13:47:34 +03:00
WiseDev
438e2c6491 compare the server checksum against the client's
LogicGameMode::calculateChecksum runs the whole game mode through a
ChecksumEncoder - in a battle there is no client home, so it is the same
encode as the snapshot with the command manager left out. we compute the
same number now and log it beside the one the client sends in every turn
message, with whether they agree.

that comparison only means something because of what turned up while
reading the encoder: the two vints the decoder throws away are not
padding. the client writes getCheckSum() into both, once after the
server tick and once after the tutorial manager. we were writing zero,
which parses fine - the decoder discards them either way - but poisons
the running checksum, so the numbers could never have matched. they
carry the real running value now.

the two will not agree yet. the point is to see how far apart they are
and where, since the gap is what stands between this and battle type 0.
2026-08-23 13:44:51 +03:00
WiseDev
774e7c60cf build and send the battle sector state
npc missions used to get a ServerErrorMessage back. now StartMission builds a
LogicGameMode snapshot off the arena tilemap and answers 21903.

towers come from assets/locations/*.csv the way initDefaultSector does it: tile
coordinates times 500, leader index decided by which half of the map the tower
sits in. the two king towers must be there, the client dereferences them without
a null check. they live in buildings.csv, not characters.csv.

LogicCharacter puts the base object fields fourth, not first. the buff component
writes a fixed array sized by the character_buffs row count even with no buffs.

training_arena parses to 2 kings, 4 princess towers, 36x64 subtiles. snapshot is
602 bytes over 6 objects. the real client has not seen it yet.
2026-08-23 10:24:20 +03:00