write the compression flag byte in SectorStateMessage

SectorManager::receiveSectorState reads one byte off the front of the
message body and branches on it: 1 goes to receiveCompressedSectorState,
anything else falls through to the plain decode. we never wrote that
byte, so the client ate the first byte of the snapshot as the flag and
then read every field one byte early - server tick 0, discard 11, and
the section sentinel landed on the LogicTime tick instead of 11.

drop the two bisect switches, they served their purpose: both settings
aborted identically, which is what ruled out the object payload.
This commit is contained in:
WiseDev 2026-08-23 11:09:27 +03:00
parent e984aa7d15
commit bc04651a73
2 changed files with 8 additions and 19 deletions

View file

@ -24,14 +24,6 @@ pub struct TowerSpec {
pub struct BattleBuilder {
root: PathBuf,
buff_type_count: usize,
summoner_bodies: bool,
princess_towers: bool,
}
fn env_flag(key: &str) -> bool {
!matches!(
std::env::var(key).unwrap_or_default().as_str(),
"0" | "false" | "off"
)
}
fn tile_to_units(tile: i32) -> i32 {
tile.saturating_mul(SUBTILE_UNITS)
@ -55,11 +47,6 @@ impl BattleBuilder {
.unwrap_or(0);
tracing::info!(
buff_type_count,
summoner_bodies = env_flag("SCROLL_BATTLE_SUMMONER"),
princess_towers = env_flag("SCROLL_BATTLE_PRINCESS"),
damage_types = LogicDataTables::instance().table(table::DAMAGE_TYPES).map(|t| t.count()).unwrap_or(0),
character_buffs = LogicDataTables::instance().table(table::CHARACTER_BUFFS).map(|t| t.count()).unwrap_or(0),
king = %character_data(CHARACTER_KING_TOWER),
king_id = ?character_data(CHARACTER_KING_TOWER).global_id(),
princess_id = ?character_data(CHARACTER_PRINCESS_TOWER).global_id(),
"battle builder ready"
@ -67,8 +54,6 @@ impl BattleBuilder {
Self {
root: root.as_ref().to_path_buf(),
buff_type_count,
summoner_bodies: env_flag("SCROLL_BATTLE_SUMMONER"),
princess_towers: env_flag("SCROLL_BATTLE_PRINCESS"),
}
}
pub fn buff_type_count(&self) -> usize {
@ -172,13 +157,13 @@ impl BattleBuilder {
owner: owner as i32,
level_index: 0,
is_leader: true,
summoner: self.summoner_bodies,
summoner: true,
});
leaders[owner] = entry.global_id;
objects.push(entry);
instance += 1;
}
if !princess.is_none() && self.princess_towers {
if !princess.is_none() {
for tile in tilemap.princess_towers() {
let owner = usize::from(tile_to_units(tile.1) >= middle);
let entry = self.tower(TowerSpec {

View file

@ -1,12 +1,16 @@
use titan::Message;
pub const SECTOR_STATE_UNCOMPRESSED: u8 = 0;
#[derive(Debug, Default, Clone, PartialEq, Eq, Message)]
#[message(id = 21903, direction = "server", name = "SectorStateMessage")]
#[codec(raw)]
pub struct SectorStateMessage {
pub snapshot: Vec<u8>,
pub body: Vec<u8>,
}
impl SectorStateMessage {
pub fn new(snapshot: Vec<u8>) -> Self {
Self { snapshot }
let mut body = Vec::with_capacity(snapshot.len() + 1);
body.push(SECTOR_STATE_UNCOMPRESSED);
body.extend_from_slice(&snapshot);
Self { body }
}
}