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.
field order taken straight off LogicBattle::encode. the object manager is
columnar, not object major: 6 counters, a count, then all data refs, then all
global ids, then all objects, then four component passes. global ids must be
ascending, the client binary searches them.
LogicRandom moved out of the shop into its own module. its abs was
checked_abs().unwrap_or(0), the binary uses NEGS so i32::MIN stays i32::MIN.
one seed in four billion, but it would have desynced the card shop.
per object subclass encodes and the component payloads are still missing, so no
snapshot can be sent yet.
14303 AskForJoinableAlliancesList and 14107 CancelMatchmake are both genuinely
empty payloads. 516 UpdateLastShownLevelUp is header only, 537 StartMatchmake
carries a vint and a bool. none of them move the home checksum.
that clears the unknown type warnings out of the log.
a panic in a session task now kills that connection, tokio catches it and the
accept loop carries on. with abort it took the whole server down.
the data table RwLock is std so it poisons on panic, and every lookup went
through expect(). one panic would have bricked every later table read, which is
worse than the abort was. it reads the inner value now, the table is read only
once installed.
RandomSpells / DifferentSpells / RareChance / EpicChance / MinGold / MaxGold all
come off the chest row now, gold is scaled by the player's arena. magic chest is
30 cards over 8 cards with 1 epic and 6 rares, like the client says it is.
arena chest rows inherit everything through BaseChest, so Free_Arena1 reads Free.
500 LogicSwapSpellsCommand does the real work, 520 and 521 are no-ops in this
build so they just decode. 535 puts its data reference BEFORE the base header,
unlike every other command.
collection only shrinks when a card moves into an empty deck slot, that is the
one case where the home checksum moves.
rounding is banded and the 5s band biases +3, so 22 goes to 25 not 20. numbers match the csv for arena 1 and 2.
free chest end timestamp needs migration 0002.
if the client presents an id we don't know, create it under that id and bump the sequence past it.
also chest offers match through BaseChest, so one silver row covers every arena.
json stores are gone, they nulled out every data ref on load and wrote the null straight back on save.
shop json and the purchase commands ended up in here too.