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.
This commit is contained in:
parent
d1cc829623
commit
438e2c6491
4 changed files with 31 additions and 5 deletions
|
|
@ -209,6 +209,9 @@ impl BattleSession {
|
||||||
pub fn stars(&self) -> (i32, i32) {
|
pub fn stars(&self) -> (i32, i32) {
|
||||||
(self.mode.battle.stars(0), self.mode.battle.stars(1))
|
(self.mode.battle.stars(0), self.mode.battle.stars(1))
|
||||||
}
|
}
|
||||||
|
pub fn checksum(&self) -> Option<i32> {
|
||||||
|
self.mode.calculate_checksum().ok()
|
||||||
|
}
|
||||||
pub fn towers_standing(&self) -> (usize, usize) {
|
pub fn towers_standing(&self) -> (usize, usize) {
|
||||||
(
|
(
|
||||||
self.mode.battle.leader_towers[0].len(),
|
self.mode.battle.leader_towers[0].len(),
|
||||||
|
|
@ -319,6 +322,7 @@ impl BattleRegistry {
|
||||||
stars: session.stars(),
|
stars: session.stars(),
|
||||||
objects: session.object_count(),
|
objects: session.object_count(),
|
||||||
towers: session.towers_standing(),
|
towers: session.towers_standing(),
|
||||||
|
checksum: session.checksum(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub async fn play<F>(
|
pub async fn play<F>(
|
||||||
|
|
@ -356,4 +360,5 @@ pub struct BattleProgress {
|
||||||
pub stars: (i32, i32),
|
pub stars: (i32, i32),
|
||||||
pub objects: usize,
|
pub objects: usize,
|
||||||
pub towers: (usize, usize),
|
pub towers: (usize, usize),
|
||||||
|
pub checksum: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -366,9 +366,14 @@ impl GameApi for GameService {
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
let progress = self.running_battles.advance(account, turn.tick).await;
|
let progress = self.running_battles.advance(account, turn.tick).await;
|
||||||
|
let server_checksum = progress.and_then(|state| state.checksum);
|
||||||
|
let agrees = server_checksum == Some(turn.checksum);
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
%account,
|
%account,
|
||||||
tick = turn.tick,
|
tick = turn.tick,
|
||||||
|
checksum = turn.checksum,
|
||||||
|
server_checksum,
|
||||||
|
agrees,
|
||||||
seconds = progress.map(|state| state.seconds),
|
seconds = progress.map(|state| state.seconds),
|
||||||
finished = progress.map(|state| state.finished),
|
finished = progress.map(|state| state.finished),
|
||||||
stars = ?progress.map(|state| state.stars),
|
stars = ?progress.map(|state| state.stars),
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,10 @@ impl LogicGameMode {
|
||||||
Ok(writer.into_inner())
|
Ok(writer.into_inner())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Payload for LogicGameMode {
|
impl LogicGameMode {
|
||||||
fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> {
|
pub fn write(&self, writer: &mut ByteStreamWriter, with_commands: bool) -> Result<()> {
|
||||||
writer.write_vint(self.server_tick);
|
writer.write_vint(self.server_tick);
|
||||||
writer.write_vint(0);
|
writer.write_checksum_checkpoint();
|
||||||
writer.write_vint(SECTION_BATTLE);
|
writer.write_vint(SECTION_BATTLE);
|
||||||
self.time.encode(writer)?;
|
self.time.encode(writer)?;
|
||||||
self.random.encode(writer)?;
|
self.random.encode(writer)?;
|
||||||
|
|
@ -37,10 +37,22 @@ impl Payload for LogicGameMode {
|
||||||
}
|
}
|
||||||
writer.write_vint(SECTION_TUTORIAL);
|
writer.write_vint(SECTION_TUTORIAL);
|
||||||
self.tutorial_manager.encode(writer)?;
|
self.tutorial_manager.encode(writer)?;
|
||||||
|
writer.write_checksum_checkpoint();
|
||||||
|
if with_commands {
|
||||||
writer.write_vint(0);
|
writer.write_vint(0);
|
||||||
writer.write_vint(0);
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
pub fn calculate_checksum(&self) -> Result<i32> {
|
||||||
|
let mut writer = ByteStreamWriter::new();
|
||||||
|
self.write(&mut writer, false)?;
|
||||||
|
Ok(writer.checksum() as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Payload for LogicGameMode {
|
||||||
|
fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> {
|
||||||
|
self.write(writer, true)
|
||||||
|
}
|
||||||
fn decode(_reader: &mut titan::ByteStreamReader<'_>) -> Result<Self> {
|
fn decode(_reader: &mut titan::ByteStreamReader<'_>) -> Result<Self> {
|
||||||
Err(titan::Error::Unsupported("LogicGameMode is encode only"))
|
Err(titan::Error::Unsupported("LogicGameMode is encode only"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ impl ByteStreamWriter {
|
||||||
pub fn checksum(&self) -> u32 {
|
pub fn checksum(&self) -> u32 {
|
||||||
self.checksum.value()
|
self.checksum.value()
|
||||||
}
|
}
|
||||||
|
pub fn write_checksum_checkpoint(&mut self) {
|
||||||
|
let running = self.checksum.value() as i32;
|
||||||
|
self.write_vint(running);
|
||||||
|
}
|
||||||
pub fn write_byte(&mut self, value: u8) {
|
pub fn write_byte(&mut self, value: u8) {
|
||||||
self.checksum.write_byte(value as i8);
|
self.checksum.write_byte(value as i8);
|
||||||
self.bit_index = 0;
|
self.bit_index = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue