Compare commits

...

5 Commits

Author SHA1 Message Date
81eca26125 minimize diff 2026-02-04 10:35:08 -08:00
88921157a7 no option 2026-02-04 10:33:33 -08:00
9ec3f7c474 put it in PhysicsState 2026-02-04 10:24:57 -08:00
ed7d6acd36 add StrafeTickState to allow 0 time strafe events 2026-02-04 10:19:50 -08:00
b7e8fb6e18 simplify adapter selection with iterators 2026-02-03 10:13:46 -08:00
3 changed files with 38 additions and 31 deletions

View File

@@ -495,6 +495,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),
@@ -572,7 +593,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,strafe:Option<&gameplay_style::StrafeSettings>,strafe_tick_state:&StrafeTickState)->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{
@@ -586,7 +607,7 @@ impl MoveState{
}
MoveState::Air=>strafe.as_ref().map(|strafe|{
TimedInstruction{
time:strafe.next_tick(time),
time:strafe_tick_state.next_tick(strafe),
//only poll the physics if there is a before and after mouse event
instruction:InternalInstruction::StrafeTick
}
@@ -871,6 +892,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.
@@ -889,6 +911,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(),
}
}
@@ -935,7 +958,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(self.style.strafe.as_ref(),&self.strafe_tick_state)
}
fn cull_velocity(&mut self,data:&PhysicsData,velocity:Planar64Vec3){
self.move_state.cull_velocity(velocity,&mut self.body,&mut self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
@@ -1793,6 +1816,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;

View File

@@ -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)
}

View File

@@ -45,8 +45,6 @@ struct SetupContextPartial2<'a>{
}
impl<'a> SetupContextPartial2<'a>{
fn pick_adapter(self)->SetupContextPartial3<'a>{
let adapter;
//TODO: prefer adapter that implements optional features
//let optional_features=optional_features();
let required_features=required_features();
@@ -54,33 +52,22 @@ impl<'a> SetupContextPartial2<'a>{
//no helper function smh gotta write it myself
let adapters=pollster::block_on(self.instance.enumerate_adapters(self.backends));
let mut chosen_adapter=None;
let mut chosen_adapter_score=0;
for adapter in adapters {
if !adapter.is_surface_supported(&self.surface) {
continue;
}
let score=match adapter.get_info().device_type{
let chosen_adapter=adapters.into_iter()
// reverse because we want to select adapters that appear first in ties,
// and max_by_key selects the last equal element in the iterator.
.rev()
.filter(|adapter|
adapter.is_surface_supported(&self.surface)
&&adapter.features().contains(required_features)
)
.max_by_key(|adapter|match adapter.get_info().device_type{
wgpu::DeviceType::IntegratedGpu=>3,
wgpu::DeviceType::DiscreteGpu=>4,
wgpu::DeviceType::VirtualGpu=>2,
wgpu::DeviceType::Other|wgpu::DeviceType::Cpu=>1,
};
let adapter_features=adapter.features();
if chosen_adapter_score<score&&adapter_features.contains(required_features) {
chosen_adapter_score=score;
chosen_adapter=Some(adapter);
}
}
if let Some(maybe_chosen_adapter)=chosen_adapter{
adapter=maybe_chosen_adapter;
}else{
panic!("No suitable GPU adapters found on the system!");
}
});
let adapter=chosen_adapter.expect("No suitable GPU adapters found on the system!");
let adapter_info=adapter.get_info();
println!("Using {} ({:?})", adapter_info.name, adapter_info.backend);