reintroduce generics to Instruction traits
This commit is contained in:
parent
16abe23e97
commit
ca003edbc3
@ -6,16 +6,32 @@ pub struct TimedInstruction<I,T>{
|
||||
pub instruction:I,
|
||||
}
|
||||
|
||||
pub trait InstructionEmitter{
|
||||
type Instruction;
|
||||
/// Ensure all emitted instructions are processed before consuming external instructions
|
||||
pub trait InstructionEmitter<I>{
|
||||
type TimeInner;
|
||||
fn next_instruction(&self,time_limit:Time<Self::TimeInner>)->Option<TimedInstruction<Self::Instruction,Self::TimeInner>>;
|
||||
fn next_instruction(&self,time_limit:Time<Self::TimeInner>)->Option<TimedInstruction<I,Self::TimeInner>>;
|
||||
}
|
||||
pub trait InstructionConsumer{
|
||||
type Instruction;
|
||||
/// Apply an atomic state update
|
||||
pub trait InstructionConsumer<I>{
|
||||
type TimeInner;
|
||||
fn process_instruction(&mut self, instruction:TimedInstruction<Self::Instruction,Self::TimeInner>);
|
||||
fn process_instruction(&mut self,instruction:TimedInstruction<I,Self::TimeInner>);
|
||||
}
|
||||
/// If the object produces its own instructions, allow exhaustively feeding them back in
|
||||
pub trait InstructionFeedback<I,T>:InstructionEmitter<I,TimeInner=T>+InstructionConsumer<I,TimeInner=T>
|
||||
where
|
||||
Time<T>:Copy,
|
||||
{
|
||||
fn process_exhaustive(&mut self,time_limit:Time<T>){
|
||||
while let Some(instruction)=self.next_instruction(time_limit){
|
||||
self.process_instruction(instruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<I,T,X> InstructionFeedback<I,T> for X
|
||||
where
|
||||
Time<T>:Copy,
|
||||
X:InstructionEmitter<I,TimeInner=T>+InstructionConsumer<I,TimeInner=T>,
|
||||
{}
|
||||
|
||||
//PROPER PRIVATE FIELDS!!!
|
||||
pub struct InstructionCollector<I,T>{
|
||||
|
@ -9,7 +9,7 @@ use strafesnet_common::gameplay_attributes::{self,CollisionAttributesId};
|
||||
use strafesnet_common::gameplay_modes::{self,StageId};
|
||||
use strafesnet_common::gameplay_style::{self,StyleModifiers};
|
||||
use strafesnet_common::controls_bitflag::Controls;
|
||||
use strafesnet_common::instruction::{self,InstructionEmitter,InstructionConsumer,TimedInstruction};
|
||||
use strafesnet_common::instruction::{self,InstructionEmitter,InstructionConsumer,InstructionFeedback,TimedInstruction};
|
||||
use strafesnet_common::integer::{self,vec3,mat3,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2};
|
||||
pub use strafesnet_common::physics::{Time,TimeInner};
|
||||
use gameplay::ModeState;
|
||||
@ -935,16 +935,21 @@ pub struct PhysicsContext{
|
||||
state:PhysicsState,//this captures the entire state of the physics.
|
||||
data:PhysicsData,//data currently loaded into memory which is needded for physics to run, but is not part of the state.
|
||||
}
|
||||
//the physics consumes the generic PhysicsInstruction, but can only emit the more narrow PhysicsInternalInstruction
|
||||
impl instruction::InstructionConsumer for PhysicsContext{
|
||||
type Instruction=PhysicsInstruction;
|
||||
// the physics consumes both PhysicsInputInstruction and PhysicsInternalInstruction,
|
||||
// but can only emit PhysicsInternalInstruction
|
||||
impl InstructionConsumer<PhysicsInternalInstruction> for PhysicsContext{
|
||||
type TimeInner=TimeInner;
|
||||
fn process_instruction(&mut self,ins:TimedInstruction<PhysicsInstruction,TimeInner>){
|
||||
atomic_state_update(&mut self.state,&self.data,ins)
|
||||
fn process_instruction(&mut self,ins:TimedInstruction<PhysicsInternalInstruction,TimeInner>){
|
||||
atomic_internal_instruction(&mut self.state,&self.data,ins)
|
||||
}
|
||||
}
|
||||
impl instruction::InstructionEmitter for PhysicsContext{
|
||||
type Instruction=PhysicsInternalInstruction;
|
||||
impl InstructionConsumer<PhysicsInputInstruction> for PhysicsContext{
|
||||
type TimeInner=TimeInner;
|
||||
fn process_instruction(&mut self,ins:TimedInstruction<PhysicsInputInstruction,TimeInner>){
|
||||
atomic_input_instruction(&mut self.state,&self.data,ins)
|
||||
}
|
||||
}
|
||||
impl InstructionEmitter<PhysicsInternalInstruction> for PhysicsContext{
|
||||
type TimeInner=TimeInner;
|
||||
//this little next instruction function could cache its return value and invalidate the cached value by watching the State.
|
||||
fn next_instruction(&self,time_limit:Time)->Option<TimedInstruction<PhysicsInternalInstruction,TimeInner>>{
|
||||
@ -1104,24 +1109,9 @@ impl PhysicsContext{
|
||||
println!("Physics Objects: {}",model_count);
|
||||
}
|
||||
|
||||
//tickless gaming
|
||||
fn run_internal_exhaustive(&mut self,time_limit:Time){
|
||||
//prepare is ommitted - everything is done via instructions.
|
||||
while let Some(instruction)=self.next_instruction(time_limit){//collect
|
||||
//process
|
||||
self.process_instruction(TimedInstruction{
|
||||
time:instruction.time,
|
||||
instruction:PhysicsInstruction::Internal(instruction.instruction),
|
||||
});
|
||||
//write hash lol
|
||||
}
|
||||
}
|
||||
pub fn run_input_instruction(&mut self,instruction:TimedInstruction<PhysicsInputInstruction,TimeInner>){
|
||||
self.run_internal_exhaustive(instruction.time);
|
||||
self.process_instruction(TimedInstruction{
|
||||
time:instruction.time,
|
||||
instruction:PhysicsInstruction::Input(instruction.instruction),
|
||||
});
|
||||
self.process_exhaustive(instruction.time);
|
||||
self.process_instruction(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1881,26 +1871,6 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
|
||||
}
|
||||
}
|
||||
|
||||
fn atomic_state_update(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInstruction,TimeInner>){
|
||||
match &ins.instruction{
|
||||
PhysicsInstruction::Input(PhysicsInputInstruction::Idle)
|
||||
|PhysicsInstruction::Input(PhysicsInputInstruction::SetNextMouse(_))
|
||||
|PhysicsInstruction::Input(PhysicsInputInstruction::ReplaceMouse(_,_))
|
||||
|PhysicsInstruction::Internal(PhysicsInternalInstruction::StrafeTick)
|
||||
|PhysicsInstruction::Internal(PhysicsInternalInstruction::ReachWalkTargetVelocity)=>(),
|
||||
_=>println!("{}|{:?}",ins.time,ins.instruction),
|
||||
}
|
||||
if ins.time<state.time{
|
||||
println!("@@@@ Time travel warning! state.time={} ins.time={}\nInstruction={:?}",state.time,ins.time,ins.instruction);
|
||||
}
|
||||
//idle is special, it is specifically a no-op to get Internal events to catch up to real time
|
||||
match ins.instruction{
|
||||
PhysicsInstruction::Input(PhysicsInputInstruction::Idle)=>(),
|
||||
PhysicsInstruction::Internal(instruction)=>atomic_internal_instruction(state,data,TimedInstruction{time:ins.time,instruction}),
|
||||
PhysicsInstruction::Input(instruction)=>atomic_input_instruction(state,data,TimedInstruction{time:ins.time,instruction}),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test{
|
||||
use strafesnet_common::integer::{vec3::{self,int as int3},mat3};
|
||||
|
Loading…
Reference in New Issue
Block a user