nimble_sample_game/
lib.rsuse app_version::{Version, VersionProvider};
use flood_rs::prelude::{InOctetStream, OutOctetStream};
use flood_rs::{BufferDeserializer, Deserialize, ReadOctetStream, Serialize, WriteOctetStream};
use log::info;
use nimble_assent::AssentCallback;
use nimble_rectify::RectifyCallback;
pub use nimble_sample_step::SampleStep;
use nimble_seer::SeerCallback;
use nimble_step::Step;
use nimble_step_map::StepMap;
use std::io;
#[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct SampleGameState {
pub x: i32,
pub y: i32,
}
impl SampleGameState {
pub fn update(&mut self, step: &StepMap<Step<SampleStep>>) {
for (participant_id, step) in step {
match &step {
Step::Custom(custom) => match custom {
SampleStep::MoveLeft(amount) => self.x -= *amount as i32,
SampleStep::MoveRight(amount) => self.x += *amount as i32,
SampleStep::Jump => self.y += 1,
SampleStep::Nothing => {}
},
Step::Forced => self.y += 1,
Step::WaitingForReconnect => info!("waiting for reconnect"),
Step::Joined(data) => info!(
"participant {} joined at time {}",
participant_id, data.tick_id
),
Step::Left => info!("participant {} left", participant_id),
}
}
}
pub fn to_octets(&self) -> io::Result<Vec<u8>> {
let mut out = OutOctetStream::new();
out.write_i32(self.x)?;
out.write_i32(self.y)?;
Ok(out.octets())
}
#[allow(unused)]
pub fn from_octets(payload: &[u8]) -> io::Result<(Self, usize)> {
let mut in_stream = InOctetStream::new(payload);
Ok((
Self {
x: in_stream.read_i32()?,
y: in_stream.read_i32()?,
},
in_stream.cursor.position() as usize,
))
}
}
impl BufferDeserializer for SampleGameState {
fn deserialize(buf: &[u8]) -> io::Result<(Self, usize)> {
let mut in_stream = InOctetStream::new(buf);
let s = <Self as Deserialize>::deserialize(&mut in_stream)?;
Ok((s, in_stream.cursor.position() as usize))
}
}
impl Serialize for SampleGameState {
fn serialize(&self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
stream.write_i32(self.x)?;
stream.write_i32(self.y)
}
}
impl Deserialize for SampleGameState {
fn deserialize(stream: &mut impl ReadOctetStream) -> io::Result<Self> {
Ok(Self {
x: stream.read_i32()?,
y: stream.read_i32()?,
})
}
}
#[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct SampleGame {
pub predicted: SampleGameState,
pub authoritative: SampleGameState,
}
impl SampleGame {
pub fn authoritative_octets(&self) -> io::Result<Vec<u8>> {
self.authoritative.to_octets()
}
}
impl BufferDeserializer for SampleGame {
fn deserialize(octets: &[u8]) -> io::Result<(Self, usize)> {
let (sample_state, size) = SampleGameState::from_octets(octets)?;
Ok((
Self {
predicted: sample_state.clone(),
authoritative: sample_state,
},
size,
))
}
}
impl VersionProvider for SampleGame {
fn version() -> Version {
Version::new(0, 0, 5)
}
}
impl Serialize for SampleGame {
fn serialize(&self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
self.authoritative.serialize(stream)
}
}
impl Deserialize for SampleGame {
fn deserialize(stream: &mut impl ReadOctetStream) -> io::Result<Self> {
let state = <SampleGameState as Deserialize>::deserialize(stream)?;
Ok(Self {
authoritative: state.clone(),
predicted: state,
})
}
}
impl SeerCallback<StepMap<Step<SampleStep>>> for SampleGame {
fn on_pre_ticks(&mut self) {}
fn on_tick(&mut self, step: &StepMap<Step<SampleStep>>) {
self.predicted.update(step);
}
fn on_post_ticks(&mut self) {}
}
impl AssentCallback<StepMap<Step<SampleStep>>> for SampleGame {
fn on_pre_ticks(&mut self) {}
fn on_tick(&mut self, step: &StepMap<Step<SampleStep>>) {
self.authoritative.update(step);
}
fn on_post_ticks(&mut self) {}
}
impl RectifyCallback for SampleGame {
fn on_copy_from_authoritative(&mut self) {
self.predicted = self.authoritative.clone();
}
}