diff --git a/Cargo.lock b/Cargo.lock
index 3fa4784cc2..ee3d1479ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3318,6 +3318,7 @@ dependencies = [
  "bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "faster 0.5.0 (git+https://github.com/AdamNiederer/faster.git?rev=6f99e0396e9992222bb33e8fd1e84347b410d9c0)",
  "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/world/Cargo.toml b/world/Cargo.toml
index a6f163f2fc..539549ed3e 100644
--- a/world/Cargo.toml
+++ b/world/Cargo.toml
@@ -9,6 +9,7 @@ bincode = "1.2.0"
 common = { package = "veloren-common", path = "../common" }
 bitvec = "0.15.2"
 faster = { git = "https://github.com/AdamNiederer/faster.git", rev = "6f99e0396e9992222bb33e8fd1e84347b410d9c0" }
+image = "0.22.3"
 itertools = "0.8.2"
 vek = "0.9.9"
 noise = { version = "0.6.0", default-features = false }
diff --git a/world/examples/water.rs b/world/examples/water.rs
index ccadd6a9df..a4a9de5d63 100644
--- a/world/examples/water.rs
+++ b/world/examples/water.rs
@@ -1,6 +1,6 @@
 use common::{terrain::TerrainChunkSize, vol::RectVolSize};
 // use self::Mode::*;
-use std::{f64, path::PathBuf};
+use std::{f64, io::Write, path::PathBuf, time::SystemTime};
 use vek::*;
 use veloren_world::{
     sim::{self, MapConfig, MapDebug, WorldOpts, WORLD_SIZE},
@@ -102,6 +102,46 @@ fn main() {
             buf[j * W + i] = u32::from_le_bytes([b, g, r, a]);
         });
 
+        if win.is_key_down(minifb::Key::F4) {
+            if let Some(len) = (W * H)
+                .checked_mul(scale as usize)
+                .and_then(|acc| acc.checked_mul(scale as usize))
+            {
+                let x = W * scale as usize;
+                let y = H * scale as usize;
+                let config = sim::MapConfig {
+                    dimensions: Vec2::new(x, y),
+                    scale: 1.0,
+                    ..config
+                };
+                let mut buf = vec![0u8; 4 * len];
+                config.generate(sampler, |pos, (r, g, b, a)| {
+                    let i = pos.x;
+                    let j = pos.y;
+                    (&mut buf[(j * x + i) * 4..]).write(&[r, g, b, a]).unwrap();
+                });
+                // TODO: Justify fits in  u32.
+                let world_map = image::RgbaImage::from_raw(x as u32, y as u32, buf)
+                    .expect("Image dimensions must be valid");
+                let mut path = PathBuf::from("./screenshots");
+                if !path.exists() {
+                    if let Err(err) = std::fs::create_dir(&path) {
+                        log::warn!("Couldn't create folder for screenshot: {:?}", err);
+                    }
+                }
+                path.push(format!(
+                    "worldmap_{}.png",
+                    SystemTime::now()
+                        .duration_since(SystemTime::UNIX_EPOCH)
+                        .map(|d| d.as_millis())
+                        .unwrap_or(0)
+                ));
+                if let Err(err) = world_map.save(&path) {
+                    log::warn!("Couldn't save screenshot: {:?}", err);
+                }
+            }
+        }
+
         let spd = 32.0;
         let lspd = 0.1;
         if win.is_key_down(minifb::Key::P) {