From c0d543301e9c3b44bbcfdcf4df58ef9038d6bbb7 Mon Sep 17 00:00:00 2001
From: Quaternions <krakow20@gmail.com>
Date: Tue, 6 Aug 2024 12:52:35 -0700
Subject: [PATCH] bot player

---
 src/physics_worker.rs | 68 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/src/physics_worker.rs b/src/physics_worker.rs
index 0a1aec3..d9d269d 100644
--- a/src/physics_worker.rs
+++ b/src/physics_worker.rs
@@ -208,15 +208,83 @@ impl MouseInterpolator{
 }
 }
 
+struct PlayBacker{
+	//Instructions
+	timeline:std::collections::VecDeque<TimedInstruction<PhysicsInputInstruction>>,
+	//"Simulation"
+	timer:Timer<Scaled>,
+	physics:crate::physics::PhysicsContext,
+}
+impl PlayBacker{
+	pub fn new(
+		physics:crate::physics::PhysicsContext,
+		timeline:std::collections::VecDeque<TimedInstruction<PhysicsInputInstruction>>,
+	)->Self{
+		Self{
+			timeline,
+			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<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>){
+		//match the instruction so the playback is pausable :D
+		match instruction{
+			&Instruction::SetPaused(paused)=>{
+				let _=self.timer.set_paused(*time,paused);
+			},
+			_=>(),
+		}
+		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,
+		});
+	}
+	pub fn get_render_stuff(&self,time:Time)->(crate::physics::PhysicsOutputState,Time,glam::IVec2){
+		(self.physics.output(),self.timer.time(time),self.physics.get_next_mouse().pos)
+	}
+	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);
+	}
+}
+
 pub fn new<'a>(
 	mut graphics_worker:crate::compat_worker::INWorker<'a,crate::graphics_worker::Instruction>,
 	user_settings:crate::settings::UserSettings,
 )->crate::compat_worker::QNWorker<'a,TimedInstruction<Instruction>>{
 	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 mut interpolator=PlayBacker::new(
+		physics,
+		instructions.into(),
+	);
 	crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<Instruction>|{
 		interpolator.handle_instruction(&ins);
 		match ins.instruction{