From cc92831d06cd1d1ae78efe928b0bfe549d796153 Mon Sep 17 00:00:00 2001 From: WiseDev <83840010+wisedevik@users.noreply.github.com> Date: Sun, 23 Aug 2026 14:17:50 +0300 Subject: [PATCH] never reuse a global id the client matches the objects in a snapshot against the ones it already has by global id, and anything it cannot find it builds from scratch. our next id was the highest one in play plus one, recomputed at every spawn - so as soon as a unit died its id came free and the next spawn took it. at five snapshots a second the client was destroying and rebuilding models faster than they could appear, which is why units fought and shot while invisible. the counter is per battle now and only ever goes up, starting past the towers. --- crates/game-service/src/battle_session.rs | 25 ++++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/game-service/src/battle_session.rs b/crates/game-service/src/battle_session.rs index 6536c11..23426b9 100644 --- a/crates/game-service/src/battle_session.rs +++ b/crates/game-service/src/battle_session.rs @@ -24,10 +24,20 @@ pub struct BattleSession { next_snapshot: i32, next_bot_play: i32, pub pushed_snapshots: u32, + next_instance: i32, pending_bot_play: Option<(LogicDataRef, LogicVector2, i32)>, } impl BattleSession { pub fn new(mode: LogicGameMode, taunts: Vec) -> Self { + let first_instance = mode + .battle + .objects + .objects + .iter() + .filter_map(|entry| entry.global_id.0.map(|id| id.instance_id)) + .max() + .map(|last| last + 1) + .unwrap_or(0); let mut random = LogicRandom::new(mode.random_seed); let next_bot_emote = Self::roll_emote_tick(&mut random, 0); Self { @@ -42,6 +52,7 @@ impl BattleSession { next_snapshot: SNAPSHOT_INTERVAL_TICKS, next_bot_play: crate::bot::BOT_OPENING_DELAY_SECONDS * BATTLE_TICKS_PER_SECOND, pushed_snapshots: 0, + next_instance: first_instance, pending_bot_play: None, } } @@ -258,16 +269,10 @@ impl BattleSession { .position(|id| *id == account) .map(|index| index as i32) } - pub fn next_instance(&self) -> i32 { - self.mode - .battle - .objects - .objects - .iter() - .filter_map(|entry| entry.global_id.0.map(|id| id.instance_id)) - .max() - .map(|last| last + 1) - .unwrap_or(0) + pub fn next_instance(&mut self) -> i32 { + let instance = self.next_instance; + self.next_instance += 1; + instance } pub fn deck_card(&self, owner: i32, slot: i32) -> Option { let deck = self.mode.battle.decks.get(owner.max(0) as usize)?.as_ref()?;