diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs
index 716c12b..0720ffa 100644
--- a/strafe-client/src/session.rs
+++ b/strafe-client/src/session.rs
@@ -466,4 +466,48 @@ mod test{
 			}
 		}
 	}
+	#[test]
+	fn test_determinism(){
+		let map=file::load("bhop_maps/5692113331.snfm");
+		let bot=file::load("replays/703s+098360278ns.snfb");
+		if let (Ok(file::Format2::Map(map)),Ok(file::Format2::Bot(bot)))=(map,bot){
+
+			// create default physics state
+			let mut physics_deterministic=physics::PhysicsState::default();
+			// create a second physics state
+			let mut physics_filtered=physics::PhysicsState::default();
+
+			// invent a new bot id and insert the replay
+			let mut physics_data=physics::PhysicsData::default();
+			println!("loading map..");
+			physics_data.generate_models(&map);
+			println!("simulating...");
+
+			for (i,ins) in bot.instructions.into_iter().enumerate(){
+				physics::PhysicsContext::run_input_instruction(&mut physics_deterministic,&physics_data,ins.clone());
+				match ins{
+					strafesnet_common::instruction::TimedInstruction{instruction:strafesnet_common::physics::Instruction::Idle,..}=>(),
+					other=>{
+						// run
+						physics::PhysicsContext::run_input_instruction(&mut physics_filtered,&physics_data,other);
+						// check if position matches
+						let b0=physics_deterministic.camera_body();
+						let b1=physics_filtered.camera_body();
+						if b0.position==b1.position{
+							println!("desync at instruction #{}",i);
+							panic!("oh no bro");
+						}
+					},
+				}
+			}
+			match physics_deterministic.get_finish_time(){
+				Some(time)=>println!("[with idle] finish time:{}",time),
+				None=>println!("[with idle] simulation did not end in finished state"),
+			}
+			match physics_filtered.get_finish_time(){
+				Some(time)=>println!("[filtered] finish time:{}",time),
+				None=>println!("[filtered] simulation did not end in finished state"),
+			}
+		}
+	}
 }