working playback

This commit is contained in:
Quaternions 2024-12-31 21:20:26 -08:00
parent 904338d7c6
commit d04a5e4625
2 changed files with 85 additions and 35 deletions

View File

@ -273,6 +273,15 @@ pub struct PhysicsCamera{
impl PhysicsCamera{ impl PhysicsCamera{
const ANGLE_PITCH_LOWER_LIMIT:Angle32=Angle32::NEG_FRAC_PI_2; const ANGLE_PITCH_LOWER_LIMIT:Angle32=Angle32::NEG_FRAC_PI_2;
const ANGLE_PITCH_UPPER_LIMIT:Angle32=Angle32::FRAC_PI_2; const ANGLE_PITCH_UPPER_LIMIT:Angle32=Angle32::FRAC_PI_2;
pub fn new(
sensitivity:Ratio64Vec2,
clamped_mouse_pos:glam::IVec2,
)->Self{
Self{
sensitivity,
clamped_mouse_pos,
}
}
pub fn move_mouse(&mut self,mouse_delta:glam::IVec2){ pub fn move_mouse(&mut self,mouse_delta:glam::IVec2){
let mut unclamped_mouse_pos=self.clamped_mouse_pos+mouse_delta; let mut unclamped_mouse_pos=self.clamped_mouse_pos+mouse_delta;
unclamped_mouse_pos.y=unclamped_mouse_pos.y.clamp( unclamped_mouse_pos.y=unclamped_mouse_pos.y.clamp(

View File

@ -212,37 +212,35 @@ impl MouseInterpolator{
} }
} }
fn vector3_to_glam(v:&strafesnet_roblox_bot_file::v0::Vector3)->glam::Vec3{
glam::vec3(v.x,v.y,v.z)
}
fn f32_to_p64(f:f32)->strafesnet_common::integer::Planar64{
f.try_into().unwrap_or(strafesnet_common::integer::Planar64::ZERO)
}
struct PlayBacker{ struct PlayBacker{
//Instructions //Instructions
timeline:std::collections::VecDeque<TimedInstruction<PhysicsInputInstruction>>, timelines:strafesnet_roblox_bot_file::v0::Block,
//"Simulation" //"Simulation"
event_id:usize,
offset:f64,
timer:Timer<Scaled>, timer:Timer<Scaled>,
physics:crate::physics::PhysicsContext, physics:crate::physics::PhysicsContext,
} }
impl PlayBacker{ impl PlayBacker{
pub fn new( pub fn new(
physics:crate::physics::PhysicsContext, physics:crate::physics::PhysicsContext,
timeline:std::collections::VecDeque<TimedInstruction<PhysicsInputInstruction>>, timelines:strafesnet_roblox_bot_file::v0::Block,
)->Self{ )->Self{
Self{ Self{
timeline, offset:timelines.output_events[0].time,
timelines,
event_id:0,
timer:Timer::from_state(Scaled::identity(),false), timer:Timer::from_state(Scaled::identity(),false),
physics, physics,
} }
} }
fn run(&mut self,time:Time){
//all this does is advance the simulation to the instruction's timestamp
let simulation_time=self.timer.time(time);
while let Some(ins)=self.timeline.get(0){
if ins.time<simulation_time{
//run that sucker
let ins=self.timeline.pop_front().unwrap();
self.physics.run_input_instruction(ins);
}else{
break;
}
}
}
pub fn handle_instruction(&mut self,TimedInstruction{time,instruction}:&TimedInstruction<Instruction>){ pub fn handle_instruction(&mut self,TimedInstruction{time,instruction}:&TimedInstruction<Instruction>){
//match the instruction so the playback is pausable :D //match the instruction so the playback is pausable :D
match instruction{ match instruction{
@ -251,22 +249,71 @@ impl PlayBacker{
}, },
_=>(), _=>(),
} }
self.run(*time); let simulation_time=self.timer.time(*time);
//idle the physics to allow any internal events to run (collisions mostly) let time_float=simulation_time.get() as f64/Time::ONE_SECOND.get() as f64+self.offset;
self.physics.run_input_instruction(TimedInstruction{ while let Some(next_event)=self.timelines.output_events.get(self.event_id+1){
time:self.timer.time(*time), //println!("{}<{}",next_event.time,time_float);
instruction:PhysicsInputInstruction::Idle, if next_event.time<time_float{
}); self.event_id+=1;
println!("event_id={}",self.event_id);
}else{
break;
}
}
} }
pub fn get_render_stuff(&self,time:Time)->(crate::physics::PhysicsOutputState,Time,glam::IVec2){ pub fn get_frame_state(&self,time:Time)->crate::graphics::FrameState{
(self.physics.output(),self.timer.time(time),self.physics.get_next_mouse().pos) let time=self.timer.time(time);
let event0=&self.timelines.output_events[self.event_id];
let event1=&self.timelines.output_events[self.event_id+1];
let p0=vector3_to_glam(&event0.event.position);
let p1=vector3_to_glam(&event1.event.position);
let v0=vector3_to_glam(&event0.event.velocity);
let v1=vector3_to_glam(&event1.event.velocity);
let a0=vector3_to_glam(&event0.event.acceleration);
let a1=vector3_to_glam(&event1.event.acceleration);
let t0=event0.time;
let t1=event1.time;
let time_float=time.get() as f64/Time::ONE_SECOND.get() as f64;
let t=((time_float+self.offset-t0)/(t1-t0)) as f32;
let p=p0.lerp(p1,t).to_array().map(f32_to_p64);
let v=v0.lerp(v1,t).to_array().map(f32_to_p64);
let a=a0.lerp(a1,t).to_array().map(f32_to_p64);
//println!("position={:?}",p);
let angles0=vector3_to_glam(&event0.event.angles);
let angles1=vector3_to_glam(&event1.event.angles);
let angles=angles0.lerp(angles1,t);
// mask mantissa out and set it to minimum value
// let ax_epsilon=f32::from_bits(angles.x.to_bits()&!((1<<23)-1)|1);
// let ay_epsilon=f32::from_bits(angles.y.to_bits()&!((1<<23)-1)|1);
let body=crate::physics::Body{
time,
position:strafesnet_common::integer::Planar64Vec3::new(p),
velocity:strafesnet_common::integer::Planar64Vec3::new(v),
acceleration:strafesnet_common::integer::Planar64Vec3::new(a),
};
const FLOAT64_TO_ANGLE32_RADIANS:f64=((1i64<<31) as f64)/std::f64::consts::PI;
// xy is reversed in strafe client for some reason
let (ax,ay)=(
-angles.y as f64*FLOAT64_TO_ANGLE32_RADIANS,
-angles.x as f64*FLOAT64_TO_ANGLE32_RADIANS,
);
let camera=crate::physics::PhysicsCamera::new(
strafesnet_common::integer::Ratio64Vec2::new(1.0f32.try_into().unwrap(),1.0f32.try_into().unwrap()),
glam::ivec2(ax as i64 as i32,ay as i64 as i32)
);
crate::graphics::FrameState{
body,
camera,
time,
}
} }
pub fn user_settings(&self)->crate::settings::UserSettings{ pub fn user_settings(&self)->crate::settings::UserSettings{
//oof, settings ignored //oof, settings ignored
crate::settings::UserSettings::default() crate::settings::UserSettings::default()
} }
pub fn change_map(&mut self,time:Time,map:&strafesnet_common::map::CompleteMap){ pub fn change_map(&mut self,time:Time,map:&strafesnet_common::map::CompleteMap){
self.run(time);
self.physics.generate_models(&map); self.physics.generate_models(&map);
} }
} }
@ -276,18 +323,12 @@ pub fn new<'a>(
user_settings:crate::settings::UserSettings, user_settings:crate::settings::UserSettings,
)->crate::compat_worker::QNWorker<'a,TimedInstruction<Instruction>>{ )->crate::compat_worker::QNWorker<'a,TimedInstruction<Instruction>>{
let physics=crate::physics::PhysicsContext::default(); let physics=crate::physics::PhysicsContext::default();
/*
let mut interpolator=MouseInterpolator::new(
physics,
user_settings
);
*/
//load bot //load bot
let bot_file=std::fs::File::open(format!("/home/quat/strafesnet/strafe-client/tools/debug_bots/17cf70412eba16d172a67385cab5727e")).unwrap(); let file=std::fs::File::open("/home/quat/strafesnet/roblox_bot_file/files/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d").unwrap();
let instructions=strafesnet_snf::bot::read_bot_debug(bot_file).unwrap(); let mut bot_file=strafesnet_roblox_bot_file::v0::File::new(std::io::BufReader::new(file)).unwrap();
let mut interpolator=PlayBacker::new( let mut interpolator=PlayBacker::new(
physics, physics,
instructions.into(), bot_file.read_all().unwrap(),
); );
crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<Instruction>|{ crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<Instruction>|{
interpolator.handle_instruction(&ins); interpolator.handle_instruction(&ins);
@ -297,7 +338,7 @@ pub fn new<'a>(
graphics_worker.send(crate::graphics_worker::Instruction::Render(frame_state)).unwrap(); graphics_worker.send(crate::graphics_worker::Instruction::Render(frame_state)).unwrap();
}, },
Instruction::Resize(size)=>{ Instruction::Resize(size)=>{
graphics_worker.send(crate::graphics_worker::Instruction::Resize(size,interpolator.user_settings().clone())).unwrap(); graphics_worker.send(crate::graphics_worker::Instruction::Resize(size,interpolator.user_settings())).unwrap();
}, },
Instruction::ChangeMap(map)=>{ Instruction::ChangeMap(map)=>{
interpolator.change_map(ins.time,&map); interpolator.change_map(ins.time,&map);