diff --git a/strafe-client/src/physics.rs b/strafe-client/src/physics.rs
index f061b7b..6a4c0ec 100644
--- a/strafe-client/src/physics.rs
+++ b/strafe-client/src/physics.rs
@@ -28,9 +28,9 @@ use gameplay::ModeState;
 // or the only bots which fail are ones exploiting a surgically patched bug.
 #[derive(Clone,Copy,Hash,Debug,id::Id,Eq,PartialEq,Ord,PartialOrd)]
 pub struct PhysicsVersion(u32);
-pub const VERSION:PhysicsVersion=PhysicsVersion(0);
+pub const VERSION:PhysicsVersion=PhysicsVersion(1);
 const LATEST_COMPATIBLE_VERSION:[u32;1+VERSION.0 as usize]=const{
-	let compat=[0];
+	let compat=[0,1];
 
 	let mut input_version=0;
 	while input_version<compat.len(){
@@ -200,17 +200,17 @@ fn ground_things(walk_settings:&gameplay_style::WalkSettings,contact:&ContactCol
 	let normal=contact_normal(models,hitbox_mesh,contact);
 	let gravity=touching.base_acceleration(models,style,camera,input_state);
 	let control_dir=style.get_y_control_dir(camera,input_state.controls);
-	let mut target_velocity=walk_settings.get_walk_target_velocity(control_dir,normal);
-	touching.constrain_velocity(models,hitbox_mesh,&mut target_velocity);
-	(gravity,target_velocity)
+	let target_velocity=walk_settings.get_walk_target_velocity(control_dir,normal);
+	let target_velocity_clipped=touching.constrain_velocity(models,hitbox_mesh,target_velocity);
+	(gravity,target_velocity_clipped)
 }
 fn ladder_things(ladder_settings:&gameplay_style::LadderSettings,contact:&ContactCollision,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState)->(Planar64Vec3,Planar64Vec3){
 	let normal=contact_normal(models,hitbox_mesh,contact);
 	let gravity=touching.base_acceleration(models,style,camera,input_state);
 	let control_dir=style.get_y_control_dir(camera,input_state.controls);
-	let mut target_velocity=ladder_settings.get_ladder_target_velocity(control_dir,normal);
-	touching.constrain_velocity(models,hitbox_mesh,&mut target_velocity);
-	(gravity,target_velocity)
+	let target_velocity=ladder_settings.get_ladder_target_velocity(control_dir,normal);
+	let target_velocity_clipped=touching.constrain_velocity(models,hitbox_mesh,target_velocity);
+	(gravity,target_velocity_clipped)
 }
 
 #[derive(Default)]
@@ -534,20 +534,20 @@ enum MoveState{
 }
 impl MoveState{
 	//call this after state.move_state is changed
-	fn apply_enum(&self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
+	fn apply_enum(&self,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
 		match self{
 			MoveState::Fly=>body.acceleration=vec3::ZERO,
 			MoveState::Air=>{
 				//calculate base acceleration
 				let a=touching.base_acceleration(models,style,camera,input_state);
 				//set_acceleration clips according to contacts
-				set_acceleration(body,touching,models,hitbox_mesh,a);
+				set_acceleration_cull(body,touching,models,hitbox_mesh,a);
 			},
 			_=>(),
 		}
 	}
 	//function to coerce &mut self into &self
-	fn apply_to_body(&self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
+	fn apply_to_body(&self,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
 		match self{
 			MoveState::Air=>(),
 			MoveState::Water=>(),
@@ -555,14 +555,14 @@ impl MoveState{
 				//set velocity according to current control state
 				let v=style.get_propulsion_control_dir(camera,input_state.controls)*80;
 				//set_velocity clips velocity according to current touching state
-				set_velocity(body,touching,models,hitbox_mesh,v);
+				set_velocity_cull(body,touching,models,hitbox_mesh,v);
 			},
 			MoveState::Walk(walk_state)
 			|MoveState::Ladder(walk_state)
 			=>{
 				//accelerate towards walk target or do nothing
 				let a=walk_state.target.acceleration();
-				set_acceleration(body,touching,models,hitbox_mesh,a);
+				set_acceleration_cull(body,touching,models,hitbox_mesh,a);
 			},
 		}
 	}
@@ -625,20 +625,20 @@ impl MoveState{
 		}
 	}
 	//lmao idk this is convenient
-	fn apply_enum_and_input_and_body(&mut self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
+	fn apply_enum_and_input_and_body(&mut self,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
 		self.apply_enum(body,touching,models,hitbox_mesh,style,camera,input_state);
 		self.apply_input(body,touching,models,hitbox_mesh,style,camera,input_state);
 		self.apply_to_body(body,touching,models,hitbox_mesh,style,camera,input_state);
 	}
-	fn apply_enum_and_body(&mut self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
+	fn apply_enum_and_body(&mut self,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
 		self.apply_enum(body,touching,models,hitbox_mesh,style,camera,input_state);
 		self.apply_to_body(body,touching,models,hitbox_mesh,style,camera,input_state);
 	}
-	fn apply_input_and_body(&mut self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
+	fn apply_input_and_body(&mut self,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
 		self.apply_input(body,touching,models,hitbox_mesh,style,camera,input_state);
 		self.apply_to_body(body,touching,models,hitbox_mesh,style,camera,input_state);
 	}
-	fn set_move_state(&mut self,move_state:MoveState,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
+	fn set_move_state(&mut self,move_state:MoveState,body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){
 		*self=move_state;
 		//this function call reads the above state that was just set
 		self.apply_enum_and_body(body,touching,models,hitbox_mesh,style,camera,input_state);
@@ -807,7 +807,7 @@ impl TouchingState{
 		//TODO: add water
 		a
 	}
-	fn constrain_velocity(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,velocity:&mut Planar64Vec3){
+	fn constrain_velocity(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,velocity:Planar64Vec3)->Planar64Vec3{
 		let contacts=self.contacts.iter().map(|contact|{
 			let n=contact_normal(models,hitbox_mesh,contact);
 			crate::push_solve::Contact{
@@ -816,9 +816,9 @@ impl TouchingState{
 				normal:n,
 			}
 		}).collect();
-		*velocity=crate::push_solve::push_solve(&contacts,*velocity);
+		crate::push_solve::push_solve(&contacts,velocity)
 	}
-	fn constrain_acceleration(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,acceleration:&mut Planar64Vec3){
+	fn constrain_acceleration(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,acceleration:Planar64Vec3)->Planar64Vec3{
 		let contacts=self.contacts.iter().map(|contact|{
 			let n=contact_normal(models,hitbox_mesh,contact);
 			crate::push_solve::Contact{
@@ -827,7 +827,7 @@ impl TouchingState{
 				normal:n,
 			}
 		}).collect();
-		*acceleration=crate::push_solve::push_solve(&contacts,*acceleration);
+		crate::push_solve::push_solve(&contacts,acceleration)
 	}
 	fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<InternalInstruction,TimeInner>,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,start_time:Time){
 		// let relative_body=crate::body::VirtualBody::relative(&Body::ZERO,body).body(time);
@@ -930,10 +930,10 @@ impl PhysicsState{
 		self.move_state.cull_velocity(velocity,&mut self.body,&mut self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
 	}
 	fn set_move_state(&mut self,data:&PhysicsData,move_state:MoveState){
-		self.move_state.set_move_state(move_state,&mut self.body,&self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
+		self.move_state.set_move_state(move_state,&mut self.body,&mut self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
 	}
 	fn apply_input_and_body(&mut self,data:&PhysicsData){
-		self.move_state.apply_input_and_body(&mut self.body,&self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
+		self.move_state.apply_input_and_body(&mut self.body,&mut self.touching,&data.models,&data.hitbox_mesh,&self.style,&self.camera,&self.input_state);
 	}
 	//state mutated on collision:
 	//Accelerator
@@ -1294,7 +1294,7 @@ fn set_velocity_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsM
 	let mut culled=false;
 	touching.contacts.retain(|contact|{
 		let n=contact_normal(models,hitbox_mesh,contact);
-		let r=n.dot(v).is_positive();
+		let r=(n.dot(v)>>52).is_positive();
 		if r{
 			culled=true;
 		}
@@ -1303,9 +1303,8 @@ fn set_velocity_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsM
 	set_velocity(body,touching,models,hitbox_mesh,v);
 	culled
 }
-fn set_velocity(body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,mut v:Planar64Vec3){
-	touching.constrain_velocity(models,hitbox_mesh,&mut v);
-	body.velocity=v;
+fn set_velocity(body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,v:Planar64Vec3){
+	body.velocity=touching.constrain_velocity(models,hitbox_mesh,v);;
 }
 fn set_acceleration_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,a:Planar64Vec3)->bool{
 	//This is not correct but is better than what I have
@@ -1321,9 +1320,8 @@ fn set_acceleration_cull(body:&mut Body,touching:&mut TouchingState,models:&Phys
 	set_acceleration(body,touching,models,hitbox_mesh,a);
 	culled
 }
-fn set_acceleration(body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,mut a:Planar64Vec3){
-	touching.constrain_acceleration(models,hitbox_mesh,&mut a);
-	body.acceleration=a;
+fn set_acceleration(body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,a:Planar64Vec3){
+	body.acceleration=touching.constrain_acceleration(models,hitbox_mesh,a);
 }
 
 fn teleport(
@@ -1343,7 +1341,7 @@ fn teleport(
 	time:Time,
 ){
 	set_position(point,move_state,body,touching,run,mode_state,mode,models,hitbox_mesh,bvh,style,camera,input_state,time);
-	set_acceleration(body,touching,models,hitbox_mesh,style.gravity);
+	set_acceleration_cull(body,touching,models,hitbox_mesh,style.gravity);
 }
 enum TeleportToSpawnError{
 	NoModel,
@@ -1524,10 +1522,7 @@ fn collision_start_contact(
 	time:Time,
 ){
 	let incident_velocity=body.velocity;
-	//add to touching
-	touching.insert(Collision::Contact(contact));
-	//clip v
-	set_velocity(body,touching,models,hitbox_mesh,incident_velocity);
+	let clipped_velocity=touching.constrain_velocity(models,hitbox_mesh,incident_velocity);
 	let mut allow_jump=true;
 	let model_id=contact.model_id.into();
 	let mut allow_run_teleport_behaviour=not_spawn_at(mode,model_id);
@@ -1535,7 +1530,7 @@ fn collision_start_contact(
 		Some(gameplay_attributes::ContactingBehaviour::Surf)=>(),
 		Some(gameplay_attributes::ContactingBehaviour::Cling)=>println!("Unimplemented!"),
 		&Some(gameplay_attributes::ContactingBehaviour::Elastic(elasticity))=>{
-			let reflected_velocity=body.velocity+((body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).fix_1();
+			let reflected_velocity=body.velocity+((clipped_velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).fix_1();
 			set_velocity(body,touching,models,hitbox_mesh,reflected_velocity);
 		},
 		Some(gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder))=>
@@ -1845,7 +1840,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
 					let jump_dir=walk_state.jump_direction.direction(&data.models,&data.hitbox_mesh,&walk_state.contact);
 					let booster_option=data.models.contact_attr(walk_state.contact.model_id).general.booster.as_ref();
 					let jumped_velocity=jump_settings.jumped_velocity(&state.style,jump_dir,state.body.velocity,booster_option);
-					state.cull_velocity(&data,jumped_velocity);
+					state.cull_velocity(data,jumped_velocity);
 				}
 			}
 			b_refresh_walk_target=false;