diff --git a/strafe-client/src/graphics_worker.rs b/strafe-client/src/graphics_worker.rs
index fda2810..76d6eca 100644
--- a/strafe-client/src/graphics_worker.rs
+++ b/strafe-client/src/graphics_worker.rs
@@ -14,13 +14,13 @@ WorkerDescription{
 */
 //up to three frames in flight, dropping new frame requests when all three are busy, and dropping output frames when one renders out of order
 
-pub fn new<'a>(
+pub fn new(
 	mut graphics:crate::graphics::GraphicsState,
 	mut config:wgpu::SurfaceConfiguration,
-	surface:wgpu::Surface<'a>,
+	surface:wgpu::Surface,
 	device:wgpu::Device,
 	queue:wgpu::Queue,
-)->crate::compat_worker::INWorker<'a,Instruction>{
+)->crate::compat_worker::INWorker<'_,Instruction>{
 	crate::compat_worker::INWorker::new(move |ins:Instruction|{
 		match ins{
 			Instruction::ChangeMap(map)=>{
diff --git a/strafe-client/src/physics_worker.rs b/strafe-client/src/physics_worker.rs
index 7d713bc..fcfd42e 100644
--- a/strafe-client/src/physics_worker.rs
+++ b/strafe-client/src/physics_worker.rs
@@ -1,39 +1,81 @@
 use crate::graphics_worker::Instruction as GraphicsInstruction;
 use crate::session::{ExternalInstruction as SessionInstruction,Session, Simulation};
+use strafesnet_common::instruction::{TimedInstruction,InstructionConsumer};
 use strafesnet_common::physics::Time as PhysicsTime;
 use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner};
 use strafesnet_common::timer::Timer;
 
-type TimedSessionInstruction=strafesnet_common::instruction::TimedInstruction<SessionInstruction,SessionTimeInner>;
+pub enum Instruction{
+	Input(strafesnet_common::physics::UnbufferedInstruction),
+	SetPaused(bool),
+	Render,
+	Resize(winit::dpi::PhysicalSize<u32>),
+	ChangeMap(strafesnet_common::map::CompleteMap),
+}
+
+const SESSION_INSTRUCTION_IDLE:SessionInstruction=SessionInstruction::Input(strafesnet_common::physics::UnbufferedInstruction::Other(strafesnet_common::physics::OtherInstruction::Idle));
 
 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,TimedSessionInstruction>{
+)->crate::compat_worker::QNWorker<'a,TimedInstruction<Instruction,SessionTimeInner>>{
 	let physics=crate::physics::PhysicsContext::default();
 	let timer=Timer::unpaused(SessionTime::ZERO,PhysicsTime::ZERO);
 	let simulation=Simulation::new(timer,physics);
-	let mouse_interpolator=crate::mouse_interpolator::MouseInterpolator::new();
 	let mut session=Session::new(
 		user_settings,
 		simulation,
 	);
-	crate::compat_worker::QNWorker::new(move |ins:TimedSessionInstruction|{
-		session.handle_instruction(&ins);
+	crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<Instruction,SessionTimeInner>|{
+		// excruciating pain
+		macro_rules! run_session_instruction{
+			($time:expr,$instruction:expr)=>{
+				session.process_instruction(TimedInstruction{
+					time:$time,
+					instruction:$instruction,
+				});
+			};
+		}
+		macro_rules! run_graphics_worker_instruction{
+			($instruction:expr)=>{
+				if let Some(instruction)=$instruction{
+					graphics_worker.send(instruction).unwrap();
+				}
+			};
+		}
 		match ins.instruction{
-			SessionInstruction::Render=>{
+			Instruction::Input(unbuffered_instruction)=>{
+				let ins_session=SessionInstruction::Input(unbuffered_instruction);
+				run_session_instruction!(ins.time,ins_session);
+				let ins_graphics=None;
+				run_graphics_worker_instruction!(ins_graphics);
+			},
+			Instruction::SetPaused(paused)=>{
+				let ins_session=SessionInstruction::SetPaused(paused);
+				run_session_instruction!(ins.time,ins_session);
+				let ins_graphics=None;
+				run_graphics_worker_instruction!(ins_graphics);
+			},
+			Instruction::Render=>{
+				let ins_session=SESSION_INSTRUCTION_IDLE;
+				run_session_instruction!(ins.time,ins_session);
 				let frame_state=session.get_frame_state(ins.time);
-				graphics_worker.send(GraphicsInstruction::Render(frame_state)).unwrap();
+				let ins_graphics=Some(GraphicsInstruction::Render(frame_state));
+				run_graphics_worker_instruction!(ins_graphics);
 			},
-			SessionInstruction::Resize(size)=>{
-				graphics_worker.send(GraphicsInstruction::Resize(size,session.user_settings().clone())).unwrap();
+			Instruction::Resize(physical_size)=>{
+				let ins_session=SESSION_INSTRUCTION_IDLE;
+				run_session_instruction!(ins.time,ins_session);
+				let user_settings=session.user_settings().clone();
+				let ins_graphics=Some(GraphicsInstruction::Resize(physical_size,user_settings));
+				run_graphics_worker_instruction!(ins_graphics);
 			},
-			SessionInstruction::ChangeMap(map)=>{
-				session.change_map(ins.time,&map);
-				graphics_worker.send(GraphicsInstruction::ChangeMap(map)).unwrap();
+			Instruction::ChangeMap(complete_map)=>{
+				let ins_session=SessionInstruction::ChangeMap(&complete_map);
+				run_session_instruction!(ins.time,ins_session);
+				let ins_graphics=Some(GraphicsInstruction::ChangeMap(complete_map));
+				run_graphics_worker_instruction!(ins_graphics);
 			},
-			SessionInstruction::Input(_)=>(),
-			SessionInstruction::SetPaused(_)=>(),
 		}
 	})
 }
diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs
index c530637..1490a28 100644
--- a/strafe-client/src/session.rs
+++ b/strafe-client/src/session.rs
@@ -6,13 +6,12 @@ use strafesnet_common::timer::{Scaled,Timer};
 use strafesnet_common::session::{TimeInner as SessionTimeInner,Time as SessionTime};
 
 use crate::mouse_interpolator::{MouseInterpolator,StepInstruction};
+use crate::settings::UserSettings;
 
-pub enum ExternalInstruction{
+pub enum ExternalInstruction<'a>{
 	Input(PhysicsUnbufferedInstruction),
 	SetPaused(bool),
-	Render,
-	Resize(winit::dpi::PhysicalSize<u32>),
-	ChangeMap(strafesnet_common::map::CompleteMap),
+	ChangeMap(&'a strafesnet_common::map::CompleteMap),
 	//Graphics(crate::graphics_worker::Instruction),
 }
 
@@ -36,6 +35,13 @@ impl Simulation{
 			physics,
 		}
 	}
+	pub fn get_frame_state(&self,time:SessionTime)->FrameState{
+		FrameState{
+			body:self.physics.camera_body(),
+			camera:self.physics.camera(),
+			time:self.timer.time(time),
+		}
+	}
 }
 
 pub struct Replay{
@@ -57,7 +63,7 @@ impl Replay{
 }
 
 pub struct Session{
-	user_settings:crate::settings::UserSettings,
+	user_settings:UserSettings,
 	mouse_interpolator:crate::mouse_interpolator::MouseInterpolator,
 	//gui:GuiState
 	simulation:Simulation,
@@ -65,7 +71,7 @@ pub struct Session{
 }
 impl Session{
 	pub fn new(
-		user_settings:crate::settings::UserSettings,
+		user_settings:UserSettings,
 		simulation:Simulation,
 	)->Self{
 		Self{
@@ -75,6 +81,15 @@ impl Session{
 			replays:Vec::new(),
 		}
 	}
+	fn change_map(&mut self,map:&strafesnet_common::map::CompleteMap){
+		self.simulation.physics.generate_models(map);
+	}
+	pub fn get_frame_state(&self,time:SessionTime)->FrameState{
+		self.simulation.get_frame_state(time)
+	}
+	pub fn user_settings(&self)->&UserSettings{
+		&self.user_settings
+	}
 }
 
 // mouseinterpolator consumes RawInputInstruction
@@ -84,7 +99,7 @@ impl Session{
 // Session consumes DoStep -> forwards DoStep to mouseinterpolator
 // Session emits DoStep
 
-impl InstructionConsumer<ExternalInstruction> for Session{
+impl InstructionConsumer<ExternalInstruction<'_>> for Session{
 	type TimeInner=SessionTimeInner;
 	fn process_instruction(&mut self,ins:TimedInstruction<ExternalInstruction,Self::TimeInner>){
 		match ins.instruction{
@@ -102,9 +117,7 @@ impl InstructionConsumer<ExternalInstruction> for Session{
 				// what if they pause for 5ms lmao
 				_=self.simulation.timer.set_paused(ins.time,paused);
 			}
-			ExternalInstruction::Render=>(),
-			ExternalInstruction::Resize(physical_size)=>(),
-			ExternalInstruction::ChangeMap(complete_map)=>(),
+			ExternalInstruction::ChangeMap(complete_map)=>self.change_map(complete_map),
 		};
 		// run all buffered instruction produced
 		self.process_exhaustive(ins.time);