diff --git a/src/lib.rs b/src/lib.rs
index ff3601a..a5a0f17 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,9 +3,11 @@ pub mod map;
 pub mod run;
 pub mod aabb;
 pub mod model;
+pub mod mouse;
 pub mod timer;
 pub mod zeroes;
 pub mod integer;
+pub mod physics;
 pub mod updatable;
 pub mod instruction;
 pub mod gameplay_attributes;
diff --git a/src/mouse.rs b/src/mouse.rs
new file mode 100644
index 0000000..c3795de
--- /dev/null
+++ b/src/mouse.rs
@@ -0,0 +1,26 @@
+use crate::integer::Time;
+
+#[derive(Clone,Debug)]
+pub struct MouseState{
+	pub pos:glam::IVec2,
+	pub time:Time,
+}
+impl Default for MouseState{
+	fn default()->Self{
+		Self{
+			time:Time::ZERO,
+			pos:glam::IVec2::ZERO,
+		}
+	}
+}
+impl MouseState{
+	pub fn lerp(&self,target:&MouseState,time:Time)->glam::IVec2{
+		let m0=self.pos.as_i64vec2();
+		let m1=target.pos.as_i64vec2();
+		//these are deltas
+		let t1t=(target.time-time).nanos();
+		let tt0=(time-self.time).nanos();
+		let dt=(target.time-self.time).nanos();
+		((m0*t1t+m1*tt0)/dt).as_ivec2()
+	}
+}
diff --git a/src/physics.rs b/src/physics.rs
new file mode 100644
index 0000000..fd377c6
--- /dev/null
+++ b/src/physics.rs
@@ -0,0 +1,21 @@
+#[derive(Debug)]
+pub enum Instruction{
+	ReplaceMouse(crate::mouse::MouseState,crate::mouse::MouseState),
+	SetNextMouse(crate::mouse::MouseState),
+	SetMoveRight(bool),
+	SetMoveUp(bool),
+	SetMoveBack(bool),
+	SetMoveLeft(bool),
+	SetMoveDown(bool),
+	SetMoveForward(bool),
+	SetJump(bool),
+	SetZoom(bool),
+	Restart,
+	Spawn(crate::gameplay_modes::ModeId,crate::gameplay_modes::StageId),
+	Idle,
+		//Idle: there were no input events, but the simulation is safe to advance to this timestep
+		//for interpolation / networking / playback reasons, most playback heads will always want
+		//to be 1 instruction ahead to generate the next state for interpolation.
+	PracticeFly,
+	SetSensitivity(crate::integer::Ratio64Vec2),
+}