cool changes

This commit is contained in:
Quaternions 2025-01-11 01:07:06 -08:00
parent 1b35c96f6e
commit 92c30c3b87
4 changed files with 96 additions and 52 deletions

View File

@ -1,11 +1,25 @@
use crate::mouse::MouseState;
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)] #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
pub enum TimeInner{} pub enum TimeInner{}
pub type Time=crate::integer::Time<TimeInner>; pub type Time=crate::integer::Time<TimeInner>;
#[derive(Clone,Debug)] #[derive(Clone,Debug)]
pub enum Instruction{ pub enum Instruction{
ReplaceMouse(crate::mouse::MouseState<TimeInner>,crate::mouse::MouseState<TimeInner>), Mouse(MouseInstruction),
SetNextMouse(crate::mouse::MouseState<TimeInner>), Other(OtherInstruction),
}
#[derive(Clone,Debug)]
pub enum MouseInstruction{
/// Replace the entire interpolation state to avoid dividing by zero when replacing twice
ReplaceMouse{
s0:MouseState<TimeInner>,
s1:MouseState<TimeInner>,
},
SetNextMouse(MouseState<TimeInner>),
}
#[derive(Clone,Debug)]
pub enum OtherInstruction{
SetMoveRight(bool), SetMoveRight(bool),
SetMoveUp(bool), SetMoveUp(bool),
SetMoveBack(bool), SetMoveBack(bool),

View File

@ -1,3 +1,9 @@
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)] #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
pub enum TimeInner{} pub enum TimeInner{}
pub type Time=crate::integer::Time<TimeInner>; pub type Time=crate::integer::Time<TimeInner>;
#[derive(Clone,Debug)]
pub enum UnbufferedInputInstruction{
MoveMouse(glam::IVec2),
Other(crate::physics::OtherInstruction),
}

View File

@ -1,6 +1,12 @@
use strafesnet_common::mouse::MouseState; use strafesnet_common::mouse::MouseState;
use strafesnet_common::physics::{Instruction as PhysicsInputInstruction,Time as PhysicsTime,TimeInner as PhysicsTimeInner}; use strafesnet_common::physics::{
use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner}; 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}; use strafesnet_common::instruction::{InstructionConsumer,InstructionEmitter,TimedInstruction};
type TimedPhysicsInstruction=TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>; type TimedPhysicsInstruction=TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>;
@ -9,23 +15,6 @@ type DoubleTimedUnbufferedInstruction=TimedInstruction<PhysicsTimedUnbufferedIns
const MOUSE_TIMEOUT:SessionTime=SessionTime::from_millis(10); const MOUSE_TIMEOUT:SessionTime=SessionTime::from_millis(10);
#[derive(Debug)]
pub enum UnbufferedInputInstruction{
MoveMouse(glam::IVec2),
MoveRight(bool),
MoveUp(bool),
MoveBack(bool),
MoveLeft(bool),
MoveDown(bool),
MoveForward(bool),
Jump(bool),
Zoom(bool),
ResetAndRestart,
ResetAndSpawn(strafesnet_common::gameplay_modes::ModeId,strafesnet_common::gameplay_modes::StageId),
PracticeFly,
Idle,
}
pub enum StepInstruction{ pub enum StepInstruction{
Other, Other,
ReplaceMouse, ReplaceMouse,
@ -38,11 +27,11 @@ enum BufferState{
Buffered(SessionTime,MouseState<PhysicsTimeInner>), Buffered(SessionTime,MouseState<PhysicsTimeInner>),
} }
impl BufferState{ impl BufferState{
fn next_state(&self,ins:DoubleTimedUnbufferedInstruction,physics_timeline:&mut std::collections::VecDeque<TimedPhysicsInstruction>)->Self{ fn next_state(&self,ins:DoubleTimedUnbufferedInstruction,physics_timeline:&mut std::collections::VecDeque<TimedPhysicsInstruction>)->(Self,Option<TimedInstruction<OtherInstruction,PhysicsTimeInner>>){
match self{ match self{
BufferState::Unbuffered=>{ BufferState::Unbuffered=>{
if let UnbufferedInputInstruction::MoveMouse(pos)=ins.instruction.instruction{ 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)=>{ BufferState::Initializing(time,mouse_state)=>{
@ -54,17 +43,24 @@ impl BufferState{
// but the timer is not accessible from this scope // but the timer is not accessible from this scope
// and it's just here to say that the mouse isn't moving anyways. // and it's just here to say that the mouse isn't moving anyways.
time:ins.instruction.time, 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{ if let UnbufferedInputInstruction::MoveMouse(pos)=ins.instruction.instruction{
let next_mouse_state=MouseState{pos,time:ins.instruction.time}; let next_mouse_state=MouseState{pos,time:ins.instruction.time};
physics_timeline.push_front(TimedInstruction{ physics_timeline.push_front(TimedInstruction{
time:mouse_state.time, 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)=>{ BufferState::Buffered(time,mouse_state)=>{
@ -76,21 +72,32 @@ impl BufferState{
// but the timer is not accessible from this scope // but the timer is not accessible from this scope
// and it's just here to say that the mouse isn't moving anyways. // and it's just here to say that the mouse isn't moving anyways.
time:ins.instruction.time, 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{ if let UnbufferedInputInstruction::MoveMouse(pos)=ins.instruction.instruction{
let next_mouse_state=MouseState{pos,time:ins.instruction.time}; let next_mouse_state=MouseState{pos,time:ins.instruction.time};
physics_timeline.push_front(TimedInstruction{ physics_timeline.push_front(TimedInstruction{
time:ins.instruction.time, 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{ pub struct MouseInterpolator{
@ -131,39 +138,55 @@ impl MouseInterpolator{
// case 3: stop // case 3: stop
// a mouse event is buffered, but no mouse events have transpired within 10ms // a mouse event is buffered, but no mouse events have transpired within 10ms
// TODO: remove clone // 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{ fn is_first_ready(&self)->bool{
// if the last instruction is a ReplaceMouse instruction // if the last instruction is a ReplaceMouse instruction
matches!(self.physics_timeline.back(),Some(TimedInstruction{ matches!(self.physics_timeline.back(),Some(TimedInstruction{
instruction:PhysicsInputInstruction::ReplaceMouse(_,_), instruction:PhysicsInputInstruction::Mouse(MouseInstruction::ReplaceMouse{..}),
.. ..
})) }))
// or if the last instruction is a SetNextMouse instruction // or if the last instruction is a SetNextMouse instruction
// and there is 2 or more instructions // and there is 2 or more instructions
||1<self.physics_timeline.len()&&matches!(self.physics_timeline.back(),Some(TimedInstruction{ ||1<self.physics_timeline.len()&&matches!(self.physics_timeline.back(),Some(TimedInstruction{
instruction:PhysicsInputInstruction::SetNextMouse(_), instruction:PhysicsInputInstruction::Mouse(MouseInstruction::SetNextMouse(_)),
.. ..
})) }))
} }
pub fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option<TimedInstruction<StepInstruction,SessionTimeInner>>{ pub fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option<TimedInstruction<StepInstruction,SessionTimeInner>>{
let timeout=self.last_mouse_state.time+MOUSE_TIMEOUT; match &self.buffer_state{
if timeout<time_limit{ BufferState::Unbuffered=>self.physics_timeline.front().map(|_|TimedInstruction{
// if the mouse has stopped moving for over 10ms, emit DoStepReplaceMouse at that exact timestamp
Some(TimedInstruction{
time:timeout,
instruction:StepInstruction::ReplaceMouse,
})
}else if self.is_first_ready(){
// emit Step
Some(TimedInstruction{
// this timestamp should not matter
// verify this and potentially emit a different type using the enum only
time:time_limit, time:time_limit,
instruction:StepInstruction::Other, instruction:StepInstruction::Other,
}) }),
}else{ BufferState::Initializing(time,_mouse_state)
None |BufferState::Buffered(time,_mouse_state)=>{
let timeout=*time+MOUSE_TIMEOUT;
if timeout<time_limit{
// if the mouse has stopped moving for over 10ms, emit DoStepReplaceMouse at that exact timestamp
Some(TimedInstruction{
time:timeout,
instruction:StepInstruction::ReplaceMouse,
})
}else if self.is_first_ready(){
// emit Step
Some(TimedInstruction{
// this timestamp should not matter
// verify this and potentially emit a different type using the enum only
time:time_limit,
instruction:StepInstruction::Other,
})
}else{
None
}
},
} }
} }
pub fn pop_buffered_instruction(&mut self,ins:StepInstruction)->Option<TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>>{ pub fn pop_buffered_instruction(&mut self,ins:StepInstruction)->Option<TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>>{
@ -177,6 +200,7 @@ impl MouseInterpolator{
// mouse instruction as an interpolation target // mouse instruction as an interpolation target
}, },
StepInstruction::ReplaceMouse=>{ StepInstruction::ReplaceMouse=>{
// convert to BufferState::Unbuffered
// use the first instruction which should be a mouse instruction // use the first instruction which should be a mouse instruction
// to push a ReplaceMouse instruction // to push a ReplaceMouse instruction
}, },

View File

@ -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. // 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::physics::{Instruction as PhysicsInputInstruction,TimeInner as PhysicsTimeInner,Time as PhysicsTime};
use strafesnet_common::timer::{Scaled,Timer}; 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{ pub enum ExternalInstruction{
ToBuffer(UnbufferedInputInstruction), ToBuffer(UnbufferedInputInstruction),