diff --git a/lib/common/src/physics.rs b/lib/common/src/physics.rs index dc6be13..74a8845 100644 --- a/lib/common/src/physics.rs +++ b/lib/common/src/physics.rs @@ -1,11 +1,25 @@ +use crate::mouse::MouseState; + #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)] pub enum TimeInner{} pub type Time=crate::integer::Time; #[derive(Clone,Debug)] pub enum Instruction{ - ReplaceMouse(crate::mouse::MouseState,crate::mouse::MouseState), - SetNextMouse(crate::mouse::MouseState), + Mouse(MouseInstruction), + Other(OtherInstruction), +} +#[derive(Clone,Debug)] +pub enum MouseInstruction{ + /// Replace the entire interpolation state to avoid dividing by zero when replacing twice + ReplaceMouse{ + s0:MouseState, + s1:MouseState, + }, + SetNextMouse(MouseState), +} +#[derive(Clone,Debug)] +pub enum OtherInstruction{ SetMoveRight(bool), SetMoveUp(bool), SetMoveBack(bool), diff --git a/lib/common/src/session.rs b/lib/common/src/session.rs index 7f2c01d..97322b1 100644 --- a/lib/common/src/session.rs +++ b/lib/common/src/session.rs @@ -1,3 +1,9 @@ #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)] pub enum TimeInner{} pub type Time=crate::integer::Time; + +#[derive(Clone,Debug)] +pub enum UnbufferedInputInstruction{ + MoveMouse(glam::IVec2), + Other(crate::physics::OtherInstruction), +} diff --git a/strafe-client/src/mouse_interpolator.rs b/strafe-client/src/mouse_interpolator.rs index ad107a3..d5e36de 100644 --- a/strafe-client/src/mouse_interpolator.rs +++ b/strafe-client/src/mouse_interpolator.rs @@ -1,6 +1,12 @@ use strafesnet_common::mouse::MouseState; -use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,Time as PhysicsTime,TimeInner as PhysicsTimeInner}; -use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner}; +use strafesnet_common::physics::{ + Instruction as PhysicsInputInstruction, + Time as PhysicsTime, + TimeInner as PhysicsTimeInner, + MouseInstruction, + OtherInstruction, +}; +use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner,UnbufferedInputInstruction}; use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,TimedInstruction}; type TimedPhysicsInstruction=TimedInstruction; @@ -9,23 +15,6 @@ type DoubleTimedUnbufferedInstruction=TimedInstruction), } impl BufferState{ - fn next_state(&self,ins:DoubleTimedUnbufferedInstruction,physics_timeline:&mut std::collections::VecDeque)->Self{ + fn next_state(&self,ins:DoubleTimedUnbufferedInstruction,physics_timeline:&mut std::collections::VecDeque)->(Self,Option>){ match self{ BufferState::Unbuffered=>{ if let UnbufferedInputInstruction::MoveMouse(pos)=ins.instruction.instruction{ - return BufferState::Initializing(ins.time,MouseState{pos,time:ins.instruction.time}); + return (BufferState::Initializing(ins.time,MouseState{pos,time:ins.instruction.time}),None); } }, BufferState::Initializing(time,mouse_state)=>{ @@ -54,17 +43,24 @@ impl BufferState{ // but the timer is not accessible from this scope // and it's just here to say that the mouse isn't moving anyways. time:ins.instruction.time, - instruction:PhysicsInputInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}), + instruction:PhysicsInputInstruction::Mouse( + MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}) + ), }); - return BufferState::Unbuffered; + return (BufferState::Unbuffered,None); } if let UnbufferedInputInstruction::MoveMouse(pos)=ins.instruction.instruction{ let next_mouse_state=MouseState{pos,time:ins.instruction.time}; physics_timeline.push_front(TimedInstruction{ time:mouse_state.time, - instruction:PhysicsInputInstruction::ReplaceMouse(mouse_state.clone(),next_mouse_state.clone()), + instruction:PhysicsInputInstruction::Mouse( + MouseInstruction::ReplaceMouse{ + s0:mouse_state.clone(), + s1:next_mouse_state.clone(), + } + ), }); - return BufferState::Buffered(ins.time,next_mouse_state); + return (BufferState::Buffered(ins.time,next_mouse_state),None); } }, BufferState::Buffered(time,mouse_state)=>{ @@ -76,21 +72,32 @@ impl BufferState{ // but the timer is not accessible from this scope // and it's just here to say that the mouse isn't moving anyways. time:ins.instruction.time, - instruction:PhysicsInputInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}), + instruction:PhysicsInputInstruction::Mouse( + MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}) + ), }); - return BufferState::Unbuffered; + return (BufferState::Unbuffered,None); } if let UnbufferedInputInstruction::MoveMouse(pos)=ins.instruction.instruction{ let next_mouse_state=MouseState{pos,time:ins.instruction.time}; physics_timeline.push_front(TimedInstruction{ time:ins.instruction.time, - instruction:PhysicsInputInstruction::SetNextMouse(next_mouse_state.clone()), + instruction:PhysicsInputInstruction::Mouse( + MouseInstruction::SetNextMouse(next_mouse_state.clone()) + ), }); - return BufferState::Buffered(ins.time,next_mouse_state); + return (BufferState::Buffered(ins.time,next_mouse_state),None); } }, } - self.clone() + let instruction_out=match ins.instruction.instruction{ + UnbufferedInputInstruction::MoveMouse(_)=>None, + UnbufferedInputInstruction::Other(other_instruction)=>Some(TimedInstruction{ + time:ins.instruction.time, + instruction:other_instruction, + }), + }; + (self.clone(),instruction_out) } } pub struct MouseInterpolator{ @@ -131,39 +138,55 @@ impl MouseInterpolator{ // case 3: stop // a mouse event is buffered, but no mouse events have transpired within 10ms // TODO: remove clone - self.buffer_state=self.buffer_state.next_state(ins,&mut self.physics_timeline); + let ins_inner; + (self.buffer_state,ins_inner)=self.buffer_state.next_state(ins,&mut self.physics_timeline); + if let Some(ins)=ins_inner{ + self.physics_timeline.push_back(TimedInstruction{ + time:ins.time, + instruction:PhysicsInputInstruction::Other(ins.instruction), + }); + } } fn is_first_ready(&self)->bool{ // if the last instruction is a ReplaceMouse instruction matches!(self.physics_timeline.back(),Some(TimedInstruction{ - instruction:PhysicsInputInstruction::ReplaceMouse(_,_), + instruction:PhysicsInputInstruction::Mouse(MouseInstruction::ReplaceMouse{..}), .. })) // or if the last instruction is a SetNextMouse instruction // and there is 2 or more instructions ||1Option>{ - let timeout=self.last_mouse_state.time+MOUSE_TIMEOUT; - if timeoutself.physics_timeline.front().map(|_|TimedInstruction{ time:time_limit, instruction:StepInstruction::Other, - }) - }else{ - None + }), + BufferState::Initializing(time,_mouse_state) + |BufferState::Buffered(time,_mouse_state)=>{ + let timeout=*time+MOUSE_TIMEOUT; + if timeoutOption>{ @@ -177,6 +200,7 @@ impl MouseInterpolator{ // mouse instruction as an interpolation target }, StepInstruction::ReplaceMouse=>{ + // convert to BufferState::Unbuffered // use the first instruction which should be a mouse instruction // to push a ReplaceMouse instruction }, diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs index a015e81..9743415 100644 --- a/strafe-client/src/session.rs +++ b/strafe-client/src/session.rs @@ -3,9 +3,9 @@ use strafesnet_common::instruction::{InstructionConsumer, InstructionEmitter, In // Ideally it is a deterministic state which is atomically updated by instructions, same as the simulation state. use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,TimeInner as PhysicsTimeInner,Time as PhysicsTime}; use strafesnet_common::timer::{Scaled,Timer}; -use strafesnet_common::session::{TimeInner as SessionTimeInner,Time as SessionTime}; +use strafesnet_common::session::{TimeInner as SessionTimeInner,Time as SessionTime,UnbufferedInputInstruction}; -use crate::mouse_interpolator::{MouseInterpolator,UnbufferedInputInstruction,StepInstruction}; +use crate::mouse_interpolator::{MouseInterpolator,StepInstruction}; pub enum ExternalInstruction{ ToBuffer(UnbufferedInputInstruction),