diff --git a/build.rs b/build.rs
index 1a3f51c2c0dd7b467460cef09793974926345660..8d9b3961edb3f084031611f00720b8bf51420c5f 100644
--- a/build.rs
+++ b/build.rs
@@ -15,7 +15,7 @@ fn main() -> io::Result<()> {
     let f = BufReader::new(f);
     let mut out = "#[allow(non_snake_case)]
     #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-    pub enum InputTypes{
+    pub(crate) enum InputTypes{
         #[allow(non_snake_case)]
         Float,
         #[allow(non_snake_case)]
@@ -35,13 +35,13 @@ fn main() -> io::Result<()> {
     #[repr(u16)]
     #[allow(non_snake_case)]
     #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-    pub enum InstructionSet{
+    pub(crate) enum InstructionSet{
 
     "
     .to_owned();
 
     let mut outputimpl = "
-    pub fn output(&self) -> Vec<InputTypes>
+    pub(crate) fn output(&self) -> Vec<InputTypes>
     {
         match self {
 
@@ -49,7 +49,7 @@ fn main() -> io::Result<()> {
     .to_owned();
 
     let mut inputimpl = "
-    pub fn input(&self) -> Vec<InputTypes>
+    pub(crate) fn input(&self) -> Vec<InputTypes>
     {
         match self {
 
@@ -65,13 +65,9 @@ fn main() -> io::Result<()> {
 
         let name = &entries[0][11..entries[0].len() - 12];
 
-        out += &format!(
-            "#[allow(non_snake_case)]\n#[allow(dead_code)]\n{name}={index},\n"
-        );
+        out += &format!("#[allow(non_snake_case)]\n#[allow(dead_code)]\n{name}={index},\n");
 
-        inputimpl += &format!(
-            "#[allow(non_snake_case)]\nInstructionSet::{name} => vec!["
-        );
+        inputimpl += &format!("#[allow(non_snake_case)]\nInstructionSet::{name} => vec![");
         for input in entries[1].split(' ').map(str::trim) {
             if input.is_empty() {
                 continue;
@@ -89,9 +85,7 @@ fn main() -> io::Result<()> {
         }
         inputimpl += "],\n";
 
-        outputimpl += &format!(
-            "#[allow(non_snake_case)]\nInstructionSet::{name} => vec!["
-        );
+        outputimpl += &format!("#[allow(non_snake_case)]\nInstructionSet::{name} => vec![");
         for output in entries[2].split(' ').map(str::trim) {
             if output.is_empty() {
                 continue;
diff --git a/src/gui.rs b/src/gui.rs
index b22c3a8e97cfc5ca44f7c24df99d25a513c368cf..5e0fe7b758da66fb3c4390b8fbd699f69cdfdb91 100644
--- a/src/gui.rs
+++ b/src/gui.rs
@@ -11,27 +11,27 @@ fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) {
 }
 
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
-pub struct PreviousDebug {
-    pub bounding_boxes: bool,
-    pub disable_meshcull: bool,
-    pub disable_meshscale1: bool,
-    pub disable_meshscale2: bool,
-    pub disable_taskcull: bool,
-    pub brute_force: bool,
+pub(crate) struct PreviousDebug {
+    pub(crate) bounding_boxes: bool,
+    pub(crate) disable_meshcull: bool,
+    pub(crate) disable_meshscale1: bool,
+    pub(crate) disable_meshscale2: bool,
+    pub(crate) disable_taskcull: bool,
+    pub(crate) brute_force: bool,
 }
 
 #[derive(Debug)]
-pub struct GState {
-    pub cursor_sensitivity: f32,
-    pub move_speed: f32,
+pub(crate) struct GState {
+    pub(crate) cursor_sensitivity: f32,
+    pub(crate) move_speed: f32,
 
-    pub meshes: Vec<Mesh>,
-    pub lights: Vec<Light>,
-    pub csg: Vec<CSG>,
+    pub(crate) meshes: Vec<Mesh>,
+    pub(crate) lights: Vec<Light>,
+    pub(crate) csg: Vec<CSG>,
 
-    pub fps: [f64; 128],
+    pub(crate) fps: [f64; 128],
 
-    pub debug: PreviousDebug,
+    pub(crate) debug: PreviousDebug,
 }
 
 impl Default for GState {
@@ -51,7 +51,7 @@ impl Default for GState {
     }
 }
 
-pub fn gui_up(gui: &mut Gui, state: &mut GState) {
+pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
     gui.immediate_ui(|gui| {
         let ctx = gui.context();
         egui::SidePanel::left(Id::new("main_left"))
@@ -121,11 +121,8 @@ pub fn gui_up(gui: &mut Gui, state: &mut GState) {
                         {
                             state.lights.remove(i);
                         }
-                        if (state.lights.len() < 32) {
-                            if ui.small_button("add light").clicked()
-                            {
-                                state.lights.push(Light::default());
-                            }
+                        if state.lights.len() < 32 && ui.small_button("add light").clicked() {
+                            state.lights.push(Light::default());
                         }
 
                         let fps: PlotPoints = state.fps.iter().enumerate().map(|(x,y)| [x as f64,*y]).collect::<Vec<_>>().into();
diff --git a/src/interpreter.rs b/src/interpreter.rs
index 194a0dc2426e973cd16b623cab2e4ea1ff7cb5d5..e7841bc295b0f5ad6ad7732a7011f571e6900dd7 100644
--- a/src/interpreter.rs
+++ b/src/interpreter.rs
@@ -6,7 +6,7 @@ use crate::{
 use cgmath::{Array, ElementWise, InnerSpace, MetricSpace, VectorSpace};
 
 #[derive(Clone, Debug)]
-pub struct Interpreter<'csg> {
+pub(crate) struct Interpreter<'csg> {
     float_stack: Vec<Float>,
     vec2_stack: Vec<Vec2>,
     vec3_stack: Vec<Vec3>,
@@ -694,7 +694,7 @@ macro_rules! normalise {
 }
 
 impl<'csg> Interpreter<'csg> {
-    pub fn new(csg: &'csg CSG) -> Self {
+    pub(crate) fn new(csg: &'csg CSG) -> Self {
         Interpreter {
             float_stack: vec![],
             vec2_stack: vec![],
@@ -755,7 +755,7 @@ impl<'csg> Interpreter<'csg> {
         );
     }*/
 
-    pub fn scene(&mut self, p: Vec3) -> Float {
+    pub(crate) fn scene(&mut self, p: Vec3) -> Float {
         self.clear_stacks();
         self.push(p);
 
diff --git a/src/main.rs b/src/main.rs
index 9ecba3f417e5070f4a8095883d56e1afae38ebb9..22f90004245fa1b3b4803e58a4e21e0b7f5c80d7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -79,7 +79,7 @@ use crate::instruction_set::InstructionSet;
 
 mod interpreter;
 
-pub type MemoryAllocator = StandardMemoryAllocator;
+pub(crate) type MemoryAllocator = StandardMemoryAllocator;
 
 fn main() {
     let library = VulkanLibrary::new().expect("Vulkan is not installed???");
@@ -1103,7 +1103,7 @@ where
 
     println!("Recompiling implicit pipeline... (may take up to 10 minutes)");
 
-    let mut implicit_pipeline = GraphicsPipeline::start()
+    let implicit_pipeline = GraphicsPipeline::start()
         .render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
         .vertex_input_state(OVertex::per_vertex())
         .input_assembly_state(InputAssemblyState::new())
diff --git a/src/mcsg_deserialise.rs b/src/mcsg_deserialise.rs
index 88c750ead2a94aa71d926857d7e222442288fc11..681d6018c9a2cf0d256a1a378b1d93d95c1af00d 100644
--- a/src/mcsg_deserialise.rs
+++ b/src/mcsg_deserialise.rs
@@ -8,12 +8,12 @@ use serde::de::{
     Visitor,
 };
 use serde::{forward_to_deserialize_any, Deserialize};
-use utf8::{BufReadDecoder};
+use utf8::BufReadDecoder;
 
 type Result<T> = core::result::Result<T, Error>;
 
 #[derive(Debug)]
-pub enum Error {
+pub(crate) enum Error {
     Message(String),
     UTF8(String),
     TrailingCharacters,
@@ -47,7 +47,7 @@ impl serde::ser::Error for Error {
     }
 }
 
-pub struct Deserializer<'de> {
+pub(crate) struct Deserializer<'de> {
     // This string starts with the input data and characters are truncated off
     // the beginning as data is parsed.
     input: BufReadDecoder<BufReader<&'de mut dyn Read>>,
@@ -61,7 +61,7 @@ impl<'de> Deserializer<'de> {
     // `serde_json::from_str(...)` while advanced use cases that require a
     // deserializer can make one with `serde_json::Deserializer::from_str(...)`.
 
-    pub fn from_reader(input: &'de mut dyn Read) -> Self {
+    pub(crate) fn from_reader(input: &'de mut dyn Read) -> Self {
         Deserializer {
             input: BufReadDecoder::new(BufReader::new(input)),
             read_buf: String::new(),
@@ -70,12 +70,12 @@ impl<'de> Deserializer<'de> {
     }
 }
 
-// By convention, the public API of a Serde deserializer is one or more
+// By convention, the pub(crate)lic API of a Serde deserializer is one or more
 // `from_xyz` methods such as `from_str`, `from_bytes`, or `from_reader`
 // depending on what Rust types the deserializer is able to consume as input.
 //
 // This basic deserializer supports only `from_str`.
-pub fn from_reader<'a, T>(s: &'a mut dyn Read) -> Result<T>
+pub(crate) fn from_reader<'a, T>(s: &'a mut dyn Read) -> Result<T>
 where
     T: Deserialize<'a>,
 {
diff --git a/src/objects.rs b/src/objects.rs
index f4ed72595bec236fb7ba3de4a9412b4167bfcbf5..1147cad789ad34891016816051f7bfb9ef48e0ed 100644
--- a/src/objects.rs
+++ b/src/objects.rs
@@ -6,8 +6,8 @@ use std::{
 
 use bytemuck::{Pod, Zeroable};
 use cgmath::{
-    Deg, EuclideanSpace, Euler, Matrix2, Matrix3, Matrix4, Point3, SquareMatrix,
-    Vector2, Vector3, Vector4,
+    Deg, EuclideanSpace, Euler, Matrix2, Matrix3, Matrix4, Point3, SquareMatrix, Vector2, Vector3,
+    Vector4,
 };
 use obj::{LoadConfig, ObjData, ObjError};
 use serde::{Deserialize, Serialize};
@@ -19,15 +19,16 @@ use vulkano::{
 use crate::instruction_set::InstructionSet;
 use crate::{mcsg_deserialise::from_reader, MemoryAllocator};
 
-pub const PLATONIC_SOLIDS: [(&str, &[u8]); 1] = [("Buny", include_bytes!("bunny.obj"))];
-pub const CSG_SOLIDS: [(&str, &[u8]); 1] = [("Primitives", include_bytes!("primitive.mcsg"))];
+pub(crate) const PLATONIC_SOLIDS: [(&str, &[u8]); 1] = [("Buny", include_bytes!("bunny.obj"))];
+pub(crate) const CSG_SOLIDS: [(&str, &[u8]); 1] =
+    [("Primitives", include_bytes!("primitive.mcsg"))];
 
 // We now create a buffer that will store the shape of our triangle.
 // We use #[repr(C)] here to force rustc to not do anything funky with our data, although for this
 // particular example, it doesn't actually change the in-memory representation.
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
-pub struct OVertex {
+pub(crate) struct OVertex {
     #[format(R32G32B32_SFLOAT)]
     position: [f32; 3],
     #[format(R32G32B32_SFLOAT)]
@@ -35,34 +36,34 @@ pub struct OVertex {
 }
 
 #[derive(Debug)]
-pub struct Mesh {
-    pub name: String,
-    pub vertices: Subbuffer<[OVertex]>,
-    pub indices: Subbuffer<[u32]>,
-    pub pos: Point3<f32>,
-    pub rot: Euler<Deg<f32>>,
-    pub scale: Vector3<f32>,
+pub(crate) struct Mesh {
+    pub(crate) name: String,
+    pub(crate) vertices: Subbuffer<[OVertex]>,
+    pub(crate) indices: Subbuffer<[u32]>,
+    pub(crate) pos: Point3<f32>,
+    pub(crate) rot: Euler<Deg<f32>>,
+    pub(crate) scale: Vector3<f32>,
 }
 
 #[derive(Debug)]
-pub struct CSG {
-    pub name: String,
-    pub parts: Vec<CSGPart>,
-    pub pos: Point3<f32>,
-    pub rot: Euler<Deg<f32>>,
-    pub scale: Vector3<f32>,
+pub(crate) struct CSG {
+    pub(crate) name: String,
+    pub(crate) parts: Vec<CSGPart>,
+    pub(crate) pos: Point3<f32>,
+    pub(crate) rot: Euler<Deg<f32>>,
+    pub(crate) scale: Vector3<f32>,
 }
 
-pub type Float = f64;
-pub type Vec2 = Vector2<Float>;
-pub type Vec3 = Vector3<Float>;
-pub type Vec4 = Vector4<Float>;
-pub type Mat2 = Matrix2<Float>;
-pub type Mat3 = Matrix3<Float>;
-pub type Mat4 = Matrix4<Float>;
+pub(crate) type Float = f64;
+pub(crate) type Vec2 = Vector2<Float>;
+pub(crate) type Vec3 = Vector3<Float>;
+pub(crate) type Vec4 = Vector4<Float>;
+pub(crate) type Mat2 = Matrix2<Float>;
+pub(crate) type Mat3 = Matrix3<Float>;
+pub(crate) type Mat4 = Matrix4<Float>;
 
 #[derive(Clone, Copy, Debug, Default, PartialEq)]
-pub enum Inputs {
+pub(crate) enum Inputs {
     #[default]
     Variable,
     Float(Float),
@@ -76,15 +77,15 @@ pub enum Inputs {
 
 #[repr(C)]
 #[derive(Clone, Debug)]
-pub struct CSGPart {
-    pub code: u16,
-    pub opcode: InstructionSet,
-    pub constants: Vec<Inputs>,
-    pub material: Option<Mat4>,
+pub(crate) struct CSGPart {
+    pub(crate) code: u16,
+    pub(crate) opcode: InstructionSet,
+    pub(crate) constants: Vec<Inputs>,
+    pub(crate) material: Option<Mat4>,
 }
 
 impl CSGPart {
-    pub fn opcode(opcode: InstructionSet, inputs: Vec<Inputs>) -> CSGPart {
+    pub(crate) fn opcode(opcode: InstructionSet, inputs: Vec<Inputs>) -> CSGPart {
         CSGPart {
             code: (opcode as u16 & 1023)
                 | inputs
@@ -104,7 +105,7 @@ impl CSGPart {
         }
     }
 
-    pub fn opcode_with_material(
+    pub(crate) fn opcode_with_material(
         opcode: InstructionSet,
         inputs: Vec<Inputs>,
         material: Mat4,
@@ -115,7 +116,7 @@ impl CSGPart {
     }
 }
 
-pub fn load_obj(
+pub(crate) fn load_obj(
     memory_allocator: &MemoryAllocator,
     input: &mut dyn Read,
     name: String,
@@ -331,7 +332,7 @@ fn get_half(o: &HashMap<String, String>) -> Result<Half, String> {
     })
 }
 
-pub fn load_csg(
+pub(crate) fn load_csg(
     _memory_allocator: &MemoryAllocator,
     input: &mut dyn Read,
     name: String,
@@ -400,13 +401,13 @@ pub fn load_csg(
 }
 
 #[derive(Debug)]
-pub struct Light {
-    pub pos: Point3<f32>,
-    pub colour: Vector3<f32>,
+pub(crate) struct Light {
+    pub(crate) pos: Point3<f32>,
+    pub(crate) colour: Vector3<f32>,
 }
 
 impl Light {
-    pub fn new(pos: [f32; 3], colour: [f32; 3], intensity: f32) -> Light {
+    pub(crate) fn new(pos: [f32; 3], colour: [f32; 3], intensity: f32) -> Light {
         let c: Vector3<f32> = colour.into();
         Light {
             pos: pos.into(),