This commit is contained in:
Quaternions 2025-01-14 21:16:36 -08:00
parent a6a242175b
commit c338826513
2 changed files with 81 additions and 101 deletions

View File

@ -19,27 +19,18 @@ type MouseState=strafesnet_common::mouse::MouseState<TimeInner>;
//external influence
//this is how you influence the physics from outside
use strafesnet_common::physics::Instruction as PhysicsInputInstruction;
use strafesnet_common::physics::OtherInstruction as PhysicsOtherInstruction;
use strafesnet_common::physics::MouseInstruction as PhysicsMouseInstruction;
use strafesnet_common::physics::{Instruction,OtherInstruction,MouseInstruction,ModeInstruction,OtherOtherInstruction,SetControlInstruction};
//internal influence
//when the physics asks itself what happens next, this is how it's represented
#[derive(Debug)]
pub enum PhysicsInternalInstruction{
pub enum InternalInstruction{
CollisionStart(Collision,model_physics::GigaTime),
CollisionEnd(Collision,model_physics::GigaTime),
StrafeTick,
ReachWalkTargetVelocity,
// Water,
}
#[derive(Debug)]
pub enum PhysicsInstruction{
Internal(PhysicsInternalInstruction),
//InputInstructions conditionally activate RefreshWalkTarget
//(by doing what SetWalkTargetVelocity used to do and then flagging it)
Input(PhysicsInputInstruction),
}
#[derive(Clone,Debug,Default)]
pub struct InputState{
@ -560,13 +551,13 @@ impl MoveState{
=>None,
}
}
fn next_move_instruction(&self,strafe:&Option<gameplay_style::StrafeSettings>,time:Time)->Option<TimedInstruction<PhysicsInternalInstruction,TimeInner>>{
fn next_move_instruction(&self,strafe:&Option<gameplay_style::StrafeSettings>,time:Time)->Option<TimedInstruction<InternalInstruction,TimeInner>>{
//check if you have a valid walk state and create an instruction
match self{
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.target{
&TransientAcceleration::Reachable{acceleration:_,time}=>Some(TimedInstruction{
time,
instruction:PhysicsInternalInstruction::ReachWalkTargetVelocity
instruction:InternalInstruction::ReachWalkTargetVelocity
}),
TransientAcceleration::Unreachable{acceleration:_}
|TransientAcceleration::Reached
@ -576,7 +567,7 @@ impl MoveState{
TimedInstruction{
time:strafe.next_tick(time),
//only poll the physics if there is a before and after mouse event
instruction:PhysicsInternalInstruction::StrafeTick
instruction:InternalInstruction::StrafeTick
}
}),
MoveState::Water=>None,//TODO
@ -788,7 +779,7 @@ impl TouchingState{
}).collect();
*acceleration=crate::push_solve::push_solve(&contacts,*acceleration);
}
fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<PhysicsInternalInstruction,TimeInner>,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){
fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<InternalInstruction,TimeInner>,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){
let relative_body=crate::body::VirtualBody::relative(&Body::ZERO,body).body(time);
for contact in &self.contacts{
//detect face slide off
@ -797,7 +788,7 @@ impl TouchingState{
collector.collect(minkowski.predict_collision_face_out(&relative_body,collector.time(),contact.face_id).map(|(_face,time)|{
TimedInstruction{
time:relative_body.time+time.into(),
instruction:PhysicsInternalInstruction::CollisionEnd(
instruction:InternalInstruction::CollisionEnd(
Collision::Contact(*contact),
time
),
@ -811,7 +802,7 @@ impl TouchingState{
collector.collect(minkowski.predict_collision_out(&relative_body,collector.time()).map(|(_face,time)|{
TimedInstruction{
time:relative_body.time+time.into(),
instruction:PhysicsInternalInstruction::CollisionEnd(
instruction:InternalInstruction::CollisionEnd(
Collision::Intersect(*intersect),
time
),
@ -886,7 +877,7 @@ impl PhysicsState{
fn reset_to_default(&mut self){
*self=Self::default();
}
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInternalInstruction,TimeInner>>{
fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,TimeInner>>{
self.move_state.next_move_instruction(&self.style.strafe,self.time)
}
fn cull_velocity(&mut self,data:&PhysicsData,velocity:Planar64Vec3){
@ -935,24 +926,24 @@ 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 both PhysicsInputInstruction and PhysicsInternalInstruction,
// the physics consumes both Instruction and PhysicsInternalInstruction,
// but can only emit PhysicsInternalInstruction
impl InstructionConsumer<PhysicsInternalInstruction> for PhysicsContext{
impl InstructionConsumer<InternalInstruction> for PhysicsContext{
type TimeInner=TimeInner;
fn process_instruction(&mut self,ins:TimedInstruction<PhysicsInternalInstruction,TimeInner>){
fn process_instruction(&mut self,ins:TimedInstruction<InternalInstruction,TimeInner>){
atomic_internal_instruction(&mut self.state,&self.data,ins)
}
}
impl InstructionConsumer<PhysicsInputInstruction> for PhysicsContext{
impl InstructionConsumer<Instruction> for PhysicsContext{
type TimeInner=TimeInner;
fn process_instruction(&mut self,ins:TimedInstruction<PhysicsInputInstruction,TimeInner>){
fn process_instruction(&mut self,ins:TimedInstruction<Instruction,TimeInner>){
atomic_input_instruction(&mut self.state,&self.data,ins)
}
}
impl InstructionEmitter<PhysicsInternalInstruction> for PhysicsContext{
impl InstructionEmitter<InternalInstruction> 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>>{
fn next_instruction(&self,time_limit:Time)->Option<TimedInstruction<InternalInstruction,TimeInner>>{
next_instruction_internal(&self.state,&self.data,time_limit)
}
}
@ -1109,14 +1100,14 @@ impl PhysicsContext{
println!("Physics Objects: {}",model_count);
}
pub fn run_input_instruction(&mut self,instruction:TimedInstruction<PhysicsInputInstruction,TimeInner>){
pub fn run_input_instruction(&mut self,instruction:TimedInstruction<Instruction,TimeInner>){
self.process_exhaustive(instruction.time);
self.process_instruction(instruction);
}
}
//this is the one who asks
fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Time)->Option<TimedInstruction<PhysicsInternalInstruction,TimeInner>>{
fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Time)->Option<TimedInstruction<InternalInstruction,TimeInner>>{
//JUST POLLING!!! NO MUTATION
let mut collector = instruction::InstructionCollector::new(time_limit);
@ -1144,7 +1135,7 @@ impl PhysicsContext{
}).map(|(time,face,dt)|
TimedInstruction{
time,
instruction:PhysicsInternalInstruction::CollisionStart(
instruction:InternalInstruction::CollisionStart(
Collision::new(convex_mesh_id,face),
dt
)
@ -1650,13 +1641,13 @@ fn collision_end_intersect(
}
}
}
fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInternalInstruction,TimeInner>){
fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<InternalInstruction,TimeInner>){
state.time=ins.time;
let (should_advance_body,goober_time)=match ins.instruction{
PhysicsInternalInstruction::CollisionStart(_,dt)
|PhysicsInternalInstruction::CollisionEnd(_,dt)=>(true,Some(dt)),
PhysicsInternalInstruction::StrafeTick
|PhysicsInternalInstruction::ReachWalkTargetVelocity=>(true,None),
InternalInstruction::CollisionStart(_,dt)
|InternalInstruction::CollisionEnd(_,dt)=>(true,Some(dt)),
InternalInstruction::StrafeTick
|InternalInstruction::ReachWalkTargetVelocity=>(true,None),
};
if should_advance_body{
match goober_time{
@ -1665,7 +1656,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
}
}
match ins.instruction{
PhysicsInternalInstruction::CollisionStart(collision,_)=>{
InternalInstruction::CollisionStart(collision,_)=>{
let mode=data.modes.get_mode(state.mode_state.get_mode_id());
match collision{
Collision::Contact(contact)=>collision_start_contact(
@ -1686,7 +1677,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
),
}
},
PhysicsInternalInstruction::CollisionEnd(collision,_)=>match collision{
InternalInstruction::CollisionEnd(collision,_)=>match collision{
Collision::Contact(contact)=>collision_end_contact(
&mut state.move_state,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state,
data.models.contact_attr(contact.model_id),
@ -1701,7 +1692,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
state.time
),
},
PhysicsInternalInstruction::StrafeTick=>{
InternalInstruction::StrafeTick=>{
//TODO make this less huge
if let Some(strafe_settings)=&state.style.strafe{
let controls=state.input_state.controls;
@ -1719,7 +1710,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
}
}
}
PhysicsInternalInstruction::ReachWalkTargetVelocity=>{
InternalInstruction::ReachWalkTargetVelocity=>{
match &mut state.move_state{
MoveState::Air
|MoveState::Water
@ -1746,27 +1737,18 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
}
}
fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInputInstruction,TimeInner>){
fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<Instruction,TimeInner>){
state.time=ins.time;
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)
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetSensitivity(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::Reset)
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::Restart)
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::Spawn(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetZoom(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::Idle)=>false,
Instruction::Other(OtherInstruction::Other(OtherOtherInstruction::SetSensitivity(..)))
|Instruction::Other(OtherInstruction::Mode(_))
|Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetZoom(..)))
|Instruction::Other(OtherInstruction::Other(OtherOtherInstruction::Idle))=>false,
//these controls only update the body if you are on the ground
PhysicsInputInstruction::Mouse(PhysicsMouseInstruction::SetNextMouse(..))
|PhysicsInputInstruction::Mouse(PhysicsMouseInstruction::ReplaceMouse{..})
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveForward(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveLeft(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveBack(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveRight(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveUp(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveDown(..))
|PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetJump(..))=>{
Instruction::Mouse(_)
|Instruction::Other(OtherInstruction::SetControl(_))=>{
match &state.move_state{
MoveState::Fly
|MoveState::Water
@ -1776,7 +1758,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
}
},
//the body must be updated unconditionally
PhysicsInputInstruction::Other(PhysicsOtherInstruction::PracticeFly)=>true,
Instruction::Other(OtherInstruction::Other(OtherOtherInstruction::PracticeFly))=>true,
};
if should_advance_body{
state.body.advance_time(state.time);
@ -1784,22 +1766,22 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
let mut b_refresh_walk_target=true;
match ins.instruction{
PhysicsInputInstruction::Mouse(PhysicsMouseInstruction::SetNextMouse(m))=>{
Instruction::Mouse(MouseInstruction::SetNextMouse(m))=>{
state.camera.move_mouse(state.input_state.mouse_delta());
state.input_state.set_next_mouse(m);
},
PhysicsInputInstruction::Mouse(PhysicsMouseInstruction::ReplaceMouse{m0,m1})=>{
Instruction::Mouse(MouseInstruction::ReplaceMouse{m0,m1})=>{
state.camera.move_mouse(m0.pos-state.input_state.mouse.pos);
state.input_state.replace_mouse(m0,m1);
},
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetSensitivity(sensitivity))=>state.camera.sensitivity=sensitivity,
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveForward(s))=>state.input_state.set_control(Controls::MoveForward,s),
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveLeft(s))=>state.input_state.set_control(Controls::MoveLeft,s),
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveBack(s))=>state.input_state.set_control(Controls::MoveBackward,s),
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveRight(s))=>state.input_state.set_control(Controls::MoveRight,s),
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveUp(s))=>state.input_state.set_control(Controls::MoveUp,s),
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetMoveDown(s))=>state.input_state.set_control(Controls::MoveDown,s),
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetJump(s))=>{
Instruction::Other(OtherInstruction::Other(OtherOtherInstruction::SetSensitivity(sensitivity)))=>state.camera.sensitivity=sensitivity,
Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetMoveForward(s)))=>state.input_state.set_control(Controls::MoveForward,s),
Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetMoveLeft(s)))=>state.input_state.set_control(Controls::MoveLeft,s),
Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetMoveBack(s)))=>state.input_state.set_control(Controls::MoveBackward,s),
Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetMoveRight(s)))=>state.input_state.set_control(Controls::MoveRight,s),
Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetMoveUp(s)))=>state.input_state.set_control(Controls::MoveUp,s),
Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetMoveDown(s)))=>state.input_state.set_control(Controls::MoveDown,s),
Instruction::Other(OtherInstruction::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{
@ -1811,16 +1793,16 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
}
b_refresh_walk_target=false;
},
PhysicsInputInstruction::Other(PhysicsOtherInstruction::SetZoom(s))=>{
Instruction::Other(OtherInstruction::SetControl(SetControlInstruction::SetZoom(s)))=>{
state.input_state.set_control(Controls::Zoom,s);
b_refresh_walk_target=false;
},
PhysicsInputInstruction::Other(PhysicsOtherInstruction::Reset)=>{
Instruction::Other(OtherInstruction::Mode(ModeInstruction::Reset))=>{
//totally reset physics state
state.reset_to_default();
b_refresh_walk_target=false;
},
PhysicsInputInstruction::Other(PhysicsOtherInstruction::Restart)=>{
Instruction::Other(OtherInstruction::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|
@ -1836,7 +1818,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
b_refresh_walk_target=false;
}
// Spawn does not necessarily imply reset
PhysicsInputInstruction::Other(PhysicsOtherInstruction::Spawn(mode_id,stage_id))=>{
Instruction::Other(OtherInstruction::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){
@ -1850,7 +1832,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
}
b_refresh_walk_target=false;
},
PhysicsInputInstruction::Other(PhysicsOtherInstruction::PracticeFly)=>{
Instruction::Other(OtherInstruction::Other(OtherOtherInstruction::PracticeFly))=>{
match &state.move_state{
MoveState::Fly=>{
state.set_move_state(data,MoveState::Air);
@ -1861,7 +1843,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
}
b_refresh_walk_target=false;
},
PhysicsInputInstruction::Other(PhysicsOtherInstruction::Idle)=>{
Instruction::Other(OtherInstruction::Other(OtherOtherInstruction::Idle))=>{
//literally idle!
b_refresh_walk_target=false;
},

View File

@ -121,39 +121,37 @@ impl Session{
impl InstructionConsumer<Instruction<'_>> for Session{
type TimeInner=SessionTimeInner;
fn process_instruction(&mut self,ins:TimedInstruction<Instruction,Self::TimeInner>){
macro_rules! run_mouse_interpolator_instruction{
($instruction:expr)=>{
self.mouse_interpolator.process_instruction(TimedInstruction{
time:ins.time,
instruction:TimedInstruction{
time:self.simulation.timer.time(ins.time),
instruction:$instruction,
},
});
};
}
match ins.instruction{
// send it down to MouseInterpolator with two timestamps, SessionTime and PhysicsTime
Instruction::Input(instruction)=>{
let instructions:&[MouseInterpolatorInstruction]=match instruction{
SessionInputInstruction::Mouse(pos)=>&[
MouseInterpolatorInstruction::MoveMouse(pos)
],
SessionInputInstruction::SetControl(set_control_instruction)=>&[
MouseInterpolatorInstruction::Other(OtherInstruction::SetControl(set_control_instruction))
],
SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndRestart)=>&[
MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Reset)),
MouseInterpolatorInstruction::Other(OtherInstruction::Other(OtherOtherInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))),
MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Restart)),
],
SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndSpawn(mode_id,spawn_id))=>&[
MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Reset)),
MouseInterpolatorInstruction::Other(OtherInstruction::Other(OtherOtherInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))),
MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id))),
],
SessionInputInstruction::Other(other_other_instruction)=>&[
MouseInterpolatorInstruction::Other(OtherInstruction::Other(other_other_instruction))
],
};
for ins_interpolator in (*instructions).into_iter(){
self.mouse_interpolator.process_instruction(TimedInstruction{
time:ins.time,
instruction:TimedInstruction{
time:self.simulation.timer.time(ins.time),
instruction:ins_interpolator,
},
});
}
Instruction::Input(SessionInputInstruction::Mouse(pos))=>{
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::MoveMouse(pos));
},
Instruction::Input(SessionInputInstruction::SetControl(set_control_instruction))=>{
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::SetControl(set_control_instruction)));
},
Instruction::Input(SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndRestart))=>{
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Reset)));
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::Other(OtherOtherInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))));
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Restart)));
},
Instruction::Input(SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndSpawn(mode_id,spawn_id)))=>{
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Reset)));
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::Other(OtherOtherInstruction::SetSensitivity(self.user_settings().calculate_sensitivity()))));
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id))));
},
Instruction::Input(SessionInputInstruction::Other(other_other_instruction))=>{
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Other(OtherInstruction::Other(other_other_instruction)));
},
Instruction::SetPaused(paused)=>{
// don't flush the buffered instructions in the mouse interpolator