From c338826513b75d38c3c8f142b7109c603efdf03d Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 14 Jan 2025 21:16:36 -0800 Subject: [PATCH] finish --- strafe-client/src/physics.rs | 122 +++++++++++++++-------------------- strafe-client/src/session.rs | 60 +++++++++-------- 2 files changed, 81 insertions(+), 101 deletions(-) diff --git a/strafe-client/src/physics.rs b/strafe-client/src/physics.rs index b176cd6..9d309b1 100644 --- a/strafe-client/src/physics.rs +++ b/strafe-client/src/physics.rs @@ -19,27 +19,18 @@ type MouseState=strafesnet_common::mouse::MouseState; //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,time:Time)->Option>{ + fn next_move_instruction(&self,strafe:&Option,time:Time)->Option>{ //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,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){ + fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector,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>{ + fn next_move_instruction(&self)->Option>{ 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 for PhysicsContext{ +impl InstructionConsumer for PhysicsContext{ type TimeInner=TimeInner; - fn process_instruction(&mut self,ins:TimedInstruction){ + fn process_instruction(&mut self,ins:TimedInstruction){ atomic_internal_instruction(&mut self.state,&self.data,ins) } } -impl InstructionConsumer for PhysicsContext{ +impl InstructionConsumer for PhysicsContext{ type TimeInner=TimeInner; - fn process_instruction(&mut self,ins:TimedInstruction){ + fn process_instruction(&mut self,ins:TimedInstruction){ atomic_input_instruction(&mut self.state,&self.data,ins) } } -impl InstructionEmitter for PhysicsContext{ +impl InstructionEmitter 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>{ + fn next_instruction(&self,time_limit:Time)->Option>{ 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){ + pub fn run_input_instruction(&mut self,instruction:TimedInstruction){ 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>{ + fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Time)->Option>{ //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){ +fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction){ 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){ +fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction){ 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; }, diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs index 27d659d..3f704c3 100644 --- a/strafe-client/src/session.rs +++ b/strafe-client/src/session.rs @@ -121,39 +121,37 @@ impl Session{ impl InstructionConsumer> for Session{ type TimeInner=SessionTimeInner; fn process_instruction(&mut self,ins:TimedInstruction){ + 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