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)]
pub enum TimeInner{}
pub type Time=crate::integer::Time<TimeInner>;
#[derive(Clone,Debug)]
pub enum Instruction{
ReplaceMouse(crate::mouse::MouseState<TimeInner>,crate::mouse::MouseState<TimeInner>),
SetNextMouse(crate::mouse::MouseState<TimeInner>),
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<TimeInner>,
s1:MouseState<TimeInner>,
},
SetNextMouse(MouseState<TimeInner>),
}
#[derive(Clone,Debug)]
pub enum OtherInstruction{
SetMoveRight(bool),
SetMoveUp(bool),
SetMoveBack(bool),

View File

@ -1,3 +1,9 @@
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
pub enum 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::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<PhysicsInputInstruction,PhysicsTimeInner>;
@ -9,23 +15,6 @@ type DoubleTimedUnbufferedInstruction=TimedInstruction<PhysicsTimedUnbufferedIns
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{
Other,
ReplaceMouse,
@ -38,11 +27,11 @@ enum BufferState{
Buffered(SessionTime,MouseState<PhysicsTimeInner>),
}
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{
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
||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>>{
let timeout=self.last_mouse_state.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
match &self.buffer_state{
BufferState::Unbuffered=>self.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 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>>{
@ -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
},

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.
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),