bevy_ggrs icon indicating copy to clipboard operation
bevy_ggrs copied to clipboard

Assertion panic with certain sizes of input struct

Open IRSMsoso opened this issue 8 months ago • 4 comments

Certain input structs hit an assertion

assertion 'left == right' failed
    left: 17
  right: 24
Encountered a panic in system 'bevy_ggrs::schedule_systems::run_ggrs_schedules<state_machine_game::rollback::RollbackConfig>'!

ggrs-0.11.0\src\network\compression.rs:23:9

It happens on the very first frame that the clients are connected and the assertion is in the delta_encode function

pub(crate) fn delta_encode<'a>(
    ref_bytes: &[u8],
    pending_input: impl Iterator<Item = &'a Vec<u8>>,
) -> Vec<u8> {
    let (lower, upper) = pending_input.size_hint();
    let capacity = upper.unwrap_or(lower) * ref_bytes.len();
    let mut bytes = Vec::with_capacity(capacity);

    for input in pending_input {
        let input_bytes = input;
        assert_eq!(input_bytes.len(), ref_bytes.len());

        for (b1, b2) in ref_bytes.iter().zip(input_bytes.iter()) {
            bytes.push(b1 ^ b2);
        }
    }
    bytes
}

My Config looks like this

#[derive(Debug)]
pub struct RollbackConfig<Input = PlayerInputType, Address = SteamId, State = u8> {
    _phantom: PhantomData<(Input, Address, State)>,
}

impl<Input, Address, State> Config for RollbackConfig<Input, Address, State>
where
    Self: 'static,
    Input: Send + Sync + PartialEq + Serialize + for<'a> Deserialize<'a> + Default + Copy,
    Address: Send + Sync + Debug + Hash + Eq + Clone,
    State: Send + Sync + Clone,
{
    type Input = Input;
    type State = State;
    type Address = Address;
}

and my Input looks like this

const INPUT_CONFIRM: u8 = 1 << 0;

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct PlayerInputType {
    pub(crate) input_vector: FixVec,
    pub(crate) buttons: u8,
}

impl Default for PlayerInputType {
    fn default() -> Self {
        Self {
            input_vector: FixVec::ZERO,
            buttons: 0,
        }
    }
}

where FixVec is a 2D fix float vector from the crate i_float. It's total size is 16 bytes alone (one i64 for x and one for y). It works fine with no assertion panics if I have only the FixVec in PlayerInputType, but as soon as I added a bool to the struct the assertion happens on the first rollback frame. u8 has the same problem. u64 doesn't have the issue and works fine, presumably because it brings the total bytes up to 24, which matches the right hand of the assertion.

Not sure why this is happening. It may be that I don't understand the library. I left the State type in my config as u8 because I couldn't figure out what it does or if it's even relevant for the bevy implementation of ggrs.

IRSMsoso avatar Apr 13 '25 14:04 IRSMsoso

Are you using a published version of bevy_ggrs or the main branch?

gschup avatar Apr 18 '25 12:04 gschup

Published version: 0.17.0

IRSMsoso avatar Apr 18 '25 19:04 IRSMsoso

The assertion you are hitting means that the inputs you are creating are differing in length. More precisely, the currently encoded input is a different length than the reference input (usually the last input we know the other parties have received).

My first guess is that this is an issue stemming interactions between #[repr(C)] , the padding it might introduce and the vector you are using.

gschup avatar May 05 '25 07:05 gschup

Having the same issue, this is especially problematic where you might want to not send certain inputs every frame to save bandwidth (for my use case aim direction when shooting).

GaspardCulis avatar Jun 05 '25 09:06 GaspardCulis