scroll.server/crates/logic/src/battle/logic_game_mode.rs
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

58 lines
2 KiB
Rust

use titan::{ByteStreamWriter, Payload, Result};
use crate::battle::logic_battle::LogicBattle;
use crate::battle::logic_time::LogicTime;
use crate::battle::logic_tutorial_manager::LogicTutorialManager;
use crate::logic_random::LogicRandom;
use crate::model::LogicClientAvatar;
pub const SECTION_BATTLE: i32 = 11;
pub const SECTION_TUTORIAL: i32 = 12;
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct LogicGameMode {
pub time: LogicTime,
pub random: LogicRandom,
pub random_seed: i32,
pub battle: LogicBattle,
pub avatars: Vec<LogicClientAvatar>,
pub tutorial_manager: LogicTutorialManager,
}
impl LogicGameMode {
pub fn snapshot(&self) -> Result<Vec<u8>> {
let mut writer = ByteStreamWriter::new();
self.encode(&mut writer)?;
Ok(writer.into_inner())
}
}
impl LogicGameMode {
pub fn write(&self, writer: &mut ByteStreamWriter, with_commands: bool) -> Result<i32> {
writer.write_vint(self.time.tick);
writer.write_checksum_checkpoint();
writer.write_vint(SECTION_BATTLE);
self.time.encode(writer)?;
self.random.encode(writer)?;
writer.write_vint(self.random_seed);
self.battle.encode(writer)?;
for avatar in &self.avatars {
avatar.encode(writer)?;
}
writer.write_vint(SECTION_TUTORIAL);
self.tutorial_manager.encode(writer)?;
let checksum = writer.write_checksum_checkpoint();
if with_commands {
writer.write_vint(0);
}
Ok(checksum)
}
pub fn calculate_checksum(&self) -> Result<i32> {
let mut writer = ByteStreamWriter::new();
self.write(&mut writer, false)
}
}
impl Payload for LogicGameMode {
fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> {
self.write(writer, true)?;
Ok(())
}
fn decode(_reader: &mut titan::ByteStreamReader<'_>) -> Result<Self> {
Err(titan::Error::Unsupported("LogicGameMode is encode only"))
}
}