diff --git a/lib/common/src/physics.rs b/lib/common/src/physics.rs index f2a07f1..f8173fa 100644 --- a/lib/common/src/physics.rs +++ b/lib/common/src/physics.rs @@ -7,17 +7,13 @@ pub type Time=crate::integer::Time; #[derive(Clone,Debug)] pub enum Instruction{ Mouse(MouseInstruction), - NonMouse(NonMouseInstruction), -} -impl Instruction{ - pub const IDLE:Self=Self::NonMouse(NonMouseInstruction::Misc(MiscInstruction::Idle)); -} -#[derive(Clone,Debug)] -pub enum NonMouseInstruction{ SetControl(SetControlInstruction), Mode(ModeInstruction), Misc(MiscInstruction), } +impl Instruction{ + pub const IDLE:Self=Self::Misc(MiscInstruction::Idle); +} #[derive(Clone,Debug)] pub enum MouseInstruction{ /// Replace the entire interpolation state to avoid dividing by zero when replacing twice diff --git a/strafe-client/src/mouse_interpolator.rs b/strafe-client/src/mouse_interpolator.rs index 5065d85..2898a56 100644 --- a/strafe-client/src/mouse_interpolator.rs +++ b/strafe-client/src/mouse_interpolator.rs @@ -1,28 +1,70 @@ use strafesnet_common::mouse::MouseState; use strafesnet_common::physics::{ - Instruction as PhysicsInputInstruction, + MouseInstruction,SetControlInstruction,ModeInstruction,MiscInstruction, + Instruction as PhysicsInstruction, TimeInner as PhysicsTimeInner, Time as PhysicsTime, - MouseInstruction, - NonMouseInstruction, }; use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner}; use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,TimedInstruction}; -type TimedPhysicsInstruction=TimedInstruction; -type TimedUnbufferedInstruction=TimedInstruction; -type DoubleTimedUnbufferedInstruction=TimedInstruction; +type TimedSelfInstruction=TimedInstruction; +type DoubleTimedSelfInstruction=TimedInstruction; + +type TimedPhysicsInstruction=TimedInstruction; const MOUSE_TIMEOUT:SessionTime=SessionTime::from_millis(10); /// To be fed into MouseInterpolator #[derive(Clone,Debug)] -pub enum Instruction{ +pub(crate) enum Instruction{ MoveMouse(glam::IVec2), - Other(NonMouseInstruction), + SetControl(SetControlInstruction), + Mode(ModeInstruction), + Misc(MiscInstruction), +} +#[derive(Clone,Debug)] +enum UnbufferedInstruction{ + MoveMouse(glam::IVec2), + NonMouse(NonMouseInstruction), +} +#[derive(Clone,Debug)] +enum BufferedInstruction{ + Mouse(MouseInstruction), + NonMouse(NonMouseInstruction), +} +#[derive(Clone,Debug)] +pub(crate) enum NonMouseInstruction{ + SetControl(SetControlInstruction), + Mode(ModeInstruction), + Misc(MiscInstruction), +} +impl From for UnbufferedInstruction{ + #[inline] + fn from(value:Instruction)->Self{ + match value{ + Instruction::MoveMouse(mouse_instruction)=>UnbufferedInstruction::MoveMouse(mouse_instruction), + Instruction::SetControl(set_control_instruction)=>UnbufferedInstruction::NonMouse(NonMouseInstruction::SetControl(set_control_instruction)), + Instruction::Mode(mode_instruction)=>UnbufferedInstruction::NonMouse(NonMouseInstruction::Mode(mode_instruction)), + Instruction::Misc(misc_instruction)=>UnbufferedInstruction::NonMouse(NonMouseInstruction::Misc(misc_instruction)), + } + } +} +impl From for PhysicsInstruction{ + #[inline] + fn from(value:BufferedInstruction)->Self{ + match value{ + BufferedInstruction::Mouse(mouse_instruction)=>PhysicsInstruction::Mouse(mouse_instruction), + BufferedInstruction::NonMouse(non_mouse_instruction)=>match non_mouse_instruction{ + NonMouseInstruction::SetControl(set_control_instruction)=>PhysicsInstruction::SetControl(set_control_instruction), + NonMouseInstruction::Mode(mode_instruction)=>PhysicsInstruction::Mode(mode_instruction), + NonMouseInstruction::Misc(misc_instruction)=>PhysicsInstruction::Misc(misc_instruction), + }, + } + } } -pub enum StepInstruction{ +pub(crate) enum StepInstruction{ Pop, Timeout, } @@ -42,10 +84,10 @@ pub struct MouseInterpolator{ } // Maybe MouseInterpolator manipulation is better expressed using impls // and called from Instruction trait impls in session -impl InstructionConsumer for MouseInterpolator{ +impl InstructionConsumer for MouseInterpolator{ type TimeInner=SessionTimeInner; - fn process_instruction(&mut self,ins:DoubleTimedUnbufferedInstruction){ - self.push_unbuffered_input(ins) + fn process_instruction(&mut self,ins:DoubleTimedSelfInstruction){ + self.push_unbuffered_input(ins.time,ins.instruction.time,ins.instruction.instruction.into()) } } impl InstructionEmitter for MouseInterpolator{ @@ -65,7 +107,7 @@ impl MouseInterpolator{ fn push_mouse_and_flush_buffer(&mut self,ins:TimedInstruction){ self.buffer.push_front(TimedInstruction{ time:ins.time, - instruction:PhysicsInputInstruction::Mouse(ins.instruction), + instruction:BufferedInstruction::Mouse(ins.instruction).into(), }); // flush buffer to output if self.output.len()==0{ @@ -110,7 +152,7 @@ impl MouseInterpolator{ }, } } - pub fn push_unbuffered_input(&mut self,ins:DoubleTimedUnbufferedInstruction){ + fn push_unbuffered_input(&mut self,session_time:SessionTime,physics_time:PhysicsTime,ins:UnbufferedInstruction){ // new input // if there is zero instruction buffered, it means the mouse is not moving // case 1: unbuffered @@ -126,12 +168,12 @@ impl MouseInterpolator{ // from behind a mutable reference, but a panic in the closure means that // the entire program terminates rather than completing an unwind. let (ins_mouse,ins_other)=replace_with::replace_with_or_abort_and_return(&mut self.buffer_state,|buffer_state|{ - match ins.instruction.instruction{ - Instruction::MoveMouse(pos)=>{ - let next_mouse_state=MouseState{pos,time:ins.instruction.time}; + match ins{ + UnbufferedInstruction::MoveMouse(pos)=>{ + let next_mouse_state=MouseState{pos,time:physics_time}; match buffer_state{ BufferState::Unbuffered=>{ - ((None,None),BufferState::Initializing(ins.time,next_mouse_state)) + ((None,None),BufferState::Initializing(session_time,next_mouse_state)) }, BufferState::Initializing(_time,mouse_state)=>{ let ins_mouse=TimedInstruction{ @@ -141,19 +183,19 @@ impl MouseInterpolator{ m1:next_mouse_state.clone(), }, }; - ((Some(ins_mouse),None),BufferState::Buffered(ins.time,next_mouse_state)) + ((Some(ins_mouse),None),BufferState::Buffered(session_time,next_mouse_state)) }, BufferState::Buffered(_time,mouse_state)=>{ let ins_mouse=TimedInstruction{ time:mouse_state.time, instruction:MouseInstruction::SetNextMouse(next_mouse_state.clone()), }; - ((Some(ins_mouse),None),BufferState::Buffered(ins.time,next_mouse_state)) + ((Some(ins_mouse),None),BufferState::Buffered(session_time,next_mouse_state)) }, } }, - Instruction::Other(other_instruction)=>((None,Some(TimedInstruction{ - time:ins.instruction.time, + UnbufferedInstruction::NonMouse(other_instruction)=>((None,Some(TimedInstruction{ + time:physics_time, instruction:other_instruction, })),buffer_state), } @@ -164,7 +206,7 @@ impl MouseInterpolator{ if let Some(ins)=ins_other{ let instruction=TimedInstruction{ time:ins.time, - instruction:PhysicsInputInstruction::NonMouse(ins.instruction), + instruction:BufferedInstruction::NonMouse(ins.instruction).into(), }; if matches!(self.buffer_state,BufferState::Unbuffered){ self.output.push_back(instruction); @@ -173,7 +215,7 @@ impl MouseInterpolator{ } } } - pub fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option>{ + fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option>{ match self.get_mouse_timedout_at(time_limit){ Some(timeout)=>Some(TimedInstruction{ time:timeout, @@ -186,7 +228,7 @@ impl MouseInterpolator{ }), } } - pub fn pop_buffered_instruction(&mut self,ins:TimedInstruction)->Option>{ + pub fn pop_buffered_instruction(&mut self,ins:TimedInstruction)->Option{ match ins.instruction{ StepInstruction::Pop=>(), StepInstruction::Timeout=>self.timeout_mouse(ins.time), @@ -207,13 +249,11 @@ mod test{ macro_rules! push{ ($time:expr,$ins:expr)=>{ println!("in={:?}",$ins); - interpolator.push_unbuffered_input(TimedInstruction{ - time:$time, - instruction:TimedInstruction{ - time:timer.time($time), - instruction:$ins, - } - }); + interpolator.push_unbuffered_input( + $time, + timer.time($time), + $ins, + ); while let Some(ins)=interpolator.buffered_instruction_with_timeout($time){ let ins_retimed=TimedInstruction{ time:timer.time(ins.time), @@ -227,11 +267,11 @@ mod test{ // test each buffer_state transition let mut t=SessionTime::ZERO; - push!(t,Instruction::MoveMouse(glam::ivec2(0,0))); + push!(t,UnbufferedInstruction::MoveMouse(glam::ivec2(0,0))); t+=SessionTime::from_millis(5); - push!(t,Instruction::MoveMouse(glam::ivec2(0,0))); + push!(t,UnbufferedInstruction::MoveMouse(glam::ivec2(0,0))); t+=SessionTime::from_millis(5); - push!(t,Instruction::MoveMouse(glam::ivec2(0,0))); + push!(t,UnbufferedInstruction::MoveMouse(glam::ivec2(0,0))); t+=SessionTime::from_millis(1); } } diff --git a/strafe-client/src/physics.rs b/strafe-client/src/physics.rs index 379e3f0..7cc397d 100644 --- a/strafe-client/src/physics.rs +++ b/strafe-client/src/physics.rs @@ -19,7 +19,7 @@ type MouseState=strafesnet_common::mouse::MouseState; //external influence //this is how you influence the physics from outside -use strafesnet_common::physics::{Instruction,NonMouseInstruction,MouseInstruction,ModeInstruction,MiscInstruction,SetControlInstruction}; +use strafesnet_common::physics::{Instruction,MouseInstruction,ModeInstruction,MiscInstruction,SetControlInstruction}; //internal influence //when the physics asks itself what happens next, this is how it's represented @@ -1736,13 +1736,13 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI let should_advance_body=match ins.instruction{ //the body may as well be a quantum wave function //as far as these instruction are concerned (they don't care where it is) - Instruction::NonMouse(NonMouseInstruction::Misc(MiscInstruction::SetSensitivity(..))) - |Instruction::NonMouse(NonMouseInstruction::Mode(_)) - |Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetZoom(..))) - |Instruction::NonMouse(NonMouseInstruction::Misc(MiscInstruction::Idle))=>false, + Instruction::Misc(MiscInstruction::SetSensitivity(..)) + |Instruction::Mode(_) + |Instruction::SetControl(SetControlInstruction::SetZoom(..)) + |Instruction::Misc(MiscInstruction::Idle)=>false, //these controls only update the body if you are on the ground Instruction::Mouse(_) - |Instruction::NonMouse(NonMouseInstruction::SetControl(_))=>{ + |Instruction::SetControl(_)=>{ match &state.move_state{ MoveState::Fly |MoveState::Water @@ -1752,7 +1752,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI } }, //the body must be updated unconditionally - Instruction::NonMouse(NonMouseInstruction::Misc(MiscInstruction::PracticeFly))=>true, + Instruction::Misc(MiscInstruction::PracticeFly)=>true, }; if should_advance_body{ state.body.advance_time(state.time); @@ -1768,14 +1768,14 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI state.camera.move_mouse(m0.pos-state.input_state.mouse.pos); state.input_state.replace_mouse(m0,m1); }, - Instruction::NonMouse(NonMouseInstruction::Misc(MiscInstruction::SetSensitivity(sensitivity)))=>state.camera.sensitivity=sensitivity, - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetMoveForward(s)))=>state.input_state.set_control(Controls::MoveForward,s), - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetMoveLeft(s)))=>state.input_state.set_control(Controls::MoveLeft,s), - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetMoveBack(s)))=>state.input_state.set_control(Controls::MoveBackward,s), - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetMoveRight(s)))=>state.input_state.set_control(Controls::MoveRight,s), - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetMoveUp(s)))=>state.input_state.set_control(Controls::MoveUp,s), - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetMoveDown(s)))=>state.input_state.set_control(Controls::MoveDown,s), - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetJump(s)))=>{ + Instruction::Misc(MiscInstruction::SetSensitivity(sensitivity))=>state.camera.sensitivity=sensitivity, + Instruction::SetControl(SetControlInstruction::SetMoveForward(s))=>state.input_state.set_control(Controls::MoveForward,s), + Instruction::SetControl(SetControlInstruction::SetMoveLeft(s))=>state.input_state.set_control(Controls::MoveLeft,s), + Instruction::SetControl(SetControlInstruction::SetMoveBack(s))=>state.input_state.set_control(Controls::MoveBackward,s), + Instruction::SetControl(SetControlInstruction::SetMoveRight(s))=>state.input_state.set_control(Controls::MoveRight,s), + Instruction::SetControl(SetControlInstruction::SetMoveUp(s))=>state.input_state.set_control(Controls::MoveUp,s), + Instruction::SetControl(SetControlInstruction::SetMoveDown(s))=>state.input_state.set_control(Controls::MoveDown,s), + Instruction::SetControl(SetControlInstruction::SetJump(s))=>{ state.input_state.set_control(Controls::Jump,s); if let Some(walk_state)=state.move_state.get_walk_state(){ if let Some(jump_settings)=&state.style.jump{ @@ -1787,16 +1787,16 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI } b_refresh_walk_target=false; }, - Instruction::NonMouse(NonMouseInstruction::SetControl(SetControlInstruction::SetZoom(s)))=>{ + Instruction::SetControl(SetControlInstruction::SetZoom(s))=>{ state.input_state.set_control(Controls::Zoom,s); b_refresh_walk_target=false; }, - Instruction::NonMouse(NonMouseInstruction::Mode(ModeInstruction::Reset))=>{ + Instruction::Mode(ModeInstruction::Reset)=>{ //totally reset physics state state.reset_to_default(); b_refresh_walk_target=false; }, - Instruction::NonMouse(NonMouseInstruction::Mode(ModeInstruction::Restart))=>{ + Instruction::Mode(ModeInstruction::Restart)=>{ //teleport to start zone let mode=data.modes.get_mode(state.mode_state.get_mode_id()); let spawn_point=mode.and_then(|mode| @@ -1812,7 +1812,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI b_refresh_walk_target=false; } // Spawn does not necessarily imply reset - Instruction::NonMouse(NonMouseInstruction::Mode(ModeInstruction::Spawn(mode_id,stage_id)))=>{ + Instruction::Mode(ModeInstruction::Spawn(mode_id,stage_id))=>{ //spawn at a particular stage if let Some(mode)=data.modes.get_mode(mode_id){ if let Some(stage)=mode.get_stage(stage_id){ @@ -1826,7 +1826,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI } b_refresh_walk_target=false; }, - Instruction::NonMouse(NonMouseInstruction::Misc(MiscInstruction::PracticeFly))=>{ + Instruction::Misc(MiscInstruction::PracticeFly)=>{ match &state.move_state{ MoveState::Fly=>{ state.set_move_state(data,MoveState::Air); @@ -1837,7 +1837,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI } b_refresh_walk_target=false; }, - Instruction::NonMouse(NonMouseInstruction::Misc(MiscInstruction::Idle))=>{ + Instruction::Misc(MiscInstruction::Idle)=>{ //literally idle! b_refresh_walk_target=false; }, diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs index 9571308..6bd782c 100644 --- a/strafe-client/src/session.rs +++ b/strafe-client/src/session.rs @@ -3,7 +3,7 @@ use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,Inst // session represents the non-hardware state of the client. // Ideally it is a deterministic state which is atomically updated by instructions, same as the simulation state. use strafesnet_common::physics::{ - ModeInstruction,NonMouseInstruction,MiscInstruction, + ModeInstruction,MiscInstruction, Instruction as PhysicsInputInstruction, TimeInner as PhysicsTimeInner, Time as PhysicsTime @@ -144,20 +144,20 @@ impl InstructionConsumer> for Session{ run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::MoveMouse(pos)); }, Instruction::Input(SessionInputInstruction::SetControl(set_control_instruction))=>{ - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::SetControl(set_control_instruction))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::SetControl(set_control_instruction)); }, Instruction::Input(SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndRestart))=>{ - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Mode(ModeInstruction::Reset))); - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())))); - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Mode(ModeInstruction::Restart))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset)); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Restart)); }, Instruction::Input(SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndSpawn(mode_id,spawn_id)))=>{ - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Mode(ModeInstruction::Reset))); - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())))); - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id)))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset)); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id))); }, Instruction::Input(SessionInputInstruction::Misc(other_other_instruction))=>{ - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Misc(other_other_instruction))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(other_other_instruction)); }, Instruction::SetPaused(paused)=>{ // don't flush the buffered instructions in the mouse interpolator @@ -168,9 +168,9 @@ impl InstructionConsumer> for Session{ Instruction::ChangeMap(complete_map)=>{ self.change_map(complete_map); // ResetAndSpawn - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Mode(ModeInstruction::Reset))); - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())))); - run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(NonMouseInstruction::Mode(ModeInstruction::Spawn(ModeId::MAIN,StageId::FIRST)))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset)); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))); + run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Spawn(ModeId::MAIN,StageId::FIRST))); }, };