use std::collections::VecDeque;
use std::fmt::Debug;
use bevy::prelude::Resource;
use serde::{Deserialize, Serialize};
use crate::inputs::UserInput;
use lightyear_macros::MessageInternal;
use tracing::info;
use crate::protocol::BitSerializable;
use crate::shared::tick_manager::Tick;
#[derive(Resource, Debug)]
pub struct InputBuffer<T: UserInput> {
pub buffer: VecDeque<Option<T>>,
pub start_tick: Tick,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
enum InputData<T: UserInput> {
Absent,
SameAsPrecedent,
Input(T),
}
#[derive(MessageInternal, Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct InputMessage<T: UserInput> {
end_tick: Tick,
inputs: Vec<InputData<T>>,
}
impl<T: UserInput> InputMessage<T> {
pub fn is_empty(&self) -> bool {
if self.inputs.len() == 0 {
return true;
}
let mut iter = self.inputs.iter();
if iter.next().unwrap() == &InputData::Absent {
return iter.all(|x| x == &InputData::SameAsPrecedent);
}
false
}
}
impl<T: UserInput> Default for InputBuffer<T> {
fn default() -> Self {
Self {
buffer: VecDeque::new(),
start_tick: Tick(0),
}
}
}
impl<T: UserInput> InputBuffer<T> {
pub(crate) fn pop(&mut self, tick: Tick) -> Option<T> {
if tick < self.start_tick {
return None;
}
if tick > self.start_tick + (self.buffer.len() as i16 - 1) {
self.buffer = VecDeque::new();
self.start_tick = tick + 1;
return None;
}
for _ in 0..(tick - self.start_tick) {
self.buffer.pop_front();
}
self.start_tick = tick + 1;
self.buffer.pop_front().unwrap()
}
pub(crate) fn get(&self, tick: Tick) -> Option<&T> {
if tick < self.start_tick || tick > self.start_tick + (self.buffer.len() as i16 - 1) {
return None;
}
self.buffer
.get((tick.0 - self.start_tick.0) as usize)
.unwrap()
.as_ref()
}
pub(crate) fn set(&mut self, tick: Tick, value: Option<T>) {
if tick < self.start_tick {
return;
}
let end_tick = self.start_tick + (self.buffer.len() as i16 - 1);
if tick > end_tick {
for _ in 0..(tick - end_tick - 1) {
self.buffer.push_back(None);
}
self.buffer.push_back(value);
return;
}
*self
.buffer
.get_mut((tick - self.start_tick) as usize)
.unwrap() = value;
}
pub(crate) fn update_from_message(&mut self, message: InputMessage<T>) {
let message_start_tick = Tick(message.end_tick.0) - message.inputs.len() as u16 + 1;
let mut prev_value = None;
for (delta, input) in message.inputs.into_iter().enumerate() {
let tick = message_start_tick + Tick(delta as u16);
match input {
InputData::Absent => {
prev_value = None;
self.set(tick, None);
}
InputData::SameAsPrecedent => {
self.set(tick, prev_value.clone());
}
InputData::Input(input) => {
prev_value = Some(input);
if self.get(tick) == prev_value.as_ref() {
continue;
} else {
self.set(tick, prev_value.clone());
}
}
}
}
}
pub(crate) fn create_message(&self, end_tick: Tick, num_ticks: u16) -> InputMessage<T> {
let mut inputs = Vec::new();
let start_tick = Tick(end_tick.0) - num_ticks + 1;
inputs.push(
self.get(start_tick)
.map_or(InputData::Absent, |input| InputData::Input(input.clone())),
);
let mut prev_value_idx = 0;
for delta in 1..num_ticks {
let tick = start_tick + Tick(delta);
let value = self
.get(tick)
.map_or(InputData::Absent, |input| InputData::Input(input.clone()));
if inputs.get(prev_value_idx).unwrap() == &value {
inputs.push(InputData::SameAsPrecedent);
} else {
prev_value_idx = inputs.len();
inputs.push(value);
}
}
InputMessage { inputs, end_tick }
}
}
#[cfg(test)]
mod tests {
use super::*;
impl UserInput for usize {}
#[test]
fn test_get_set_pop() {
let mut input_buffer = InputBuffer::default();
input_buffer.set(Tick(4), Some(0));
input_buffer.set(Tick(6), Some(1));
input_buffer.set(Tick(7), Some(1));
assert_eq!(input_buffer.get(Tick(4)), Some(&0));
assert_eq!(input_buffer.get(Tick(5)), None);
assert_eq!(input_buffer.get(Tick(6)), Some(&1));
assert_eq!(input_buffer.get(Tick(8)), None);
assert_eq!(input_buffer.pop(Tick(5)), None);
assert_eq!(input_buffer.start_tick, Tick(6));
assert_eq!(input_buffer.pop(Tick(7)), Some(1));
assert_eq!(input_buffer.start_tick, Tick(8));
assert_eq!(input_buffer.buffer.len(), 0);
}
#[test]
fn test_create_message() {
let mut input_buffer = InputBuffer::default();
input_buffer.set(Tick(4), Some(0));
input_buffer.set(Tick(6), Some(1));
input_buffer.set(Tick(7), Some(1));
let message = input_buffer.create_message(Tick(10), 8);
assert_eq!(
message,
InputMessage {
end_tick: Tick(10),
inputs: vec![
InputData::Absent,
InputData::Input(0),
InputData::Absent,
InputData::Input(1),
InputData::SameAsPrecedent,
InputData::Absent,
InputData::SameAsPrecedent,
InputData::SameAsPrecedent,
],
}
);
}
#[test]
fn test_update_from_message() {
let mut input_buffer = InputBuffer::default();
let message = InputMessage {
end_tick: Tick(20),
inputs: vec![
InputData::Absent,
InputData::Input(0),
InputData::Absent,
InputData::Input(1),
InputData::SameAsPrecedent,
InputData::Absent,
InputData::SameAsPrecedent,
InputData::SameAsPrecedent,
],
};
input_buffer.update_from_message(message);
assert_eq!(input_buffer.get(Tick(20)), None);
assert_eq!(input_buffer.get(Tick(19)), None);
assert_eq!(input_buffer.get(Tick(18)), None);
assert_eq!(input_buffer.get(Tick(17)), Some(&1));
assert_eq!(input_buffer.get(Tick(16)), Some(&1));
assert_eq!(input_buffer.get(Tick(15)), None);
assert_eq!(input_buffer.get(Tick(14)), Some(&0));
assert_eq!(input_buffer.get(Tick(13)), None);
}
}