diff --git a/strafe-client/src/physics.rs b/strafe-client/src/physics.rs index 956136f..d9be5dd 100644 --- a/strafe-client/src/physics.rs +++ b/strafe-client/src/physics.rs @@ -273,6 +273,15 @@ pub struct PhysicsCamera{ impl PhysicsCamera{ const ANGLE_PITCH_LOWER_LIMIT:Angle32=Angle32::NEG_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){ let mut unclamped_mouse_pos=self.clamped_mouse_pos+mouse_delta; unclamped_mouse_pos.y=unclamped_mouse_pos.y.clamp( diff --git a/strafe-client/src/physics_worker.rs b/strafe-client/src/physics_worker.rs index 2e62859..202516d 100644 --- a/strafe-client/src/physics_worker.rs +++ b/strafe-client/src/physics_worker.rs @@ -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{ //Instructions - timeline:std::collections::VecDeque>, + timelines:strafesnet_roblox_bot_file::v0::Block, //"Simulation" + event_id:usize, + offset:f64, timer:Timer, physics:crate::physics::PhysicsContext, } impl PlayBacker{ pub fn new( physics:crate::physics::PhysicsContext, - timeline:std::collections::VecDeque>, + timelines:strafesnet_roblox_bot_file::v0::Block, )->Self{ Self{ - timeline, + offset:timelines.output_events[0].time, + timelines, + event_id:0, timer:Timer::from_state(Scaled::identity(),false), 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){ //match the instruction so the playback is pausable :D match instruction{ @@ -251,22 +249,71 @@ impl PlayBacker{ }, _=>(), } - self.run(*time); - //idle the physics to allow any internal events to run (collisions mostly) - self.physics.run_input_instruction(TimedInstruction{ - time:self.timer.time(*time), - instruction:PhysicsInputInstruction::Idle, - }); + let simulation_time=self.timer.time(*time); + let time_float=simulation_time.get() as f64/Time::ONE_SECOND.get() as f64+self.offset; + while let Some(next_event)=self.timelines.output_events.get(self.event_id+1){ + //println!("{}<{}",next_event.time,time_float); + if next_event.time(crate::physics::PhysicsOutputState,Time,glam::IVec2){ - (self.physics.output(),self.timer.time(time),self.physics.get_next_mouse().pos) + pub fn get_frame_state(&self,time:Time)->crate::graphics::FrameState{ + 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{ //oof, settings ignored crate::settings::UserSettings::default() } pub fn change_map(&mut self,time:Time,map:&strafesnet_common::map::CompleteMap){ - self.run(time); self.physics.generate_models(&map); } } @@ -276,18 +323,12 @@ pub fn new<'a>( user_settings:crate::settings::UserSettings, )->crate::compat_worker::QNWorker<'a,TimedInstruction>{ let physics=crate::physics::PhysicsContext::default(); - /* - let mut interpolator=MouseInterpolator::new( - physics, - user_settings - ); - */ //load bot - let bot_file=std::fs::File::open(format!("/home/quat/strafesnet/strafe-client/tools/debug_bots/17cf70412eba16d172a67385cab5727e")).unwrap(); - let instructions=strafesnet_snf::bot::read_bot_debug(bot_file).unwrap(); + let file=std::fs::File::open("/home/quat/strafesnet/roblox_bot_file/files/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d").unwrap(); + let mut bot_file=strafesnet_roblox_bot_file::v0::File::new(std::io::BufReader::new(file)).unwrap(); let mut interpolator=PlayBacker::new( physics, - instructions.into(), + bot_file.read_all().unwrap(), ); crate::compat_worker::QNWorker::new(move |ins:TimedInstruction|{ interpolator.handle_instruction(&ins); @@ -297,7 +338,7 @@ pub fn new<'a>( graphics_worker.send(crate::graphics_worker::Instruction::Render(frame_state)).unwrap(); }, 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)=>{ interpolator.change_map(ins.time,&map);