diff --git a/strafe-client/src/mouse_interpolator.rs b/strafe-client/src/mouse_interpolator.rs
index d5fd15b..0c61089 100644
--- a/strafe-client/src/mouse_interpolator.rs
+++ b/strafe-client/src/mouse_interpolator.rs
@@ -36,7 +36,8 @@ enum BufferState{
 pub struct MouseInterpolator{
 	buffer_state:BufferState,
 	// double timestamped timeline?
-	physics_timeline:std::collections::VecDeque<TimedPhysicsInstruction>,
+	buffer:std::collections::VecDeque<TimedPhysicsInstruction>,
+	output:std::collections::VecDeque<TimedPhysicsInstruction>,
 }
 // Maybe MouseInterpolator manipulation is better expressed using impls
 // and called from Instruction trait impls in session
@@ -56,7 +57,22 @@ impl MouseInterpolator{
 	pub fn new()->MouseInterpolator{
 		MouseInterpolator{
 			buffer_state:BufferState::Unbuffered,
-			physics_timeline:std::collections::VecDeque::new(),
+			buffer:std::collections::VecDeque::new(),
+			output:std::collections::VecDeque::new(),
+		}
+	}
+	fn push_mouse(&mut self,ins:TimedInstruction<MouseInstruction,PhysicsTimeInner>){
+		self.buffer.push_front(TimedInstruction{
+			time:ins.time,
+			instruction:PhysicsInputInstruction::Mouse(ins.instruction),
+		});
+		// flush buffer to output
+		if self.output.len()==0{
+			// swap buffers
+			core::mem::swap(&mut self.buffer,&mut self.output);
+		}else{
+			// append buffer contents to output
+			self.output.append(&mut self.buffer);
 		}
 	}
 	pub fn push_unbuffered_input(&mut self,ins:DoubleTimedUnbufferedInstruction){
@@ -140,27 +156,26 @@ impl MouseInterpolator{
 			((None,ins_other),next_state)
 		});
 		if let Some(ins)=ins_mouse{
-			self.physics_timeline.push_front(TimedInstruction{
-				time:ins.time,
-				instruction:PhysicsInputInstruction::Mouse(ins.instruction),
-			});
+			self.push_mouse(ins);
 		}
 		if let Some(ins)=ins_other{
-			self.physics_timeline.push_back(TimedInstruction{
+			let instruction=TimedInstruction{
 				time:ins.time,
 				instruction:PhysicsInputInstruction::Other(ins.instruction),
-			});
+			};
+			if matches!(self.buffer_state,BufferState::Unbuffered){
+				self.output.push_back(instruction);
+			}else{
+				self.buffer.push_back(instruction);
+			}
 		}
 	}
-	fn is_first_ready(&self)->bool{
-		matches!(self.physics_timeline.back(),Some(TimedInstruction{
-			instruction:PhysicsInputInstruction::Mouse(_),
-			..
-		}))
+	fn has_output(&self)->bool{
+		self.output.len()!=0
 	}
 	pub fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option<TimedInstruction<StepInstruction,SessionTimeInner>>{
 		match &self.buffer_state{
-			BufferState::Unbuffered=>self.physics_timeline.front().map(|_|TimedInstruction{
+			BufferState::Unbuffered=>self.has_output().then_some(TimedInstruction{
 				time:time_limit,
 				instruction:StepInstruction::Pop,
 			}),
@@ -173,7 +188,7 @@ impl MouseInterpolator{
 						time:timeout,
 						instruction:StepInstruction::Timeout,
 					})
-				}else if self.is_first_ready(){
+				}else if self.has_output(){
 					// emit Step
 					Some(TimedInstruction{
 						// this timestamp should not matter
@@ -191,31 +206,30 @@ impl MouseInterpolator{
 	pub fn pop_buffered_instruction(&mut self,ins:StepInstruction)->Option<TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>>{
 		match ins{
 			// could check if self.is_first_ready()
-			StepInstruction::Pop=>self.physics_timeline.pop_front(),
+			StepInstruction::Pop=>(),
 			StepInstruction::Timeout=>{
 				let buffer_state=core::mem::replace(&mut self.buffer_state,BufferState::Unbuffered);
 				match buffer_state{
-					BufferState::Unbuffered=>None,
+					BufferState::Unbuffered=>(),
 					BufferState::Initializing(_time,mouse_state)
 					|BufferState::Buffered(_time,mouse_state)=>{
 						// convert to BufferState::Unbuffered
 						// use the first instruction which should be a mouse instruction
 						// to push a ReplaceMouse instruction
 						// duplicate the current mouse
-						Some(TimedInstruction{
+						self.push_mouse(TimedInstruction{
 							// This should be simulation_timer.time(timeout)
 							// but the timer is not accessible from this scope
 							// and it's just here to say that the mouse isn't moving anyways.
 							// I think this is a divide by zero bug, two identical mouse_states will occupy the interpolation state
 							time:mouse_state.time,
-							instruction:PhysicsInputInstruction::Mouse(
-								MouseInstruction::SetNextMouse(mouse_state)
-							),
-						})
+							instruction:MouseInstruction::SetNextMouse(mouse_state),
+						});
 					},
 				}
 			},
 		}
+		self.output.pop_front()
 	}
 }