diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 341c618e44..0d1f7721cf 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,5 @@
 stages:
-  - build
+  - check
   - test
   - post-build
   - executable
@@ -39,24 +39,24 @@ before_script:
     fi;
 
 #############
-# BUILD
+# CHECK
 #############
 
-build-voxygen:
-  stage: build
+check-voxygen:
+  stage: check
   image: registry.gitlab.com/veloren/veloren-docker-ci
   tags:
     - veloren-docker
   script:
-    - (cd voxygen && cargo rustc -v -- -D warnings)
+    - (cd voxygen && RUSTFLAGS="-D warnings" cargo check)
 
-build-server-cli:
-  stage: build
+check-server-cli:
+  stage: check
   image: registry.gitlab.com/veloren/veloren-docker-ci
   tags:
     - veloren-docker
   script:
-    - (cd server-cli && cargo rustc -v -- -D warnings)
+    - (cd server-cli && RUSTFLAGS="-D warnings" cargo check)
 
 #############
 # TEST
diff --git a/client/src/lib.rs b/client/src/lib.rs
index 1dd3cc0e1c..37fec85ef5 100644
--- a/client/src/lib.rs
+++ b/client/src/lib.rs
@@ -64,7 +64,7 @@ impl Client {
         let mut postbox = PostBox::to(addr)?;
 
         // Wait for initial sync
-        let (mut state, entity, server_info) = match postbox.next_message() {
+        let (state, entity, server_info) = match postbox.next_message() {
             Some(ServerMsg::InitialSync {
                 ecs_state,
                 entity_uid,
diff --git a/common/src/assets/mod.rs b/common/src/assets/mod.rs
index 2aa0e04fdb..89bea172b9 100644
--- a/common/src/assets/mod.rs
+++ b/common/src/assets/mod.rs
@@ -9,10 +9,9 @@ use log::error;
 use serde_json::Value;
 use std::{
     any::Any,
-    env,
-    fs::{self, read_link, File, ReadDir},
+    fs::{self, File, ReadDir},
     io::{BufReader, Read},
-    path::{Path, PathBuf},
+    path::PathBuf,
     sync::{Arc, RwLock},
 };
 
@@ -243,7 +242,7 @@ fn unpack_specifier(specifier: &str) -> PathBuf {
 
 /// Loads a file based on the specifier and possible extensions
 pub fn load_file(specifier: &str, endings: &[&str]) -> Result<BufReader<File>, Error> {
-    let mut path = unpack_specifier(specifier);
+    let path = unpack_specifier(specifier);
     for ending in endings {
         let mut path = path.clone();
         path.set_extension(ending);
diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs
index fb34afefd5..19e620a01c 100644
--- a/common/src/comp/character_state.rs
+++ b/common/src/comp/character_state.rs
@@ -1,5 +1,5 @@
 use specs::{Component, FlaggedStorage, HashMapStorage};
-use specs_idvs::IDVStorage;
+//use specs_idvs::IDVStorage;
 use std::time::Duration;
 
 #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs
index e65b9eecd6..618cd5b99a 100644
--- a/common/src/comp/inventory/mod.rs
+++ b/common/src/comp/inventory/mod.rs
@@ -5,7 +5,7 @@ pub mod item;
 pub use self::item::{Debug, Item, Tool};
 
 use specs::{Component, HashMapStorage, NullStorage};
-use specs_idvs::IDVStorage;
+//use specs_idvs::IDVStorage;
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct Inventory {
diff --git a/common/src/comp/last.rs b/common/src/comp/last.rs
index 94561f1c5d..dd10781530 100644
--- a/common/src/comp/last.rs
+++ b/common/src/comp/last.rs
@@ -1,5 +1,5 @@
 use specs::{Component, VecStorage};
-use std::{fmt::Debug, marker::Send, ops::Deref};
+use std::marker::Send;
 
 #[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize)]
 pub struct Last<C: Component + PartialEq>(pub C);
diff --git a/common/src/sys/cleanup.rs b/common/src/sys/cleanup.rs
index 090e137d62..5ef189ebb5 100644
--- a/common/src/sys/cleanup.rs
+++ b/common/src/sys/cleanup.rs
@@ -1,13 +1,12 @@
 use crate::comp::Controller;
-use specs::{Entities, Join, System, WriteStorage};
-use vek::*;
+use specs::{Join, System, WriteStorage};
 
 /// This system will allow NPCs to modify their controller
 pub struct Sys;
 impl<'a> System<'a> for Sys {
-    type SystemData = (Entities<'a>, WriteStorage<'a, Controller>);
+    type SystemData = WriteStorage<'a, Controller>;
 
-    fn run(&mut self, (entities, mut controllers): Self::SystemData) {
+    fn run(&mut self, mut controllers: Self::SystemData) {
         for controller in (&mut controllers).join() {
             *controller = Controller::default();
         }
diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs
index 84c1a3d90e..c5372d2425 100644
--- a/common/src/sys/combat.rs
+++ b/common/src/sys/combat.rs
@@ -77,9 +77,7 @@ impl<'a> System<'a> for Sys {
             };
 
             if deal_damage {
-                if let Some(Attack { time_left, applied }) =
-                    &character_states.get(entity).map(|c| c.action)
-                {
+                if let Some(Attack { .. }) = &character_states.get(entity).map(|c| c.action) {
                     // Go through all other entities
                     for (b, pos_b, ori_b, character_b, mut vel_b, stat_b) in (
                         &entities,
diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs
index 3d2b767dfd..6372c03372 100644
--- a/common/src/sys/movement.rs
+++ b/common/src/sys/movement.rs
@@ -5,9 +5,8 @@ use crate::{
     },
     state::DeltaTime,
     terrain::TerrainMap,
-    vol::{ReadVol, Vox},
 };
-use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
+use specs::{Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
 use std::time::Duration;
 use vek::*;
 
@@ -31,7 +30,6 @@ pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
 pub struct Sys;
 impl<'a> System<'a> for Sys {
     type SystemData = (
-        Entities<'a>,
         ReadExpect<'a, TerrainMap>,
         Read<'a, DeltaTime>,
         ReadStorage<'a, Stats>,
@@ -46,8 +44,7 @@ impl<'a> System<'a> for Sys {
     fn run(
         &mut self,
         (
-            entities,
-            terrain,
+            _terrain,
             dt,
             stats,
             controllers,
@@ -59,8 +56,7 @@ impl<'a> System<'a> for Sys {
         ): Self::SystemData,
     ) {
         // Apply movement inputs
-        for (entity, stats, controller, physics, mut character, mut pos, mut vel, mut ori) in (
-            &entities,
+        for (stats, controller, physics, mut character, mut _pos, mut vel, mut ori) in (
             &stats,
             &controllers,
             &physics_states,
@@ -86,8 +82,8 @@ impl<'a> System<'a> for Sys {
             if character.action.is_block() || character.action.is_attack() {
                 vel.0 += Vec2::broadcast(dt.0)
                     * controller.move_dir
-                    * match (physics.on_ground) {
-                        (true) if vel.0.magnitude_squared() < BLOCK_SPEED.powf(2.0) => BLOCK_ACCEL,
+                    * match physics.on_ground {
+                        true if vel.0.magnitude_squared() < BLOCK_SPEED.powf(2.0) => BLOCK_ACCEL,
                         _ => 0.0,
                     }
             } else {
diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs
index d816d21871..511e94b136 100644
--- a/common/src/sys/phys.rs
+++ b/common/src/sys/phys.rs
@@ -1,10 +1,10 @@
 use {
     crate::{
-        comp::{Body, MovementState::*, Ori, PhysicsState, Pos, Scale, Stats, Vel},
+        comp::{Body, Ori, PhysicsState, Pos, Scale, Vel},
         event::{EventBus, LocalEvent},
         state::DeltaTime,
         terrain::TerrainMap,
-        vol::{ReadVol, Vox},
+        vol::ReadVol,
     },
     specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage},
     vek::*,
@@ -73,7 +73,7 @@ impl<'a> System<'a> for Sys {
         let mut event_emitter = event_bus.emitter();
 
         // Apply movement inputs
-        for (entity, scale, _b, mut pos, mut vel, _ori) in (
+        for (entity, scale, _, mut pos, mut vel, mut _ori) in (
             &entities,
             scales.maybe(),
             &bodies,
diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs
index 955f6a6556..34af563d79 100644
--- a/common/src/terrain/structure.rs
+++ b/common/src/terrain/structure.rs
@@ -1,4 +1,4 @@
-use super::{Block, BlockKind};
+use super::BlockKind;
 use crate::{
     assets::{self, Asset},
     vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol},
@@ -6,7 +6,7 @@ use crate::{
 };
 use dot_vox::DotVoxData;
 use std::fs::File;
-use std::io::{BufReader, Read};
+use std::io::BufReader;
 use vek::*;
 
 #[derive(Copy, Clone)]
diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs
index fc6c7026f2..a893e6f75b 100644
--- a/world/src/block/mod.rs
+++ b/world/src/block/mod.rs
@@ -1,7 +1,7 @@
 mod natural;
 
 use crate::{
-    column::{ColumnGen, ColumnSample, StructureData},
+    column::{ColumnGen, ColumnSample},
     generator::{Generator, TownGen},
     util::{HashCache, RandomField, Sampler, SamplerMut},
     World, CONFIG,
@@ -11,7 +11,6 @@ use common::{
     util::saturate_srgb,
     vol::{ReadVol, Vox},
 };
-use noise::NoiseFn;
 use std::ops::{Add, Div, Mul, Neg};
 use vek::*;
 
@@ -79,7 +78,7 @@ impl<'a> BlockGen<'a> {
 
     pub fn get_z_cache(&mut self, wpos: Vec2<i32>) -> Option<ZCache<'a>> {
         let BlockGen {
-            world,
+            world: _,
             column_cache,
             column_gen,
         } = self;
@@ -141,7 +140,7 @@ impl<'a> BlockGen<'a> {
         let &ColumnSample {
             alt,
             chaos,
-            water_level,
+            water_level: _,
             //river,
             surface_color,
             sub_surface_color,
@@ -166,7 +165,7 @@ impl<'a> BlockGen<'a> {
 
         let wposf = wpos.map(|e| e as f64);
 
-        let (definitely_underground, height, water_height) =
+        let (_definitely_underground, height, water_height) =
             if (wposf.z as f32) < alt - 64.0 * chaos {
                 // Shortcut warping
                 (true, alt, CONFIG.sea_level /*water_level*/)
@@ -214,7 +213,7 @@ impl<'a> BlockGen<'a> {
 
         // let dirt_col = Rgb::new(79, 67, 60);
 
-        let air = Block::empty();
+        let _air = Block::empty();
         // let stone = Block::new(2, stone_col);
         // let surface_stone = Block::new(1, Rgb::new(200, 220, 255));
         // let dirt = Block::new(1, dirt_col);
@@ -399,7 +398,7 @@ impl<'a> ZCache<'a> {
             .structures
             .iter()
             .filter_map(|st| st.as_ref())
-            .fold((0.0f32, 0.0f32), |(min, max), (st_info, st_sample)| {
+            .fold((0.0f32, 0.0f32), |(min, max), (st_info, _st_sample)| {
                 let bounds = st_info.get_bounds();
                 let st_area = Aabr {
                     min: Vec2::from(bounds.min),
diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs
index 1489b92eef..30a5a330d0 100644
--- a/world/src/block/natural.rs
+++ b/world/src/block/natural.rs
@@ -1,4 +1,4 @@
-use super::{BlockGen, StructureInfo, StructureMeta, ZCache};
+use super::{BlockGen, StructureInfo, StructureMeta};
 use crate::{
     all::ForestKind,
     column::{ColumnGen, ColumnSample},
diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs
index 04c1903ae0..376efd16d1 100644
--- a/world/src/column/mod.rs
+++ b/world/src/column/mod.rs
@@ -4,7 +4,7 @@ use crate::{
     generator::{Generator, SpawnRules, TownGen},
     sim::{LocationInfo, SimChunk, WorldSim},
     util::{RandomPerm, Sampler, UnitChooser},
-    World, CONFIG,
+    CONFIG,
 };
 use common::{
     assets,
@@ -148,7 +148,8 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
 
         let sim_chunk = sim.get(chunk_pos)?;
 
-        const RIVER_PROPORTION: f32 = 0.025;
+        // Never used
+        //const RIVER_PROPORTION: f32 = 0.025;
 
         /*
         let river = dryness
diff --git a/world/src/generator/town/mod.rs b/world/src/generator/town/mod.rs
index 181b3874b5..62cd36d89e 100644
--- a/world/src/generator/town/mod.rs
+++ b/world/src/generator/town/mod.rs
@@ -5,8 +5,7 @@ use super::{Generator, SpawnRules};
 use crate::{
     block::block_from_structure,
     column::{ColumnGen, ColumnSample},
-    sim::WorldSim,
-    util::{seed_expan, Grid, Sampler, UnitChooser},
+    util::Sampler,
 };
 use common::{
     assets,
@@ -16,7 +15,6 @@ use common::{
 use hashbrown::HashSet;
 use lazy_static::lazy_static;
 use rand::prelude::*;
-use rand_chacha::ChaChaRng;
 use std::{ops::Add, sync::Arc};
 use vek::*;
 
@@ -96,14 +94,14 @@ impl<'a> Sampler<'a> for TownGen {
 impl<'a> Generator<'a, TownState> for TownGen {
     fn get_z_limits(
         &self,
-        town: &'a TownState,
-        wpos: Vec2<i32>,
+        _town: &'a TownState,
+        _wpos: Vec2<i32>,
         sample: &ColumnSample,
     ) -> (f32, f32) {
         (sample.alt - 32.0, sample.alt + 75.0)
     }
 
-    fn spawn_rules(&self, town: &'a TownState, wpos: Vec2<i32>) -> SpawnRules {
+    fn spawn_rules(&self, _town: &'a TownState, _wpos: Vec2<i32>) -> SpawnRules {
         SpawnRules { trees: false }
     }
 }
@@ -234,7 +232,7 @@ impl TownVol {
         let mut junctions = HashSet::new();
         junctions.insert(self.choose_column(rng, |_, col| col.is_road()).unwrap());
 
-        for road in 0..n {
+        for _road in 0..n {
             for _ in 0..ATTEMPTS {
                 let start = *junctions.iter().choose(rng).unwrap();
                 //let start = self.choose_column(rng, |pos, col| pos.map(|e| e % 2 == 0).reduce_and() && col.is_road()).unwrap();
@@ -291,10 +289,9 @@ impl TownVol {
                     })
                     .unwrap();
 
-                let mut park =
-                    self.floodfill(Some(16), [start].iter().copied().collect(), |_, col| {
-                        col.is_empty()
-                    });
+                let park = self.floodfill(Some(16), [start].iter().copied().collect(), |_, col| {
+                    col.is_empty()
+                });
 
                 if park.len() < 4 {
                     continue;
@@ -305,7 +302,8 @@ impl TownVol {
                     let col = self.col(cell).unwrap();
                     let ground = col.ground;
                     for z in 0..2 {
-                        self.set(Vec3::new(cell.x, cell.y, ground + z), CellKind::Park.into());
+                        let _ =
+                            self.set(Vec3::new(cell.x, cell.y, ground + z), CellKind::Park.into());
                     }
                 }
 
@@ -314,7 +312,7 @@ impl TownVol {
         }
     }
 
-    fn gen_walls(&mut self, rng: &mut impl Rng) {
+    fn gen_walls(&mut self, _rng: &mut impl Rng) {
         let mut outer = HashSet::new();
         for i in 0..self.size().x {
             outer.insert(Vec2::new(i, 0));
@@ -325,10 +323,10 @@ impl TownVol {
             outer.insert(Vec2::new(self.size().x - 1, j));
         }
 
-        let mut outer = self.floodfill(None, outer, |_, col| col.is_empty());
+        let outer = self.floodfill(None, outer, |_, col| col.is_empty());
 
         let mut walls = HashSet::new();
-        let inner = self.floodfill(
+        let _inner = self.floodfill(
             None,
             [self.size() / 2].iter().copied().collect(),
             |pos, _| {
@@ -371,7 +369,7 @@ impl TownVol {
             let col = self.col(*wall).unwrap();
             let ground = col.ground;
             for z in -1..3 {
-                self.set(Vec3::new(wall.x, wall.y, ground + z), CellKind::Wall.into());
+                let _ = self.set(Vec3::new(wall.x, wall.y, ground + z), CellKind::Wall.into());
             }
         }
     }
@@ -385,13 +383,12 @@ impl TownVol {
                 match col.kind {
                     None => {}
                     Some(ColumnKind::Internal) => {}
-                    Some(ColumnKind::External) => {}
+                    //Some(ColumnKind::External) => {}
                     Some(ColumnKind::Road) => {
                         for z in -1..2 {
-                            self.set(Vec3::new(i, j, ground + z), CellKind::Road.into());
+                            let _ = self.set(Vec3::new(i, j, ground + z), CellKind::Road.into());
                         }
                     }
-                    _ => unimplemented!(),
                 }
             }
         }
@@ -482,7 +479,7 @@ impl TownVol {
                 }
 
                 for cell in cells {
-                    self.set(cell, CellKind::House(houses.len()).into());
+                    let _ = self.set(cell, CellKind::House(houses.len()).into());
                     self.set_col_kind(Vec2::from(cell), Some(ColumnKind::Internal));
                 }
 
@@ -508,7 +505,7 @@ impl TownVol {
                             .map(TownCell::is_space)
                             .unwrap_or(true)
                     {
-                        self.set(pos, TownCell::empty());
+                        let _ = self.set(pos, TownCell::empty());
                     }
                 }
             }
@@ -574,7 +571,7 @@ impl TownVol {
 
                     if let Some(module) = module {
                         let kind = this_cell.kind.clone();
-                        self.set(
+                        let _ = self.set(
                             pos,
                             TownCell {
                                 kind,
diff --git a/world/src/generator/town/util.rs b/world/src/generator/town/util.rs
index 99cce9c784..7350f7f615 100644
--- a/world/src/generator/town/util.rs
+++ b/world/src/generator/town/util.rs
@@ -16,9 +16,10 @@ pub fn unit(i: usize) -> (Vec2<i32>, Vec2<i32>) {
     (UNITS[i % 4], UNITS[(i + 1) % 4])
 }
 
-pub fn gen_unit(rng: &mut impl Rng) -> (Vec2<i32>, Vec2<i32>) {
-    unit(rng.gen_range(0, 4))
-}
+// unused
+//pub fn gen_unit(rng: &mut impl Rng) -> (Vec2<i32>, Vec2<i32>) {
+//    unit(rng.gen_range(0, 4))
+//}
 
 pub fn gen_dir(rng: &mut impl Rng) -> Vec2<i32> {
     UNITS[rng.gen_range(0, 4)]
@@ -37,6 +38,7 @@ pub fn dir_3d(i: usize) -> Vec3<i32> {
     UNITS_3D[i % 6]
 }
 
-pub fn gen_dir_3d(rng: &mut impl Rng) -> Vec3<i32> {
-    UNITS_3D[rng.gen_range(0, 6)]
-}
+// unused
+//pub fn gen_dir_3d(rng: &mut impl Rng) -> Vec3<i32> {
+//    UNITS_3D[rng.gen_range(0, 6)]
+//}
diff --git a/world/src/generator/town/vol.rs b/world/src/generator/town/vol.rs
index ecc610697c..1a630ed3e0 100644
--- a/world/src/generator/town/vol.rs
+++ b/world/src/generator/town/vol.rs
@@ -7,9 +7,9 @@ use vek::*;
 #[derive(Clone)]
 pub enum ColumnKind {
     Road,
-    Wall,
+    //Wall,
     Internal,
-    External, // Outside the boundary wall
+    //External, // Outside the boundary wall
 }
 
 #[derive(Clone, Default)]
diff --git a/world/src/lib.rs b/world/src/lib.rs
index cb0deb7f1f..5cd9a8916b 100644
--- a/world/src/lib.rs
+++ b/world/src/lib.rs
@@ -21,7 +21,7 @@ pub use crate::config::CONFIG;
 use crate::{
     block::BlockGen,
     column::{ColumnGen, ColumnSample},
-    util::{Sampler, SamplerMut},
+    util::Sampler,
 };
 use common::{
     terrain::{Block, BlockKind, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs
index 97a921f9d1..c6d10bcca8 100644
--- a/world/src/sim/mod.rs
+++ b/world/src/sim/mod.rs
@@ -104,7 +104,7 @@ pub struct WorldSim {
 
 impl WorldSim {
     pub fn generate(mut seed: u32) -> Self {
-        let mut seed = &mut seed;
+        let seed = &mut seed;
         let mut gen_seed = || {
             *seed = seed_expan::diffuse(*seed);
             *seed
@@ -162,7 +162,7 @@ impl WorldSim {
 
         // chaos produces a value in [0.1, 1.24].  It is a meta-level factor intended to reflect how
         // "chaotic" the region is--how much weird stuff is going on on this terrain.
-        let chaos = uniform_noise(|posi, wposf| {
+        let chaos = uniform_noise(|_posi, wposf| {
             // From 0 to 1.6, but the distribution before the max is from -1 and 1, so there is a
             // 50% chance that hill will end up at 0.
             let hill = (0.0
@@ -252,7 +252,7 @@ impl WorldSim {
         };
 
         // A version of alt that is uniform over *non-seawater* (or land-adjacent seawater) chunks.
-        let alt_no_seawater = uniform_noise(|posi, wposf| {
+        let alt_no_seawater = uniform_noise(|posi, _wposf| {
             if pure_water(posi) {
                 None
             } else {
@@ -436,7 +436,7 @@ impl WorldSim {
                 let near_towns = self.gen_ctx.town_gen.get(wpos);
                 let town = near_towns
                     .iter()
-                    .min_by_key(|(pos, seed)| wpos.distance_squared(*pos));
+                    .min_by_key(|(pos, _seed)| wpos.distance_squared(*pos));
 
                 if let Some((pos, _)) = town {
                     let maybe_town = maybe_towns