Compare commits
6 Commits
fix-surf
...
surf-bodge
| Author | SHA1 | Date | |
|---|---|---|---|
|
b33329a26a
|
|||
|
f3d705dc2b
|
|||
|
a482c9859a
|
|||
|
e6206c0e80
|
|||
|
77a3dc4aad
|
|||
|
fc9a720bc1
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -4045,7 +4045,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "strafesnet_physics"
|
||||
version = "0.0.2"
|
||||
version = "0.0.2-surf2"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"glam",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "strafesnet_physics"
|
||||
version = "0.0.2"
|
||||
version = "0.0.2-surf2"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -501,6 +501,27 @@ impl StyleHelper for StyleModifiers{
|
||||
}
|
||||
}
|
||||
#[derive(Clone,Debug)]
|
||||
struct StrafeTickState{
|
||||
tick_number:u64,
|
||||
}
|
||||
impl StrafeTickState{
|
||||
fn new(time:Time,settings:&gameplay_style::StrafeSettings)->Self{
|
||||
// let time=n*seconds/ticks;
|
||||
let time=time.nanos() as i128;
|
||||
let ticks=settings.tick_rate.num() as i128;
|
||||
let seconds=settings.tick_rate.den() as i128;
|
||||
let tick_number=(time*ticks/seconds) as u64;
|
||||
StrafeTickState{tick_number}
|
||||
}
|
||||
fn next_tick(&self,settings:&gameplay_style::StrafeSettings)->Time{
|
||||
let n=self.tick_number as i128;
|
||||
let ticks=settings.tick_rate.num() as i128;
|
||||
let seconds=settings.tick_rate.den() as i128;
|
||||
let time=n*seconds/ticks;
|
||||
Time::from_nanos(time as i64)
|
||||
}
|
||||
}
|
||||
#[derive(Clone,Debug)]
|
||||
enum MoveState{
|
||||
Air,
|
||||
Walk(ContactMoveState),
|
||||
@@ -578,7 +599,7 @@ impl MoveState{
|
||||
=>None,
|
||||
}
|
||||
}
|
||||
fn next_move_instruction(&self,strafe:&Option<gameplay_style::StrafeSettings>,time:Time)->Option<TimedInstruction<InternalInstruction,Time>>{
|
||||
fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,Time>>{
|
||||
//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{
|
||||
@@ -590,13 +611,7 @@ impl MoveState{
|
||||
|TransientAcceleration::Reached
|
||||
=>None,
|
||||
}
|
||||
MoveState::Air=>strafe.as_ref().map(|strafe|{
|
||||
TimedInstruction{
|
||||
time:strafe.next_tick(time),
|
||||
//only poll the physics if there is a before and after mouse event
|
||||
instruction:InternalInstruction::StrafeTick
|
||||
}
|
||||
}),
|
||||
MoveState::Air=>None,
|
||||
MoveState::Water=>None,//TODO
|
||||
MoveState::Fly=>None,
|
||||
}
|
||||
@@ -878,6 +893,7 @@ pub struct PhysicsState{
|
||||
//gameplay_state
|
||||
mode_state:ModeState,
|
||||
move_state:MoveState,
|
||||
strafe_tick_state:StrafeTickState,
|
||||
//run is non optional: when you spawn in a run is created
|
||||
//the run cannot be finished unless you start it by visiting
|
||||
//a start zone. If you change mode, a new run is created.
|
||||
@@ -896,6 +912,7 @@ impl Default for PhysicsState{
|
||||
input_state:InputState::default(),
|
||||
_world:WorldState{},
|
||||
mode_state:ModeState::default(),
|
||||
strafe_tick_state:StrafeTickState::new(Time::ZERO,&StyleModifiers::default().strafe.unwrap()),
|
||||
run:run::Run::new(),
|
||||
}
|
||||
}
|
||||
@@ -942,7 +959,7 @@ impl PhysicsState{
|
||||
*self=Self::default();
|
||||
}
|
||||
fn next_move_instruction(&self)->Option<TimedInstruction<InternalInstruction,Time>>{
|
||||
self.move_state.next_move_instruction(&self.style.strafe,self.time)
|
||||
self.move_state.next_move_instruction()
|
||||
}
|
||||
fn set_move_state(&mut self,data:&PhysicsData,move_state:MoveState){
|
||||
self.move_state.set_move_state(move_state,&mut self.body,&self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
|
||||
@@ -1200,8 +1217,18 @@ fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Ti
|
||||
//JUST POLLING!!! NO MUTATION
|
||||
let mut collector=instruction::InstructionCollector::new(time_limit);
|
||||
|
||||
// walking
|
||||
collector.collect(state.next_move_instruction());
|
||||
|
||||
// strafe tick
|
||||
collector.collect(state.style.strafe.as_ref().map(|strafe|{
|
||||
TimedInstruction{
|
||||
time:state.strafe_tick_state.next_tick(strafe),
|
||||
//only poll the physics if there is a before and after mouse event
|
||||
instruction:InternalInstruction::StrafeTick
|
||||
}
|
||||
}));
|
||||
|
||||
let trajectory=state.body.with_acceleration(state.acceleration(data));
|
||||
//check for collision ends
|
||||
state.touching.predict_collision_end(&mut collector,&data.models,&data.hitbox_mesh,&trajectory,state.time);
|
||||
@@ -1332,7 +1359,7 @@ fn set_velocity_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsM
|
||||
let mut culled=false;
|
||||
touching.contacts.retain(|convex_mesh_id,face_id|{
|
||||
let n=contact_normal(models,hitbox_mesh,convex_mesh_id,*face_id);
|
||||
let r=n.dot(v).is_positive();
|
||||
let r=(n.dot(v)>>52).is_positive();
|
||||
if r{
|
||||
culled=true;
|
||||
}
|
||||
@@ -1782,6 +1809,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
|
||||
),
|
||||
},
|
||||
InternalInstruction::StrafeTick=>{
|
||||
state.strafe_tick_state.tick_number+=1;
|
||||
//TODO make this less huge
|
||||
if let Some(strafe_settings)=&state.style.strafe{
|
||||
let controls=state.input_state.controls;
|
||||
|
||||
@@ -244,18 +244,18 @@ impl InstructionConsumer<Instruction<'_>> for Session{
|
||||
self.clear_recording();
|
||||
let mode_id=self.simulation.physics.mode();
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset));
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())));
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Restart(mode_id)));
|
||||
// TODO: think about this harder. This works around a bug where you fall infinitely when you reset.
|
||||
self.simulation.timer.set_time(ins.time,PhysicsTime::ZERO);
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())));
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Restart(mode_id)));
|
||||
},
|
||||
Instruction::Input(SessionInputInstruction::Mode(ImplicitModeInstruction::ResetAndSpawn(mode_id,spawn_id)))=>{
|
||||
self.clear_recording();
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Reset));
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())));
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id)));
|
||||
// TODO: think about this harder. This works around a bug where you fall infinitely when you reset.
|
||||
self.simulation.timer.set_time(ins.time,PhysicsTime::ZERO);
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(MiscInstruction::SetSensitivity(self.user_settings().calculate_sensitivity())));
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Mode(ModeInstruction::Spawn(mode_id,spawn_id)));
|
||||
},
|
||||
Instruction::Input(SessionInputInstruction::Misc(misc_instruction))=>{
|
||||
run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(misc_instruction));
|
||||
|
||||
@@ -111,3 +111,21 @@ fn bug_3(){
|
||||
assert_eq!(body.velocity,vec3::int(0,0,0));
|
||||
assert_eq!(body.time,Time::from_secs(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn press_w(){
|
||||
let physics_data=test_scene();
|
||||
let mut physics=PhysicsState::default();
|
||||
// press W
|
||||
PhysicsContext::run_input_instruction(&mut physics,&physics_data,strafesnet_common::instruction::TimedInstruction{
|
||||
time:Time::ZERO,
|
||||
instruction:strafesnet_common::physics::Instruction::SetControl(strafesnet_common::physics::SetControlInstruction::SetMoveForward(true)),
|
||||
});
|
||||
// wait 10 ms
|
||||
PhysicsContext::run_input_instruction(&mut physics,&physics_data,strafesnet_common::instruction::TimedInstruction{
|
||||
time:Time::from_millis(10),
|
||||
instruction:strafesnet_common::physics::Instruction::Idle,
|
||||
});
|
||||
// observe current velocity
|
||||
assert_eq!(physics.body().velocity,vec3::raw_xyz(0,-1<<32,-0x2b3333333));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ const VALVE_SCALE:Planar64=Planar64::raw(1<<28);// 1/16
|
||||
|
||||
use crate::integer::{int,vec3::int as int3,AbsoluteTime,Ratio64,Planar64,Planar64Vec3};
|
||||
use crate::controls_bitflag::Controls;
|
||||
use crate::physics::Time as PhysicsTime;
|
||||
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct StyleModifiers{
|
||||
@@ -273,9 +272,6 @@ impl StrafeSettings{
|
||||
false=>None,
|
||||
}
|
||||
}
|
||||
pub fn next_tick(&self,time:PhysicsTime)->PhysicsTime{
|
||||
PhysicsTime::from_nanos(self.tick_rate.rhs_div_int(self.tick_rate.mul_int(time.nanos())+1))
|
||||
}
|
||||
pub const fn activates(&self,controls:Controls)->bool{
|
||||
self.enable.activates(controls)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user