diff --git a/strafe-client/src/mouse_interpolator.rs b/strafe-client/src/mouse_interpolator.rs index c28665f..5f5b8bc 100644 --- a/strafe-client/src/mouse_interpolator.rs +++ b/strafe-client/src/mouse_interpolator.rs @@ -1,17 +1,15 @@ 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::instruction::{self,InstructionConsumer,InstructionEmitter,TimedInstruction}; +use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,TimedInstruction}; + +use crate::session::StepInstruction as SessionInternalInstruction; type TimedPhysicsInstruction=TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>; -type TimedInterpolatorInstruction=TimedInstruction<Instruction,SessionTimeInner>; - -pub struct DropInstruction<'a>{ - instruction:&'a TimedPhysicsInstruction, -} +type TimedInterpolatorInstruction=TimedInstruction<UnbufferedInputInstruction,SessionTimeInner>; #[derive(Debug)] -pub enum InputInstruction{ +pub enum UnbufferedInputInstruction{ MoveMouse(glam::IVec2), MoveRight(bool), MoveUp(bool), @@ -26,52 +24,42 @@ pub enum InputInstruction{ PracticeFly, Idle, } -pub enum Instruction{ - Input(InputInstruction), - //SetPaused is not an InputInstruction: the physics doesn't know that it's paused. - SetPaused(bool), - //Graphics(crate::graphics_worker::Instruction), -} pub struct MouseInterpolator{ - session_timeline:std::collections::VecDeque<TimedInterpolatorInstruction>, physics_timeline:std::collections::VecDeque<TimedPhysicsInstruction>, } // Maybe MouseInterpolator manipulation is better expressed using impls // and called from Instruction trait impls in session -impl InstructionConsumer<Instruction> for MouseInterpolator{ +impl InstructionConsumer<UnbufferedInputInstruction> for MouseInterpolator{ type TimeInner=SessionTimeInner; fn process_instruction(&mut self,ins:TimedInterpolatorInstruction){ - self.push_input(ins) + self.push_unbuffered_input(ins) } } -impl<'a> InstructionConsumer<DropInstruction<'a>> for MouseInterpolator{ +impl InstructionEmitter<SessionInternalInstruction> for MouseInterpolator{ type TimeInner=SessionTimeInner; - fn process_instruction(&mut self,ins:TimedInstruction<DropInstruction<'a>,SessionTimeInner>){ - self.drop_output(ins) - } -} -impl<'a> InstructionEmitter<DropInstruction<'a>> for MouseInterpolator{ - type TimeInner=SessionTimeInner; - fn next_instruction(&'a self,time_limit:SessionTime)->Option<TimedInstruction<DropInstruction<'a>,Self::TimeInner>>{ - self.next_output(time_limit) + fn next_instruction(&self,time_limit:SessionTime)->Option<TimedInstruction<SessionInternalInstruction,Self::TimeInner>>{ + self.buffered_instruction_with_timeout(time_limit) } } impl MouseInterpolator{ pub fn new()->MouseInterpolator{ MouseInterpolator{ - session_timeline:std::collections::VecDeque::new(), physics_timeline:std::collections::VecDeque::new(), } } - pub fn push_input(&mut self,ins:TimedInterpolatorInstruction){ + pub fn push_unbuffered_input(&mut self,ins:TimedInterpolatorInstruction){ // new input } - pub fn drop_output<'a>(&mut self,ins:TimedInstruction<DropInstruction<'a>,SessionTimeInner>){ + pub fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option<TimedInstruction<SessionInternalInstruction,SessionTimeInner>>{ + // if the mouse has stopped moving for over 10ms, emit DoStepReplaceMouse + // if there is a mouse interpolation target, emit DoStep + // else emit None + None + } + pub fn pop_buffered_instruction(&mut self)->Option<TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>>{ // so the idea is that Session gets in the middle of MouseInterpolator instruction processing // and injects its own side effects, notably running physics - } - pub fn next_output(&self,time_limit:SessionTime)->Option<TimedInstruction<DropInstruction<'_>,SessionTimeInner>>{ None } } diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs index 8e70397..a4a1440 100644 --- a/strafe-client/src/session.rs +++ b/strafe-client/src/session.rs @@ -1,23 +1,25 @@ -use strafesnet_common::instruction::{InstructionConsumer, InstructionEmitter}; +use strafesnet_common::instruction::{InstructionConsumer, InstructionEmitter, InstructionFeedback, TimedInstruction}; // 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::{Instruction as PhysicsInputInstruction,Time as PhysicsTime}; +use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,TimeInner as PhysicsTimeInner,Time as PhysicsTime}; use strafesnet_common::timer::{Scaled,Timer}; -use strafesnet_common::physics::TimeInner as PhysicsTimeInner; -use strafesnet_common::session::TimeInner as SessionTimeInner; +use strafesnet_common::session::{TimeInner as SessionTimeInner,Time as SessionTime}; -use crate::mouse_interpolator::MouseInterpolator; +use crate::mouse_interpolator::{MouseInterpolator,UnbufferedInputInstruction}; -pub enum Instruction{ - Input(InputInstruction), +pub enum ExternalInstruction{ + ToBuffer(UnbufferedInputInstruction), + SetPaused(bool), Render, Resize(winit::dpi::PhysicalSize<u32>), ChangeMap(strafesnet_common::map::CompleteMap), - //SetPaused is not an InputInstruction: the physics doesn't know that it's paused. - SetPaused(bool), //Graphics(crate::graphics_worker::Instruction), } +pub enum StepInstruction{ + DoStep, +} + pub struct FrameState{ pub body:crate::physics::Body, pub camera:crate::physics::PhysicsCamera, @@ -81,28 +83,49 @@ impl Session{ // mouseinterpolator consumes RawInputInstruction // mouseinterpolator emits PhysicsInputInstruction -// mouseinterpolator consumes DropInstruction to move on to the next emitted instruction +// mouseinterpolator consumes DoStep to move on to the next emitted instruction // Session comsumes SessionInstruction -> forwards RawInputInstruction to mouseinterpolator -// Session consumes DropInstruction -> forwards DropInstruction to mouseinterpolator -// Session emits DropInstruction +// Session consumes DoStep -> forwards DoStep to mouseinterpolator +// Session emits DoStep -impl InstructionConsumer<Instruction> for Session{ +impl InstructionConsumer<ExternalInstruction> for Session{ type TimeInner=SessionTimeInner; - fn process_instruction(&mut self,instruction:strafesnet_common::instruction::TimedInstruction<Instruction,Self::TimeInner>){ - // send it down to MouseInterpolator - self.mouse_interpolator.process_instruction(ins); + fn process_instruction(&mut self,ins:TimedInstruction<ExternalInstruction,Self::TimeInner>){ + match ins.instruction{ + // send it down to MouseInterpolator + ExternalInstruction::ToBuffer(instruction)=>self.mouse_interpolator.process_instruction(TimedInstruction{ + time:ins.time, + instruction, + }), + ExternalInstruction::SetPaused(paused)=>{ + // don't flush the buffered instructions in the mouse interpolator + // until the mouse is confirmed to be not moving at a later time + // what if they pause for 5ms lmao + _=self.simulation.timer.set_paused(ins.time,paused); + } + ExternalInstruction::Render=>(), + ExternalInstruction::Resize(physical_size)=>(), + ExternalInstruction::ChangeMap(complete_map)=>(), + }; + // run all buffered instruction produced + self.process_exhaustive(ins.time); } } -impl<'a> InstructionConsumer<DropInstruction<'a>> for Session{ +impl InstructionConsumer<StepInstruction> for Session{ type TimeInner=SessionTimeInner; - fn process_instruction(&mut self,instruction:strafesnet_common::instruction::TimedInstruction<DropInstruction,Self::TimeInner>){ - // send it down to MouseInterpolator - self.mouse_interpolator.process_instruction(ins); + fn process_instruction(&mut self,ins:TimedInstruction<StepInstruction,Self::TimeInner>){ + match ins.instruction{ + StepInstruction::DoStep=>{ + if let Some(instruction)=self.mouse_interpolator.pop_buffered_instruction(){ + self.simulation.physics.run_input_instruction(instruction); + } + } + } } } -impl<'a> InstructionEmitter<DropInstruction<'a>> for Session{ +impl InstructionEmitter<StepInstruction> for Session{ type TimeInner=SessionTimeInner; - fn next_instruction(&self,time_limit:strafesnet_common::integer::Time<Self::TimeInner>)->Option<strafesnet_common::instruction::TimedInstruction<DropInstruction,Self::TimeInner>>{ + fn next_instruction(&self,time_limit:SessionTime)->Option<TimedInstruction<StepInstruction,Self::TimeInner>>{ self.mouse_interpolator.next_instruction(time_limit) } }