From 47b3b5e5d9626e33b7a0caa26b3f2e7aab51ab82 Mon Sep 17 00:00:00 2001
From: Avi Weinstock <aweinstock314@gmail.com>
Date: Mon, 28 Jun 2021 21:26:24 -0400
Subject: [PATCH] Generate palette info from block statistics, and benchmark
 how well it compresses.

---
 Cargo.lock                                    |    1 +
 common/net/src/msg/compression.rs             |   15 +-
 world/Cargo.toml                              |    3 +-
 .../examples/chunk_compression_benchmarks.rs  |  129 +-
 world/examples/palettes.ron                   | 1838 +++++++++++++++++
 world/examples/world_block_statistics.rs      |  120 +-
 6 files changed, 2084 insertions(+), 22 deletions(-)
 create mode 100644 world/examples/palettes.ron

diff --git a/Cargo.lock b/Cargo.lock
index 65f5c8fe67..b8e5e4307c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6143,6 +6143,7 @@ dependencies = [
  "arr_macro",
  "bincode",
  "bitvec",
+ "clap",
  "criterion",
  "csv",
  "deflate 0.9.1",
diff --git a/common/net/src/msg/compression.rs b/common/net/src/msg/compression.rs
index 0fd0f89276..98136476ec 100644
--- a/common/net/src/msg/compression.rs
+++ b/common/net/src/msg/compression.rs
@@ -127,8 +127,9 @@ pub trait VoxelImageEncoding: Copy {
     type Workspace;
     type Output;
     fn create(width: u32, height: u32) -> Self::Workspace;
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>);
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>);
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -176,13 +177,14 @@ impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
     }
 
     #[inline(always)]
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
         ws.0.put_pixel(x, y, image::Luma([kind as u8]));
         ws.3.put_pixel(x / N, y / N, image::Rgb([rgb.r, rgb.g, rgb.b]));
     }
 
     #[inline(always)]
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -451,7 +453,7 @@ impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_
         )
     }
 
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
         ws.0.put_pixel(x, y, image::Luma([kind as u8]));
         ws.1.put_pixel(x, y, image::Luma([0]));
         ws.2.put_pixel(x, y, image::Luma([0]));
@@ -461,6 +463,7 @@ impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_
     }
 
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -666,7 +669,7 @@ pub fn image_terrain<
     P: PackingFormula,
     VIE: VoxelImageEncoding,
 >(
-    _: VIE,
+    vie: VIE,
     packing: P,
     vol: &V,
     lo: Vec3<u32>,
@@ -697,10 +700,10 @@ pub fn image_terrain<
                     .unwrap_or(&Block::empty());
                 match (block.get_color(), block.get_sprite()) {
                     (Some(rgb), None) => {
-                        VIE::put_solid(&mut image, i, j, *block, rgb);
+                        VIE::put_solid(&vie, &mut image, i, j, *block, rgb);
                     },
                     (None, Some(sprite)) => {
-                        VIE::put_sprite(&mut image, i, j, *block, sprite, block.get_ori());
+                        VIE::put_sprite(&vie, &mut image, i, j, *block, sprite, block.get_ori());
                     },
                     _ => panic!(
                         "attr being used for color vs sprite is mutually exclusive (and that's \
diff --git a/world/Cargo.toml b/world/Cargo.toml
index 56ff2134b6..b6d4ef4666 100644
--- a/world/Cargo.toml
+++ b/world/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
 
 [features]
 simd = ["vek/platform_intrinsics"]
-bin_compression = ["lz-fear", "deflate", "flate2", "image/jpeg", "num-traits", "fallible-iterator", "kiddo"]
+bin_compression = ["lz-fear", "deflate", "flate2", "image/jpeg", "num-traits", "fallible-iterator", "kiddo", "clap"]
 
 default = ["simd"]
 
@@ -43,6 +43,7 @@ flate2 = { version = "1.0.20", optional = true }
 num-traits = { version = "0.2", optional = true }
 fallible-iterator = { version = "0.2.0", optional = true }
 kiddo = { version = "0.1.4", optional = true }
+clap = { version = "2.33.3", optional = true }
 
 
 [dev-dependencies]
diff --git a/world/examples/chunk_compression_benchmarks.rs b/world/examples/chunk_compression_benchmarks.rs
index 9ac934b953..538612618e 100644
--- a/world/examples/chunk_compression_benchmarks.rs
+++ b/world/examples/chunk_compression_benchmarks.rs
@@ -173,11 +173,12 @@ impl VoxelImageEncoding for PngEncoding {
         ImageBuffer::<Rgba<u8>, Vec<u8>>::new(width, height)
     }
 
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
         ws.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8]));
     }
 
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -223,11 +224,12 @@ impl VoxelImageEncoding for JpegEncoding {
         ImageBuffer::<Rgba<u8>, Vec<u8>>::new(width, height)
     }
 
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
         ws.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8]));
     }
 
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -268,7 +270,7 @@ impl VoxelImageEncoding for MixedEncoding {
         )
     }
 
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
         ws.0.put_pixel(x, y, image::Luma([kind as u8]));
         ws.1.put_pixel(x, y, image::Luma([0]));
         ws.2.put_pixel(x, y, image::Luma([0]));
@@ -276,6 +278,7 @@ impl VoxelImageEncoding for MixedEncoding {
     }
 
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -378,12 +381,13 @@ impl VoxelImageEncoding for MixedEncodingSparseSprites {
         )
     }
 
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
         ws.0.put_pixel(x, y, image::Luma([kind as u8]));
         ws.1.put_pixel(x, y, image::Rgb([rgb.r, rgb.g, rgb.b]));
     }
 
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -439,12 +443,13 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites {
         )
     }
 
-    fn put_solid(ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
         ws.0.put_pixel(x, y, image::Luma([kind as u8]));
         ws.3.put_pixel(x, y, image::Rgb([rgb.r, rgb.g, rgb.b]));
     }
 
     fn put_sprite(
+        &self,
         ws: &mut Self::Workspace,
         x: u32,
         y: u32,
@@ -488,6 +493,100 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites {
     }
 }
 
+use kiddo::KdTree;
+
+lazy_static::lazy_static! {
+    pub static ref PALETTE: HashMap<BlockKind, KdTree<f32, u8, 3>> = {
+        let ron_bytes = include_bytes!("palettes.ron");
+        let palettes: HashMap<BlockKind, Vec<Rgb<u8>>> =
+            ron::de::from_bytes(&*ron_bytes).expect("palette should parse");
+        palettes
+            .into_iter()
+            .map(|(k, v)| {
+                let mut tree = KdTree::new();
+                for (i, rgb) in v.into_iter().enumerate() {
+                    tree.add(&[rgb.r as f32, rgb.g as f32, rgb.b as f32], i as u8)
+                        .expect("kdtree insert should succeed");
+                }
+                (k, tree)
+            })
+            .collect()
+    };
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct PaletteEncoding<'a, const N: u32>(&'a HashMap<BlockKind, KdTree<f32, u8, 3>>);
+
+impl<'a, const N: u32> VoxelImageEncoding for PaletteEncoding<'a, N> {
+    #[allow(clippy::type_complexity)]
+    type Output = CompressedData<(Vec<u8>, [usize; 4])>;
+    #[allow(clippy::type_complexity)]
+    type Workspace = (
+        ImageBuffer<image::Luma<u8>, Vec<u8>>,
+        ImageBuffer<image::Luma<u8>, Vec<u8>>,
+        ImageBuffer<image::Luma<u8>, Vec<u8>>,
+        ImageBuffer<image::Luma<u8>, Vec<u8>>,
+    );
+
+    fn create(width: u32, height: u32) -> Self::Workspace {
+        (
+            ImageBuffer::new(width, height),
+            ImageBuffer::new(width, height),
+            ImageBuffer::new(width, height),
+            ImageBuffer::new(width / N, height / N),
+        )
+    }
+
+    fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
+        ws.0.put_pixel(x, y, image::Luma([kind as u8]));
+        let i = self.0[&kind]
+            .nearest_one(
+                &[rgb.r as f32, rgb.g as f32, rgb.b as f32],
+                &kiddo::distance::squared_euclidean,
+            )
+            .map(|(_, i)| *i)
+            .unwrap_or(0);
+        ws.3.put_pixel(x / N, y / N, image::Luma([i]));
+    }
+
+    fn put_sprite(
+        &self,
+        ws: &mut Self::Workspace,
+        x: u32,
+        y: u32,
+        kind: BlockKind,
+        sprite: SpriteKind,
+        ori: Option<u8>,
+    ) {
+        ws.0.put_pixel(x, y, image::Luma([kind as u8]));
+        ws.1.put_pixel(x, y, image::Luma([sprite as u8]));
+        ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)]));
+    }
+
+    fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
+        let mut buf = Vec::new();
+        use image::codecs::png::{CompressionType, FilterType};
+        let mut indices = [0; 4];
+        let mut f = |x: &ImageBuffer<_, Vec<u8>>, i| {
+            let png = image::codecs::png::PngEncoder::new_with_quality(
+                &mut buf,
+                CompressionType::Rle,
+                FilterType::Up,
+            );
+            png.encode(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8)
+                .ok()?;
+            indices[i] = buf.len();
+            Some(())
+        };
+        f(&ws.0, 0)?;
+        f(&ws.1, 1)?;
+        f(&ws.2, 2)?;
+        f(&ws.3, 3)?;
+
+        Some(CompressedData::compress(&(buf, indices), 1))
+    }
+}
+
 #[allow(clippy::many_single_char_names)]
 fn histogram_to_dictionary(histogram: &HashMap<Vec<u8>, usize>, dictionary: &mut Vec<u8>) {
     let mut tmp: Vec<(Vec<u8>, usize)> = histogram.iter().map(|(k, v)| (k.clone(), *v)).collect();
@@ -898,6 +997,15 @@ fn main() {
                         .unwrap();
                 let tripngconst_post = Instant::now();
 
+                let palettepng_pre = Instant::now();
+                let palettepng = image_terrain_chonk(
+                    PaletteEncoding::<4>(&PALETTE),
+                    WidePacking::<true>(),
+                    &chunk,
+                )
+                .unwrap();
+                let palettepng_post = Instant::now();
+
                 #[rustfmt::skip]
                 sizes.extend_from_slice(&[
                     ("quadpngfull", quadpngfull.data.len() as f32 / n as f32),
@@ -906,6 +1014,7 @@ fn main() {
                     ("quadpngquartwide", quadpngquartwide.data.len() as f32 / n as f32),
                     ("tripngaverage", tripngaverage.data.len() as f32 / n as f32),
                     ("tripngconst", tripngconst.data.len() as f32 / n as f32),
+                    ("palettepng", palettepng.data.len() as f32 / n as f32),
                 ]);
                 let best_idx = sizes
                     .iter()
@@ -926,6 +1035,7 @@ fn main() {
                     ("quadpngquartwide", (quadpngquartwide_post - quadpngquartwide_pre).subsec_nanos()),
                     ("tripngaverage", (tripngaverage_post - tripngaverage_pre).subsec_nanos()),
                     ("tripngconst", (tripngconst_post - tripngconst_pre).subsec_nanos()),
+                    ("palettepng", (palettepng_post - palettepng_pre).subsec_nanos()),
                 ]);
                 if false {
                     let bucket = z_buckets
@@ -965,6 +1075,15 @@ fn main() {
                     bucket.0 += 1;
                     bucket.1 += (tripngconst_post - tripngconst_pre).subsec_nanos() as f32;
                 }
+                if true {
+                    let bucket = z_buckets
+                        .entry("palettepng")
+                        .or_default()
+                        .entry(chunk.get_max_z() - chunk.get_min_z())
+                        .or_insert((0, 0.0));
+                    bucket.0 += 1;
+                    bucket.1 += (palettepng_post - palettepng_pre).subsec_nanos() as f32;
+                }
                 trace!(
                     "{} {}: uncompressed: {}, {:?} {} {:?}",
                     spiralpos.x,
diff --git a/world/examples/palettes.ron b/world/examples/palettes.ron
new file mode 100644
index 0000000000..efea1bc695
--- /dev/null
+++ b/world/examples/palettes.ron
@@ -0,0 +1,1838 @@
+{
+    Leaves: [
+        (r:9,g:66,b:37),
+        (r:67,g:122,b:11),
+        (r:35,g:97,b:27),
+        (r:57,g:74,b:34),
+        (r:34,g:130,b:60),
+        (r:90,g:140,b:0),
+        (r:15,g:80,b:10),
+        (r:57,g:140,b:34),
+        (r:19,g:115,b:42),
+        (r:31,g:100,b:0),
+        (r:89,g:109,b:19),
+        (r:33,g:61,b:45),
+        (r:53,g:103,b:7),
+        (r:15,g:88,b:35),
+        (r:62,g:54,b:43),
+        (r:32,g:77,b:32),
+        (r:54,g:95,b:22),
+        (r:31,g:94,b:29),
+        (r:17,g:98,b:27),
+        (r:0,g:60,b:50),
+        (r:71,g:106,b:13),
+        (r:18,g:72,b:24),
+        (r:49,g:63,b:44),
+        (r:20,g:75,b:44),
+        (r:47,g:107,b:21),
+        (r:78,g:131,b:5),
+        (r:46,g:84,b:30),
+        (r:16,g:91,b:20),
+        (r:29,g:79,b:11),
+        (r:65,g:83,b:27),
+        (r:34,g:96,b:27),
+        (r:33,g:81,b:35),
+        (r:25,g:55,b:50),
+        (r:57,g:114,b:16),
+        (r:43,g:74,b:38),
+        (r:11,g:77,b:33),
+        (r:1,g:71,b:44),
+        (r:42,g:102,b:4),
+        (r:32,g:69,b:40),
+        (r:26,g:86,b:35),
+        (r:63,g:64,b:39),
+        (r:18,g:107,b:35),
+        (r:21,g:83,b:25),
+        (r:34,g:73,b:42),
+        (r:37,g:86,b:27),
+        (r:23,g:63,b:45),
+        (r:21,g:71,b:33),
+        (r:20,g:92,b:29),
+        (r:24,g:95,b:30),
+        (r:29,g:73,b:29),
+        (r:31,g:84,b:28),
+        (r:62,g:105,b:10),
+        (r:80,g:108,b:16),
+        (r:38,g:89,b:36),
+        (r:47,g:55,b:48),
+        (r:24,g:76,b:18),
+        (r:37,g:77,b:28),
+        (r:32,g:91,b:30),
+        (r:20,g:79,b:36),
+        (r:25,g:97,b:30),
+        (r:41,g:102,b:24),
+        (r:4,g:63,b:43),
+        (r:7,g:76,b:41),
+        (r:17,g:74,b:42),
+        (r:11,g:74,b:33),
+        (r:30,g:76,b:40),
+        (r:54,g:104,b:8),
+        (r:13,g:84,b:42),
+        (r:55,g:66,b:39),
+        (r:61,g:76,b:31),
+        (r:42,g:77,b:37),
+        (r:25,g:74,b:40),
+        (r:49,g:77,b:33),
+        (r:42,g:92,b:25),
+        (r:43,g:66,b:38),
+        (r:53,g:111,b:18),
+        (r:84,g:135,b:2),
+        (r:73,g:126,b:8),
+        (r:52,g:102,b:18),
+        (r:63,g:71,b:31),
+        (r:7,g:83,b:33),
+        (r:15,g:86,b:15),
+        (r:21,g:86,b:30),
+        (r:35,g:75,b:38),
+        (r:32,g:84,b:32),
+        (r:25,g:87,b:29),
+        (r:18,g:94,b:33),
+        (r:62,g:118,b:13),
+        (r:39,g:82,b:32),
+        (r:15,g:68,b:35),
+        (r:6,g:74,b:41),
+        (r:25,g:76,b:33),
+        (r:17,g:96,b:24),
+        (r:26,g:93,b:25),
+        (r:16,g:82,b:31),
+        (r:18,g:78,b:43),
+        (r:19,g:78,b:36),
+        (r:20,g:89,b:36),
+        (r:19,g:84,b:39),
+        (r:24,g:82,b:40),
+        (r:13,g:75,b:39),
+        (r:21,g:76,b:28),
+        (r:16,g:83,b:29),
+        (r:34,g:67,b:40),
+        (r:15,g:70,b:29),
+        (r:49,g:73,b:37),
+        (r:14,g:81,b:37),
+        (r:31,g:81,b:37),
+        (r:28,g:71,b:36),
+        (r:34,g:91,b:30),
+        (r:26,g:67,b:42),
+        (r:17,g:103,b:31),
+        (r:25,g:82,b:30),
+        (r:26,g:90,b:31),
+        (r:36,g:101,b:2),
+        (r:18,g:76,b:31),
+        (r:20,g:75,b:31),
+        (r:65,g:59,b:40),
+        (r:33,g:86,b:32),
+        (r:25,g:76,b:42),
+        (r:31,g:86,b:33),
+        (r:36,g:73,b:37),
+        (r:37,g:75,b:33),
+        (r:49,g:87,b:27),
+        (r:46,g:79,b:33),
+        (r:22,g:84,b:35),
+        (r:14,g:69,b:30),
+        (r:22,g:71,b:43),
+        (r:42,g:97,b:23),
+        (r:16,g:71,b:35),
+        (r:22,g:81,b:29),
+        (r:15,g:74,b:40),
+        (r:21,g:66,b:41),
+        (r:18,g:111,b:39),
+        (r:48,g:103,b:6),
+        (r:25,g:97,b:27),
+        (r:32,g:89,b:28),
+        (r:20,g:92,b:31),
+        (r:8,g:80,b:37),
+        (r:25,g:74,b:32),
+        (r:33,g:83,b:28),
+        (r:16,g:89,b:29),
+        (r:38,g:130,b:57),
+        (r:24,g:95,b:29),
+        (r:22,g:85,b:38),
+        (r:41,g:88,b:29),
+        (r:27,g:84,b:34),
+        (r:21,g:74,b:21),
+        (r:29,g:94,b:32),
+        (r:26,g:77,b:14),
+        (r:75,g:107,b:15),
+        (r:66,g:106,b:12),
+        (r:51,g:68,b:38),
+        (r:22,g:75,b:37),
+        (r:84,g:109,b:18),
+        (r:45,g:70,b:39),
+        (r:48,g:74,b:35),
+        (r:20,g:80,b:41),
+        (r:19,g:86,b:34),
+        (r:50,g:93,b:22),
+        (r:33,g:97,b:23),
+        (r:20,g:84,b:39),
+        (r:34,g:92,b:25),
+        (r:35,g:85,b:33),
+        (r:21,g:73,b:37),
+        (r:19,g:91,b:30),
+        (r:39,g:72,b:40),
+        (r:22,g:79,b:32),
+        (r:32,g:82,b:36),
+        (r:27,g:80,b:36),
+        (r:29,g:76,b:35),
+        (r:42,g:63,b:41),
+        (r:19,g:91,b:36),
+        (r:16,g:85,b:38),
+        (r:8,g:87,b:34),
+        (r:12,g:80,b:30),
+        (r:27,g:83,b:37),
+        (r:20,g:86,b:28),
+        (r:20,g:85,b:34),
+        (r:15,g:83,b:12),
+        (r:37,g:80,b:36),
+        (r:21,g:83,b:31),
+        (r:25,g:85,b:31),
+        (r:40,g:103,b:20),
+        (r:41,g:96,b:24),
+        (r:27,g:92,b:29),
+        (r:18,g:82,b:35),
+        (r:24,g:79,b:37),
+        (r:44,g:104,b:22),
+        (r:7,g:64,b:40),
+        (r:38,g:99,b:25),
+        (r:23,g:88,b:33),
+        (r:2,g:61,b:46),
+        (r:34,g:97,b:27),
+        (r:58,g:104,b:9),
+        (r:71,g:125,b:9),
+        (r:38,g:90,b:27),
+        (r:42,g:85,b:30),
+        (r:11,g:83,b:35),
+        (r:17,g:76,b:39),
+        (r:37,g:84,b:28),
+        (r:42,g:80,b:34),
+        (r:12,g:74,b:37),
+        (r:15,g:89,b:31),
+        (r:54,g:72,b:36),
+        (r:29,g:81,b:32),
+        (r:29,g:73,b:40),
+        (r:17,g:74,b:38),
+        (r:46,g:75,b:33),
+        (r:26,g:90,b:35),
+        (r:54,g:112,b:17),
+        (r:11,g:67,b:34),
+        (r:50,g:109,b:19),
+        (r:81,g:133,b:4),
+        (r:11,g:79,b:39),
+        (r:75,g:129,b:7),
+        (r:87,g:138,b:1),
+        (r:37,g:95,b:25),
+        (r:19,g:80,b:39),
+        (r:59,g:71,b:35),
+        (r:14,g:79,b:35),
+        (r:29,g:85,b:30),
+        (r:20,g:97,b:29),
+        (r:29,g:87,b:29),
+        (r:23,g:89,b:29),
+        (r:17,g:85,b:31),
+        (r:29,g:91,b:26),
+        (r:31,g:87,b:25),
+        (r:17,g:91,b:26),
+        (r:17,g:101,b:29),
+        (r:16,g:88,b:18),
+        (r:36,g:88,b:30),
+        (r:19,g:87,b:38),
+        (r:23,g:84,b:37),
+        (r:32,g:76,b:37),
+        (r:15,g:84,b:35),
+        (r:33,g:78,b:38),
+        (r:15,g:94,b:35),
+        (r:38,g:77,b:38),
+        (r:34,g:89,b:27),
+        (r:33,g:81,b:31),
+        (r:27,g:80,b:39),
+        (r:24,g:78,b:36),
+        (r:28,g:84,b:30),
+        (r:49,g:80,b:31),
+        (r:20,g:78,b:38),
+        (r:16,g:76,b:35),
+        (r:15,g:71,b:33),
+        (r:60,g:116,b:15),
+        (r:28,g:88,b:33),
+        (r:38,g:101,b:22),
+        (r:19,g:72,b:40),
+        (r:24,g:92,b:33),
+        (r:25,g:86,b:36),
+        (r:41,g:83,b:33),
+        (r:19,g:83,b:32),
+    ],
+    Lava: [
+        (r:186,g:41,b:2),
+        (r:177,g:32,b:0),
+        (r:189,g:44,b:5),
+        (r:178,g:33,b:0),
+        (r:188,g:43,b:4),
+        (r:184,g:39,b:0),
+        (r:179,g:34,b:0),
+        (r:180,g:35,b:0),
+        (r:190,g:45,b:6),
+        (r:176,g:31,b:0),
+        (r:183,g:38,b:0),
+        (r:191,g:46,b:7),
+        (r:181,g:36,b:0),
+        (r:187,g:42,b:3),
+        (r:185,g:40,b:1),
+        (r:182,g:37,b:0),
+    ],
+    Misc: [
+        (r:73,g:42,b:36),
+        (r:255,g:255,b:255),
+        (r:65,g:65,b:65),
+        (r:114,g:68,b:57),
+        (r:158,g:93,b:79),
+        (r:32,g:32,b:32),
+        (r:65,g:30,b:0),
+        (r:227,g:198,b:172),
+        (r:97,g:44,b:0),
+        (r:207,g:179,b:149),
+        (r:244,g:202,b:144),
+        (r:114,g:105,b:100),
+        (r:204,g:86,b:62),
+        (r:0,g:52,b:58),
+        (r:87,g:39,b:67),
+        (r:184,g:151,b:134),
+        (r:223,g:212,b:202),
+        (r:61,g:93,b:94),
+        (r:141,g:71,b:37),
+        (r:177,g:173,b:157),
+        (r:128,g:85,b:74),
+        (r:237,g:237,b:237),
+        (r:180,g:94,b:47),
+        (r:166,g:133,b:148),
+        (r:98,g:53,b:40),
+        (r:127,g:84,b:73),
+        (r:52,g:52,b:47),
+        (r:177,g:142,b:111),
+        (r:232,g:178,b:152),
+        (r:191,g:187,b:171),
+        (r:247,g:208,b:150),
+        (r:221,g:167,b:141),
+        (r:194,g:174,b:144),
+        (r:180,g:147,b:162),
+        (r:77,g:45,b:13),
+        (r:54,g:30,b:26),
+        (r:74,g:106,b:107),
+        (r:12,g:65,b:71),
+        (r:63,g:63,b:63),
+        (r:57,g:22,b:0),
+        (r:103,g:76,b:74),
+        (r:24,g:19,b:17),
+        (r:244,g:210,b:174),
+        (r:90,g:58,b:59),
+        (r:77,g:77,b:77),
+        (r:97,g:72,b:47),
+        (r:88,g:56,b:24),
+        (r:125,g:116,b:111),
+        (r:80,g:49,b:55),
+        (r:114,g:72,b:53),
+        (r:220,g:190,b:157),
+        (r:77,g:29,b:57),
+        (r:64,g:96,b:97),
+        (r:108,g:55,b:7),
+        (r:79,g:70,b:57),
+        (r:107,g:82,b:57),
+        (r:235,g:193,b:135),
+        (r:41,g:41,b:41),
+        (r:137,g:94,b:83),
+        (r:160,g:101,b:91),
+        (r:95,g:60,b:55),
+        (r:109,g:62,b:42),
+        (r:100,g:70,b:60),
+        (r:55,g:39,b:40),
+        (r:186,g:151,b:120),
+        (r:196,g:78,b:54),
+        (r:145,g:86,b:76),
+        (r:86,g:42,b:22),
+        (r:43,g:35,b:22),
+        (r:86,g:47,b:44),
+        (r:105,g:80,b:55),
+        (r:184,g:180,b:164),
+        (r:211,g:93,b:69),
+        (r:64,g:36,b:31),
+        (r:196,g:176,b:146),
+        (r:213,g:175,b:144),
+        (r:97,g:64,b:37),
+        (r:116,g:100,b:90),
+        (r:207,g:187,b:157),
+        (r:72,g:37,b:7),
+        (r:89,g:57,b:46),
+        (r:71,g:71,b:71),
+        (r:6,g:59,b:65),
+        (r:226,g:172,b:146),
+        (r:172,g:139,b:154),
+        (r:192,g:157,b:126),
+        (r:117,g:77,b:59),
+        (r:239,g:209,b:183),
+        (r:104,g:65,b:54),
+        (r:45,g:29,b:30),
+        (r:203,g:175,b:145),
+        (r:220,g:195,b:177),
+        (r:82,g:50,b:18),
+        (r:50,g:34,b:35),
+        (r:103,g:50,b:2),
+        (r:60,g:44,b:45),
+        (r:120,g:111,b:106),
+        (r:82,g:34,b:62),
+        (r:69,g:101,b:102),
+        (r:92,g:44,b:72),
+        (r:122,g:79,b:68),
+        (r:150,g:91,b:81),
+        (r:63,g:28,b:0),
+        (r:50,g:52,b:55),
+        (r:155,g:96,b:86),
+        (r:97,g:62,b:58),
+        (r:87,g:51,b:51),
+        (r:110,g:73,b:59),
+        (r:97,g:57,b:48),
+        (r:93,g:66,b:44),
+        (r:108,g:72,b:60),
+        (r:54,g:46,b:38),
+        (r:220,g:186,b:163),
+        (r:84,g:54,b:59),
+        (r:214,g:186,b:156),
+        (r:105,g:67,b:56),
+        (r:92,g:51,b:44),
+        (r:73,g:73,b:73),
+        (r:101,g:76,b:51),
+        (r:239,g:197,b:139),
+        (r:133,g:90,b:79),
+        (r:200,g:82,b:58),
+        (r:217,g:163,b:137),
+        (r:110,g:101,b:96),
+        (r:182,g:147,b:116),
+        (r:176,g:143,b:158),
+        (r:200,g:180,b:150),
+        (r:225,g:171,b:145),
+        (r:89,g:54,b:52),
+        (r:113,g:68,b:48),
+        (r:92,g:65,b:50),
+        (r:103,g:71,b:65),
+        (r:109,g:69,b:54),
+        (r:101,g:57,b:43),
+        (r:246,g:204,b:146),
+        (r:93,g:40,b:0),
+        (r:119,g:69,b:59),
+        (r:94,g:71,b:42),
+        (r:104,g:63,b:49),
+        (r:68,g:68,b:68),
+        (r:85,g:53,b:21),
+        (r:187,g:183,b:167),
+        (r:211,g:183,b:153),
+        (r:208,g:90,b:66),
+        (r:69,g:34,b:4),
+        (r:91,g:43,b:71),
+        (r:229,g:175,b:149),
+        (r:169,g:136,b:151),
+        (r:204,g:176,b:146),
+        (r:189,g:154,b:123),
+        (r:9,g:62,b:68),
+        (r:117,g:108,b:103),
+        (r:181,g:177,b:161),
+        (r:203,g:183,b:153),
+        (r:92,g:59,b:58),
+        (r:94,g:63,b:62),
+        (r:89,g:51,b:48),
+        (r:93,g:54,b:48),
+        (r:111,g:72,b:56),
+        (r:100,g:70,b:44),
+        (r:2,g:55,b:61),
+        (r:96,g:54,b:44),
+        (r:111,g:102,b:101),
+        (r:98,g:65,b:61),
+        (r:51,g:51,b:51),
+        (r:100,g:47,b:0),
+        (r:60,g:25,b:0),
+        (r:88,g:50,b:47),
+        (r:114,g:77,b:62),
+        (r:93,g:57,b:53),
+        (r:115,g:74,b:57),
+        (r:91,g:55,b:43),
+        (r:99,g:54,b:41),
+        (r:217,g:189,b:159),
+        (r:101,g:62,b:51),
+        (r:89,g:56,b:56),
+        (r:102,g:66,b:58),
+        (r:86,g:53,b:54),
+        (r:105,g:70,b:62),
+        (r:89,g:49,b:44),
+        (r:99,g:57,b:46),
+        (r:111,g:75,b:62),
+        (r:84,g:47,b:47),
+        (r:75,g:75,b:75),
+        (r:90,g:58,b:26),
+        (r:79,g:47,b:15),
+        (r:48,g:32,b:33),
+        (r:106,g:53,b:5),
+        (r:75,g:43,b:11),
+        (r:103,g:78,b:53),
+        (r:99,g:74,b:49),
+        (r:52,g:36,b:37),
+        (r:57,g:41,b:42),
+        (r:153,g:94,b:84),
+        (r:123,g:114,b:109),
+        (r:198,g:80,b:56),
+        (r:206,g:88,b:64),
+        (r:158,g:99,b:89),
+        (r:179,g:175,b:159),
+        (r:89,g:41,b:69),
+        (r:237,g:195,b:137),
+        (r:202,g:84,b:60),
+        (r:148,g:89,b:79),
+        (r:184,g:149,b:118),
+        (r:198,g:178,b:148),
+        (r:192,g:172,b:142),
+        (r:179,g:144,b:113),
+        (r:84,g:36,b:64),
+        (r:80,g:32,b:60),
+        (r:242,g:200,b:142),
+        (r:189,g:185,b:169),
+        (r:66,g:98,b:99),
+        (r:130,g:87,b:76),
+        (r:63,g:95,b:96),
+        (r:223,g:169,b:143),
+        (r:71,g:103,b:104),
+        (r:67,g:32,b:2),
+        (r:125,g:82,b:71),
+        (r:209,g:181,b:151),
+        (r:59,g:91,b:92),
+        (r:219,g:165,b:139),
+        (r:135,g:92,b:81),
+        (r:95,g:70,b:45),
+        (r:112,g:103,b:98),
+        (r:95,g:52,b:41),
+        (r:112,g:73,b:56),
+        (r:98,g:57,b:45),
+        (r:92,g:50,b:41),
+        (r:103,g:68,b:60),
+        (r:94,g:56,b:50),
+        (r:111,g:71,b:55),
+        (r:92,g:52,b:46),
+        (r:95,g:55,b:46),
+        (r:95,g:67,b:42),
+        (r:98,g:65,b:58),
+        (r:95,g:42,b:0),
+        (r:247,g:206,b:148),
+        (r:91,g:54,b:50),
+        (r:107,g:69,b:56),
+        (r:111,g:69,b:52),
+        (r:92,g:67,b:42),
+        (r:99,g:63,b:57),
+        (r:94,g:53,b:45),
+        (r:96,g:51,b:39),
+        (r:106,g:72,b:62),
+        (r:87,g:49,b:45),
+        (r:90,g:51,b:45),
+        (r:89,g:50,b:46),
+        (r:110,g:72,b:58),
+        (r:112,g:69,b:50),
+        (r:112,g:74,b:58),
+        (r:91,g:49,b:43),
+        (r:117,g:76,b:57),
+        (r:91,g:53,b:48),
+        (r:91,g:55,b:52),
+        (r:94,g:52,b:43),
+    ],
+    Wood: [
+        (r:60,g:30,b:0),
+    ],
+    Snow: [
+        (r:210,g:210,b:255),
+        (r:129,g:163,b:255),
+        (r:164,g:186,b:255),
+        (r:90,g:110,b:150),
+        (r:97,g:142,b:233),
+        (r:82,g:132,b:198),
+        (r:59,g:117,b:144),
+        (r:46,g:108,b:116),
+        (r:131,g:131,b:255),
+        (r:111,g:118,b:208),
+        (r:81,g:98,b:114),
+        (r:107,g:101,b:179),
+        (r:35,g:101,b:85),
+        (r:72,g:84,b:79),
+        (r:19,g:89,b:58),
+        (r:64,g:73,b:47),
+        (r:43,g:51,b:73),
+        (r:67,g:122,b:165),
+        (r:86,g:100,b:151),
+        (r:52,g:65,b:101),
+        (r:65,g:73,b:130),
+        (r:77,g:103,b:188),
+        (r:87,g:72,b:102),
+        (r:94,g:84,b:136),
+        (r:103,g:160,b:212),
+        (r:94,g:128,b:173),
+        (r:47,g:86,b:65),
+        (r:123,g:135,b:227),
+        (r:107,g:119,b:242),
+        (r:155,g:159,b:255),
+        (r:56,g:92,b:98),
+        (r:186,g:200,b:255),
+        (r:109,g:147,b:255),
+        (r:71,g:95,b:141),
+        (r:73,g:60,b:66),
+        (r:58,g:90,b:104),
+        (r:84,g:69,b:95),
+        (r:86,g:97,b:98),
+        (r:50,g:68,b:97),
+        (r:139,g:176,b:255),
+        (r:8,g:82,b:39),
+        (r:111,g:161,b:237),
+        (r:34,g:99,b:99),
+        (r:68,g:87,b:153),
+        (r:101,g:138,b:209),
+        (r:100,g:118,b:199),
+        (r:80,g:130,b:203),
+        (r:89,g:110,b:203),
+        (r:139,g:144,b:255),
+        (r:66,g:109,b:125),
+        (r:97,g:147,b:202),
+        (r:101,g:114,b:157),
+        (r:95,g:105,b:130),
+        (r:94,g:123,b:222),
+        (r:88,g:95,b:171),
+        (r:55,g:113,b:151),
+        (r:84,g:125,b:154),
+        (r:50,g:78,b:33),
+        (r:55,g:69,b:73),
+        (r:80,g:79,b:119),
+        (r:71,g:124,b:184),
+        (r:54,g:90,b:123),
+        (r:103,g:94,b:157),
+        (r:76,g:87,b:99),
+        (r:83,g:113,b:169),
+        (r:67,g:77,b:96),
+        (r:91,g:144,b:185),
+        (r:100,g:116,b:193),
+        (r:74,g:116,b:153),
+        (r:109,g:118,b:178),
+        (r:39,g:83,b:49),
+        (r:117,g:134,b:244),
+        (r:114,g:109,b:202),
+        (r:66,g:83,b:62),
+        (r:43,g:88,b:68),
+        (r:44,g:74,b:82),
+        (r:47,g:94,b:82),
+        (r:115,g:127,b:202),
+        (r:65,g:75,b:110),
+        (r:65,g:113,b:143),
+        (r:63,g:108,b:122),
+        (r:65,g:91,b:124),
+        (r:63,g:74,b:119),
+        (r:64,g:93,b:138),
+        (r:87,g:117,b:186),
+        (r:138,g:148,b:255),
+        (r:65,g:99,b:107),
+        (r:114,g:120,b:226),
+        (r:99,g:116,b:175),
+        (r:46,g:103,b:98),
+        (r:85,g:92,b:150),
+        (r:59,g:117,b:151),
+        (r:127,g:122,b:237),
+        (r:108,g:149,b:255),
+        (r:102,g:121,b:206),
+        (r:108,g:132,b:225),
+        (r:109,g:119,b:247),
+        (r:24,g:93,b:75),
+        (r:49,g:109,b:133),
+        (r:109,g:144,b:224),
+        (r:84,g:115,b:198),
+        (r:105,g:135,b:246),
+        (r:82,g:117,b:170),
+        (r:69,g:102,b:160),
+        (r:73,g:68,b:83),
+        (r:93,g:101,b:187),
+        (r:79,g:108,b:136),
+        (r:82,g:92,b:129),
+        (r:67,g:107,b:124),
+        (r:65,g:92,b:126),
+        (r:139,g:160,b:255),
+        (r:56,g:80,b:85),
+        (r:99,g:131,b:190),
+        (r:49,g:103,b:101),
+        (r:107,g:115,b:224),
+        (r:72,g:93,b:93),
+        (r:90,g:138,b:220),
+        (r:110,g:131,b:216),
+        (r:105,g:147,b:221),
+        (r:154,g:174,b:255),
+        (r:89,g:107,b:123),
+        (r:62,g:76,b:101),
+        (r:76,g:120,b:150),
+        (r:110,g:146,b:239),
+        (r:124,g:144,b:255),
+        (r:87,g:114,b:183),
+        (r:83,g:103,b:152),
+        (r:85,g:111,b:166),
+        (r:83,g:98,b:173),
+        (r:84,g:88,b:151),
+        (r:85,g:115,b:152),
+        (r:86,g:115,b:201),
+        (r:46,g:92,b:82),
+        (r:76,g:105,b:150),
+        (r:82,g:116,b:183),
+        (r:56,g:63,b:60),
+        (r:61,g:81,b:67),
+        (r:47,g:87,b:67),
+        (r:68,g:81,b:142),
+        (r:81,g:83,b:98),
+        (r:96,g:104,b:214),
+        (r:109,g:132,b:232),
+        (r:99,g:90,b:150),
+        (r:89,g:89,b:123),
+        (r:52,g:81,b:53),
+        (r:134,g:176,b:255),
+        (r:124,g:148,b:255),
+        (r:110,g:146,b:255),
+        (r:138,g:145,b:255),
+        (r:109,g:148,b:232),
+        (r:64,g:101,b:110),
+        (r:96,g:117,b:165),
+        (r:64,g:107,b:136),
+        (r:61,g:65,b:89),
+        (r:98,g:105,b:201),
+        (r:97,g:104,b:166),
+        (r:32,g:98,b:98),
+        (r:49,g:81,b:109),
+        (r:108,g:150,b:234),
+        (r:83,g:132,b:166),
+        (r:178,g:189,b:255),
+        (r:49,g:59,b:66),
+        (r:66,g:89,b:83),
+        (r:66,g:83,b:96),
+        (r:67,g:72,b:71),
+        (r:47,g:102,b:97),
+        (r:71,g:88,b:112),
+        (r:116,g:164,b:249),
+        (r:93,g:99,b:142),
+        (r:110,g:121,b:191),
+        (r:88,g:127,b:196),
+        (r:85,g:124,b:187),
+        (r:87,g:121,b:152),
+        (r:69,g:84,b:66),
+        (r:99,g:150,b:204),
+        (r:86,g:135,b:207),
+        (r:108,g:128,b:226),
+        (r:93,g:131,b:211),
+        (r:107,g:131,b:248),
+        (r:116,g:148,b:244),
+        (r:72,g:117,b:154),
+        (r:110,g:133,b:255),
+        (r:108,g:130,b:213),
+        (r:32,g:87,b:59),
+        (r:107,g:159,b:225),
+        (r:109,g:105,b:191),
+        (r:86,g:87,b:110),
+        (r:73,g:83,b:130),
+        (r:81,g:100,b:126),
+        (r:72,g:97,b:135),
+        (r:90,g:96,b:139),
+        (r:80,g:93,b:162),
+        (r:87,g:81,b:126),
+        (r:61,g:65,b:38),
+        (r:64,g:88,b:116),
+        (r:100,g:135,b:202),
+        (r:58,g:117,b:131),
+        (r:64,g:91,b:117),
+        (r:62,g:95,b:99),
+        (r:99,g:119,b:185),
+        (r:60,g:90,b:134),
+        (r:52,g:94,b:113),
+        (r:56,g:97,b:125),
+        (r:54,g:80,b:98),
+        (r:66,g:70,b:68),
+        (r:66,g:80,b:99),
+        (r:74,g:128,b:173),
+        (r:87,g:118,b:173),
+        (r:91,g:119,b:211),
+        (r:57,g:90,b:74),
+        (r:77,g:90,b:124),
+        (r:90,g:76,b:113),
+        (r:108,g:116,b:183),
+        (r:97,g:108,b:178),
+        (r:86,g:101,b:177),
+        (r:104,g:100,b:175),
+        (r:62,g:72,b:65),
+        (r:90,g:107,b:176),
+        (r:93,g:90,b:152),
+        (r:103,g:129,b:237),
+        (r:83,g:86,b:140),
+        (r:88,g:130,b:183),
+        (r:65,g:77,b:78),
+        (r:16,g:86,b:47),
+        (r:81,g:97,b:143),
+        (r:119,g:113,b:215),
+        (r:108,g:138,b:235),
+        (r:66,g:97,b:125),
+        (r:38,g:102,b:110),
+        (r:102,g:146,b:244),
+        (r:86,g:130,b:177),
+        (r:36,g:94,b:75),
+        (r:115,g:123,b:238),
+        (r:109,g:133,b:230),
+        (r:122,g:136,b:233),
+        (r:77,g:107,b:177),
+        (r:67,g:100,b:145),
+        (r:85,g:96,b:103),
+        (r:65,g:80,b:121),
+        (r:72,g:90,b:105),
+        (r:88,g:95,b:123),
+        (r:74,g:88,b:124),
+        (r:77,g:79,b:108),
+        (r:72,g:114,b:164),
+        (r:109,g:128,b:203),
+        (r:104,g:112,b:213),
+        (r:84,g:115,b:158),
+        (r:89,g:117,b:201),
+        (r:107,g:120,b:176),
+        (r:165,g:172,b:255),
+        (r:65,g:122,b:150),
+        (r:78,g:102,b:124),
+        (r:96,g:104,b:154),
+        (r:130,g:139,b:247),
+        (r:52,g:91,b:102),
+        (r:88,g:133,b:165),
+    ],
+    Air: [
+        (r:0,g:0,b:0),
+    ],
+    Earth: [
+        (r:90,g:110,b:150),
+        (r:71,g:31,b:11),
+        (r:48,g:68,b:18),
+        (r:128,g:102,b:73),
+        (r:68,g:88,b:38),
+        (r:115,g:107,b:103),
+        (r:87,g:75,b:92),
+        (r:57,g:103,b:110),
+        (r:85,g:50,b:35),
+        (r:35,g:101,b:85),
+        (r:95,g:64,b:63),
+        (r:68,g:46,b:65),
+        (r:117,g:61,b:30),
+        (r:90,g:93,b:120),
+        (r:154,g:124,b:81),
+        (r:60,g:76,b:74),
+        (r:38,g:56,b:49),
+        (r:28,g:96,b:73),
+        (r:63,g:54,b:85),
+        (r:152,g:122,b:80),
+        (r:94,g:96,b:62),
+        (r:40,g:27,b:66),
+        (r:60,g:68,b:114),
+        (r:133,g:84,b:47),
+        (r:81,g:124,b:178),
+        (r:44,g:24,b:34),
+        (r:14,g:72,b:31),
+        (r:81,g:58,b:36),
+        (r:91,g:79,b:20),
+        (r:171,g:152,b:101),
+        (r:59,g:115,b:141),
+        (r:101,g:141,b:155),
+        (r:95,g:136,b:218),
+        (r:38,g:34,b:81),
+        (r:93,g:154,b:184),
+        (r:15,g:10,b:43),
+        (r:145,g:74,b:18),
+        (r:111,g:128,b:127),
+        (r:64,g:91,b:151),
+        (r:87,g:130,b:149),
+        (r:86,g:108,b:89),
+        (r:82,g:98,b:77),
+        (r:37,g:70,b:90),
+        (r:32,g:96,b:24),
+        (r:62,g:88,b:81),
+        (r:63,g:83,b:140),
+        (r:104,g:82,b:83),
+        (r:102,g:122,b:121),
+        (r:40,g:54,b:79),
+        (r:133,g:131,b:107),
+        (r:14,g:41,b:62),
+        (r:153,g:105,b:56),
+        (r:109,g:97,b:37),
+        (r:63,g:120,b:152),
+        (r:43,g:84,b:52),
+        (r:82,g:47,b:32),
+        (r:81,g:57,b:68),
+        (r:49,g:53,b:42),
+        (r:43,g:53,b:80),
+        (r:83,g:39,b:9),
+        (r:132,g:106,b:81),
+        (r:86,g:102,b:146),
+        (r:118,g:87,b:13),
+        (r:78,g:99,b:15),
+        (r:51,g:16,b:1),
+        (r:22,g:71,b:65),
+        (r:109,g:83,b:80),
+        (r:114,g:143,b:149),
+        (r:83,g:79,b:45),
+        (r:83,g:81,b:80),
+        (r:19,g:92,b:47),
+        (r:188,g:169,b:110),
+        (r:82,g:81,b:58),
+        (r:19,g:18,b:77),
+        (r:62,g:65,b:51),
+        (r:43,g:63,b:13),
+        (r:48,g:54,b:80),
+        (r:48,g:98,b:77),
+        (r:46,g:79,b:80),
+        (r:77,g:116,b:124),
+        (r:22,g:26,b:23),
+        (r:24,g:53,b:43),
+        (r:50,g:93,b:22),
+        (r:102,g:91,b:81),
+        (r:82,g:83,b:95),
+        (r:62,g:80,b:88),
+        (r:44,g:82,b:100),
+        (r:69,g:81,b:139),
+        (r:43,g:49,b:101),
+        (r:48,g:88,b:52),
+        (r:61,g:51,b:21),
+        (r:72,g:74,b:19),
+        (r:69,g:82,b:117),
+        (r:110,g:76,b:49),
+        (r:106,g:80,b:77),
+        (r:84,g:81,b:43),
+        (r:83,g:87,b:20),
+        (r:132,g:77,b:40),
+        (r:122,g:80,b:16),
+        (r:142,g:83,b:18),
+        (r:111,g:81,b:55),
+        (r:83,g:75,b:80),
+        (r:79,g:100,b:168),
+        (r:15,g:54,b:46),
+        (r:79,g:81,b:114),
+        (r:47,g:79,b:29),
+        (r:103,g:107,b:123),
+        (r:88,g:119,b:199),
+        (r:102,g:105,b:105),
+        (r:173,g:139,b:83),
+        (r:153,g:137,b:99),
+        (r:82,g:76,b:80),
+        (r:99,g:52,b:18),
+        (r:63,g:36,b:37),
+        (r:80,g:133,b:157),
+        (r:110,g:103,b:82),
+        (r:51,g:54,b:36),
+        (r:100,g:142,b:238),
+        (r:37,g:47,b:60),
+        (r:80,g:100,b:50),
+        (r:48,g:77,b:45),
+        (r:67,g:69,b:47),
+        (r:83,g:103,b:78),
+        (r:98,g:67,b:35),
+        (r:82,g:62,b:48),
+        (r:82,g:53,b:52),
+        (r:50,g:31,b:44),
+        (r:31,g:39,b:40),
+        (r:77,g:100,b:106),
+        (r:61,g:105,b:116),
+        (r:67,g:82,b:112),
+        (r:21,g:11,b:37),
+        (r:49,g:52,b:39),
+        (r:103,g:81,b:26),
+        (r:128,g:139,b:125),
+        (r:121,g:103,b:54),
+        (r:83,g:50,b:55),
+        (r:31,g:21,b:48),
+        (r:48,g:54,b:60),
+        (r:47,g:67,b:63),
+        (r:73,g:97,b:130),
+        (r:49,g:81,b:103),
+        (r:9,g:91,b:28),
+        (r:28,g:73,b:45),
+        (r:47,g:100,b:76),
+        (r:102,g:81,b:81),
+        (r:71,g:66,b:98),
+        (r:43,g:54,b:81),
+        (r:92,g:89,b:111),
+        (r:66,g:44,b:43),
+        (r:103,g:91,b:100),
+        (r:95,g:138,b:173),
+        (r:43,g:84,b:81),
+        (r:88,g:116,b:112),
+        (r:37,g:101,b:104),
+        (r:122,g:82,b:31),
+        (r:118,g:83,b:59),
+        (r:117,g:101,b:79),
+        (r:105,g:94,b:12),
+        (r:117,g:99,b:57),
+        (r:98,g:107,b:132),
+        (r:168,g:132,b:78),
+        (r:138,g:122,b:91),
+        (r:136,g:97,b:29),
+        (r:38,g:62,b:31),
+        (r:47,g:54,b:46),
+        (r:27,g:75,b:47),
+        (r:18,g:56,b:50),
+        (r:12,g:85,b:46),
+        (r:66,g:59,b:79),
+        (r:66,g:84,b:49),
+        (r:42,g:85,b:46),
+        (r:64,g:55,b:23),
+        (r:27,g:40,b:75),
+        (r:110,g:80,b:30),
+        (r:82,g:76,b:39),
+        (r:62,g:94,b:66),
+        (r:79,g:63,b:81),
+        (r:52,g:40,b:71),
+        (r:53,g:102,b:88),
+        (r:43,g:105,b:116),
+        (r:61,g:53,b:80),
+        (r:56,g:27,b:20),
+        (r:148,g:93,b:43),
+        (r:101,g:128,b:138),
+        (r:104,g:129,b:144),
+        (r:155,g:126,b:82),
+        (r:104,g:123,b:131),
+        (r:111,g:122,b:114),
+        (r:126,g:125,b:104),
+        (r:53,g:64,b:98),
+        (r:48,g:72,b:60),
+        (r:87,g:80,b:63),
+        (r:102,g:60,b:47),
+        (r:84,g:80,b:42),
+        (r:129,g:78,b:45),
+        (r:67,g:53,b:40),
+        (r:59,g:73,b:31),
+        (r:138,g:96,b:59),
+        (r:33,g:38,b:41),
+        (r:46,g:51,b:44),
+        (r:102,g:105,b:115),
+        (r:144,g:109,b:71),
+        (r:79,g:94,b:81),
+        (r:27,g:68,b:18),
+        (r:48,g:53,b:60),
+        (r:118,g:80,b:64),
+        (r:77,g:117,b:143),
+        (r:118,g:88,b:76),
+        (r:78,g:116,b:161),
+        (r:63,g:92,b:98),
+        (r:69,g:83,b:107),
+        (r:115,g:71,b:44),
+        (r:67,g:117,b:112),
+        (r:117,g:82,b:16),
+        (r:84,g:82,b:62),
+        (r:100,g:99,b:78),
+        (r:52,g:83,b:119),
+        (r:30,g:54,b:64),
+        (r:117,g:82,b:36),
+        (r:43,g:36,b:80),
+        (r:51,g:69,b:81),
+        (r:47,g:30,b:45),
+        (r:97,g:125,b:151),
+        (r:29,g:80,b:30),
+        (r:65,g:54,b:63),
+        (r:66,g:81,b:76),
+        (r:76,g:72,b:63),
+        (r:58,g:77,b:62),
+        (r:48,g:78,b:80),
+        (r:82,g:78,b:79),
+        (r:101,g:87,b:97),
+        (r:162,g:120,b:67),
+        (r:83,g:67,b:28),
+        (r:82,g:43,b:16),
+        (r:131,g:67,b:23),
+        (r:36,g:80,b:67),
+        (r:51,g:87,b:114),
+        (r:33,g:96,b:57),
+        (r:92,g:95,b:40),
+        (r:92,g:84,b:47),
+        (r:102,g:82,b:44),
+        (r:59,g:35,b:57),
+        (r:77,g:102,b:115),
+        (r:72,g:106,b:128),
+        (r:77,g:83,b:118),
+        (r:71,g:103,b:144),
+        (r:86,g:63,b:45),
+        (r:31,g:57,b:46),
+        (r:61,g:94,b:128),
+        (r:76,g:102,b:152),
+        (r:66,g:90,b:22),
+        (r:83,g:64,b:44),
+        (r:80,g:60,b:20),
+        (r:69,g:82,b:85),
+        (r:56,g:80,b:124),
+    ],
+    GlowingRock: [
+        (r:96,g:0,b:128),
+    ],
+    Water: [
+        (r:0,g:0,b:0),
+    ],
+    Grass: [
+        (r:90,g:110,b:150),
+        (r:128,g:102,b:73),
+        (r:167,g:132,b:79),
+        (r:47,g:71,b:39),
+        (r:94,g:80,b:53),
+        (r:182,g:156,b:99),
+        (r:110,g:100,b:100),
+        (r:12,g:70,b:30),
+        (r:50,g:84,b:76),
+        (r:84,g:76,b:85),
+        (r:62,g:47,b:54),
+        (r:103,g:54,b:36),
+        (r:43,g:106,b:99),
+        (r:32,g:96,b:24),
+        (r:70,g:86,b:19),
+        (r:24,g:89,b:56),
+        (r:28,g:47,b:56),
+        (r:98,g:108,b:132),
+        (r:106,g:81,b:58),
+        (r:94,g:50,b:40),
+        (r:69,g:89,b:114),
+        (r:48,g:41,b:85),
+        (r:156,g:109,b:58),
+        (r:130,g:66,b:23),
+        (r:196,g:180,b:119),
+        (r:82,g:111,b:185),
+        (r:97,g:82,b:19),
+        (r:69,g:82,b:146),
+        (r:45,g:107,b:102),
+        (r:45,g:61,b:103),
+        (r:120,g:103,b:39),
+        (r:151,g:138,b:107),
+        (r:96,g:115,b:57),
+        (r:98,g:113,b:67),
+        (r:66,g:99,b:48),
+        (r:124,g:134,b:74),
+        (r:26,g:20,b:73),
+        (r:59,g:66,b:100),
+        (r:29,g:67,b:32),
+        (r:80,g:66,b:74),
+        (r:61,g:67,b:30),
+        (r:94,g:105,b:88),
+        (r:61,g:110,b:136),
+        (r:59,g:68,b:101),
+        (r:93,g:105,b:12),
+        (r:96,g:73,b:24),
+        (r:124,g:125,b:107),
+        (r:44,g:67,b:70),
+        (r:68,g:68,b:60),
+        (r:95,g:99,b:124),
+        (r:143,g:119,b:88),
+        (r:105,g:118,b:130),
+        (r:102,g:120,b:63),
+        (r:97,g:81,b:86),
+        (r:152,g:117,b:63),
+        (r:60,g:67,b:126),
+        (r:8,g:101,b:33),
+        (r:93,g:81,b:57),
+        (r:69,g:70,b:55),
+        (r:31,g:79,b:58),
+        (r:93,g:106,b:43),
+        (r:30,g:102,b:72),
+        (r:76,g:99,b:67),
+        (r:8,g:56,b:42),
+        (r:131,g:115,b:95),
+        (r:77,g:67,b:49),
+        (r:65,g:92,b:99),
+        (r:120,g:88,b:12),
+        (r:46,g:30,b:63),
+        (r:136,g:90,b:52),
+        (r:70,g:68,b:102),
+        (r:76,g:96,b:167),
+        (r:97,g:96,b:41),
+        (r:56,g:104,b:14),
+        (r:47,g:87,b:56),
+        (r:75,g:68,b:33),
+        (r:45,g:61,b:48),
+        (r:113,g:79,b:35),
+        (r:146,g:116,b:78),
+        (r:125,g:98,b:71),
+        (r:99,g:105,b:73),
+        (r:92,g:87,b:105),
+        (r:50,g:84,b:103),
+        (r:115,g:115,b:116),
+        (r:119,g:116,b:59),
+        (r:25,g:68,b:48),
+        (r:44,g:84,b:101),
+        (r:115,g:118,b:86),
+        (r:95,g:86,b:101),
+        (r:86,g:67,b:29),
+        (r:52,g:91,b:32),
+        (r:52,g:69,b:31),
+        (r:51,g:84,b:22),
+        (r:52,g:84,b:56),
+        (r:137,g:116,b:71),
+        (r:61,g:57,b:79),
+        (r:84,g:88,b:36),
+        (r:40,g:65,b:91),
+        (r:55,g:67,b:51),
+        (r:96,g:62,b:57),
+        (r:53,g:39,b:71),
+        (r:58,g:86,b:57),
+        (r:112,g:89,b:74),
+        (r:39,g:70,b:87),
+        (r:63,g:69,b:81),
+        (r:61,g:68,b:67),
+        (r:70,g:69,b:101),
+        (r:62,g:91,b:91),
+        (r:25,g:67,b:52),
+        (r:132,g:85,b:31),
+        (r:32,g:75,b:26),
+        (r:30,g:47,b:78),
+        (r:70,g:111,b:155),
+        (r:167,g:143,b:96),
+        (r:77,g:95,b:133),
+        (r:53,g:100,b:119),
+        (r:179,g:166,b:116),
+        (r:98,g:63,b:53),
+        (r:96,g:97,b:70),
+        (r:133,g:117,b:70),
+        (r:48,g:105,b:17),
+        (r:49,g:67,b:30),
+        (r:21,g:87,b:37),
+        (r:63,g:85,b:69),
+        (r:83,g:116,b:56),
+        (r:141,g:138,b:89),
+        (r:49,g:49,b:66),
+        (r:81,g:49,b:54),
+        (r:103,g:95,b:71),
+        (r:117,g:86,b:53),
+        (r:97,g:85,b:19),
+        (r:113,g:87,b:31),
+        (r:117,g:84,b:15),
+        (r:42,g:68,b:68),
+        (r:45,g:98,b:37),
+        (r:66,g:82,b:41),
+        (r:74,g:107,b:12),
+        (r:88,g:88,b:17),
+        (r:78,g:90,b:54),
+        (r:88,g:92,b:54),
+        (r:52,g:92,b:33),
+        (r:80,g:93,b:37),
+        (r:68,g:92,b:21),
+        (r:112,g:64,b:23),
+        (r:100,g:100,b:115),
+        (r:117,g:111,b:84),
+        (r:41,g:69,b:56),
+        (r:84,g:68,b:68),
+        (r:75,g:66,b:91),
+        (r:69,g:54,b:39),
+        (r:93,g:92,b:24),
+        (r:99,g:85,b:57),
+        (r:37,g:96,b:57),
+        (r:38,g:95,b:86),
+        (r:108,g:101,b:54),
+        (r:67,g:62,b:63),
+        (r:61,g:73,b:84),
+        (r:52,g:68,b:49),
+        (r:51,g:55,b:39),
+        (r:81,g:93,b:87),
+        (r:31,g:82,b:75),
+        (r:98,g:70,b:32),
+        (r:139,g:107,b:56),
+        (r:128,g:99,b:70),
+        (r:129,g:106,b:36),
+        (r:168,g:153,b:110),
+        (r:59,g:92,b:133),
+        (r:94,g:109,b:141),
+        (r:45,g:44,b:50),
+        (r:145,g:129,b:73),
+        (r:151,g:122,b:81),
+        (r:9,g:86,b:25),
+        (r:90,g:69,b:41),
+        (r:69,g:83,b:143),
+        (r:97,g:83,b:44),
+        (r:51,g:67,b:70),
+        (r:54,g:33,b:59),
+        (r:74,g:51,b:67),
+        (r:63,g:102,b:57),
+        (r:35,g:81,b:45),
+        (r:151,g:136,b:90),
+        (r:84,g:85,b:71),
+        (r:75,g:86,b:57),
+        (r:64,g:89,b:100),
+        (r:55,g:82,b:119),
+        (r:95,g:91,b:82),
+        (r:18,g:89,b:57),
+        (r:69,g:85,b:85),
+        (r:74,g:98,b:146),
+        (r:19,g:102,b:45),
+        (r:79,g:112,b:169),
+        (r:96,g:126,b:69),
+        (r:79,g:83,b:99),
+        (r:52,g:48,b:89),
+        (r:81,g:115,b:63),
+        (r:24,g:54,b:42),
+        (r:121,g:84,b:53),
+        (r:13,g:67,b:31),
+        (r:61,g:96,b:102),
+        (r:87,g:93,b:57),
+        (r:147,g:133,b:103),
+        (r:97,g:82,b:71),
+        (r:99,g:103,b:89),
+        (r:66,g:67,b:65),
+        (r:119,g:121,b:64),
+        (r:50,g:56,b:80),
+        (r:33,g:59,b:61),
+        (r:39,g:33,b:60),
+        (r:28,g:39,b:63),
+        (r:115,g:115,b:99),
+        (r:49,g:97,b:67),
+        (r:42,g:97,b:86),
+        (r:42,g:85,b:57),
+        (r:46,g:73,b:89),
+        (r:113,g:108,b:71),
+        (r:149,g:97,b:47),
+        (r:49,g:69,b:19),
+        (r:29,g:70,b:30),
+        (r:24,g:98,b:25),
+        (r:31,g:95,b:55),
+        (r:26,g:83,b:22),
+        (r:36,g:68,b:71),
+        (r:94,g:66,b:42),
+        (r:85,g:68,b:56),
+        (r:51,g:60,b:64),
+        (r:55,g:83,b:19),
+        (r:58,g:60,b:111),
+        (r:71,g:91,b:110),
+        (r:70,g:81,b:124),
+        (r:68,g:77,b:102),
+        (r:71,g:105,b:143),
+        (r:129,g:118,b:94),
+        (r:94,g:66,b:68),
+        (r:58,g:52,b:65),
+        (r:9,g:75,b:44),
+        (r:115,g:86,b:68),
+        (r:82,g:64,b:63),
+        (r:153,g:116,b:71),
+        (r:123,g:102,b:54),
+        (r:99,g:76,b:72),
+        (r:99,g:110,b:46),
+        (r:30,g:68,b:39),
+        (r:190,g:167,b:106),
+        (r:126,g:81,b:28),
+        (r:50,g:54,b:60),
+        (r:113,g:64,b:40),
+        (r:96,g:92,b:40),
+        (r:68,g:79,b:129),
+        (r:82,g:95,b:14),
+        (r:130,g:116,b:80),
+        (r:79,g:78,b:46),
+        (r:73,g:68,b:33),
+        (r:74,g:88,b:22),
+        (r:51,g:71,b:57),
+        (r:72,g:90,b:52),
+        (r:50,g:85,b:42),
+    ],
+    WeakRock: [
+        (r:90,g:110,b:150),
+        (r:190,g:185,b:207),
+        (r:39,g:22,b:80),
+        (r:71,g:50,b:17),
+        (r:88,g:69,b:110),
+        (r:229,g:147,b:46),
+        (r:209,g:127,b:26),
+        (r:76,g:93,b:128),
+        (r:49,g:46,b:89),
+        (r:75,g:95,b:150),
+        (r:95,g:102,b:127),
+        (r:202,g:197,b:219),
+        (r:75,g:110,b:137),
+        (r:61,g:40,b:7),
+        (r:219,g:137,b:36),
+        (r:90,g:95,b:142),
+        (r:30,g:13,b:71),
+        (r:96,g:77,b:118),
+        (r:40,g:37,b:80),
+        (r:76,g:112,b:154),
+        (r:237,g:155,b:54),
+        (r:89,g:110,b:136),
+        (r:71,g:97,b:139),
+        (r:82,g:103,b:145),
+        (r:86,g:97,b:131),
+        (r:196,g:191,b:213),
+        (r:45,g:28,b:86),
+        (r:82,g:63,b:104),
+        (r:34,g:31,b:74),
+        (r:81,g:95,b:139),
+        (r:90,g:100,b:150),
+        (r:82,g:104,b:135),
+        (r:81,g:113,b:143),
+        (r:98,g:108,b:133),
+        (r:73,g:102,b:132),
+        (r:66,g:45,b:12),
+        (r:76,g:55,b:22),
+        (r:91,g:72,b:113),
+        (r:214,g:132,b:31),
+        (r:224,g:142,b:41),
+        (r:75,g:104,b:150),
+        (r:87,g:104,b:142),
+        (r:84,g:95,b:149),
+        (r:79,g:96,b:131),
+        (r:84,g:103,b:153),
+        (r:91,g:102,b:135),
+        (r:94,g:110,b:143),
+        (r:83,g:110,b:150),
+        (r:75,g:104,b:142),
+        (r:85,g:95,b:148),
+        (r:75,g:110,b:146),
+        (r:85,g:98,b:138),
+        (r:34,g:17,b:75),
+        (r:45,g:42,b:85),
+        (r:233,g:151,b:50),
+        (r:85,g:106,b:148),
+        (r:77,g:97,b:144),
+        (r:84,g:105,b:142),
+        (r:82,g:110,b:138),
+        (r:75,g:104,b:143),
+        (r:85,g:105,b:135),
+        (r:74,g:100,b:155),
+        (r:85,g:110,b:141),
+        (r:77,g:101,b:137),
+        (r:84,g:95,b:143),
+        (r:90,g:95,b:135),
+        (r:84,g:99,b:142),
+        (r:76,g:95,b:136),
+        (r:76,g:95,b:142),
+        (r:79,g:100,b:149),
+        (r:92,g:106,b:139),
+        (r:85,g:95,b:139),
+        (r:84,g:108,b:143),
+        (r:78,g:109,b:142),
+        (r:84,g:99,b:136),
+        (r:87,g:105,b:153),
+        (r:86,g:99,b:144),
+        (r:89,g:100,b:139),
+        (r:89,g:108,b:145),
+        (r:187,g:182,b:204),
+        (r:193,g:188,b:210),
+        (r:199,g:194,b:216),
+        (r:37,g:34,b:77),
+        (r:42,g:25,b:83),
+        (r:85,g:66,b:107),
+        (r:206,g:124,b:23),
+        (r:79,g:107,b:149),
+        (r:79,g:100,b:142),
+        (r:90,g:95,b:149),
+        (r:82,g:114,b:153),
+        (r:76,g:106,b:143),
+        (r:84,g:105,b:148),
+        (r:95,g:108,b:137),
+        (r:90,g:103,b:146),
+        (r:71,g:104,b:139),
+        (r:78,g:105,b:138),
+        (r:73,g:106,b:132),
+        (r:85,g:100,b:150),
+        (r:90,g:102,b:145),
+        (r:82,g:102,b:139),
+        (r:75,g:103,b:135),
+        (r:84,g:100,b:148),
+        (r:90,g:98,b:129),
+        (r:81,g:99,b:143),
+        (r:85,g:109,b:138),
+        (r:75,g:105,b:148),
+        (r:80,g:105,b:145),
+        (r:90,g:106,b:138),
+        (r:90,g:110,b:140),
+        (r:82,g:100,b:132),
+        (r:75,g:102,b:142),
+        (r:80,g:95,b:147),
+        (r:84,g:110,b:142),
+        (r:85,g:110,b:150),
+        (r:75,g:100,b:147),
+        (r:80,g:110,b:146),
+        (r:94,g:105,b:134),
+        (r:81,g:104,b:150),
+        (r:85,g:102,b:141),
+        (r:79,g:108,b:135),
+        (r:78,g:104,b:147),
+        (r:90,g:98,b:138),
+        (r:80,g:97,b:135),
+        (r:90,g:105,b:150),
+        (r:85,g:95,b:135),
+        (r:85,g:109,b:145),
+        (r:87,g:100,b:135),
+        (r:92,g:101,b:131),
+        (r:90,g:103,b:135),
+        (r:82,g:103,b:139),
+        (r:75,g:109,b:150),
+        (r:84,g:108,b:135),
+        (r:85,g:106,b:139),
+        (r:90,g:98,b:146),
+        (r:86,g:95,b:143),
+        (r:84,g:95,b:136),
+        (r:84,g:95,b:142),
+        (r:80,g:105,b:142),
+        (r:76,g:99,b:140),
+        (r:87,g:103,b:149),
+        (r:79,g:101,b:135),
+        (r:78,g:96,b:142),
+        (r:78,g:98,b:138),
+        (r:86,g:102,b:147),
+        (r:79,g:104,b:143),
+        (r:75,g:96,b:147),
+        (r:84,g:96,b:148),
+        (r:83,g:100,b:150),
+        (r:79,g:95,b:150),
+        (r:80,g:101,b:148),
+        (r:75,g:99,b:149),
+        (r:84,g:104,b:148),
+        (r:75,g:100,b:143),
+        (r:80,g:113,b:150),
+        (r:85,g:103,b:145),
+        (r:89,g:104,b:139),
+        (r:75,g:108,b:140),
+        (r:84,g:98,b:145),
+        (r:89,g:107,b:146),
+        (r:90,g:106,b:142),
+        (r:77,g:110,b:143),
+        (r:90,g:103,b:145),
+        (r:75,g:107,b:135),
+        (r:84,g:106,b:138),
+        (r:88,g:95,b:138),
+        (r:78,g:98,b:148),
+        (r:79,g:101,b:145),
+        (r:77,g:105,b:139),
+        (r:85,g:109,b:146),
+        (r:88,g:95,b:146),
+        (r:84,g:97,b:139),
+        (r:78,g:110,b:138),
+        (r:78,g:103,b:135),
+        (r:85,g:99,b:139),
+        (r:87,g:104,b:138),
+        (r:89,g:102,b:138),
+        (r:84,g:110,b:146),
+        (r:32,g:15,b:73),
+        (r:36,g:19,b:77),
+        (r:68,g:47,b:14),
+        (r:73,g:52,b:19),
+        (r:64,g:43,b:10),
+        (r:47,g:44,b:87),
+        (r:93,g:74,b:115),
+        (r:42,g:39,b:82),
+        (r:90,g:71,b:112),
+        (r:77,g:110,b:142),
+        (r:221,g:139,b:38),
+        (r:226,g:144,b:43),
+        (r:217,g:135,b:34),
+        (r:231,g:149,b:48),
+        (r:212,g:130,b:29),
+        (r:75,g:99,b:135),
+        (r:85,g:102,b:137),
+        (r:235,g:153,b:52),
+        (r:87,g:97,b:150),
+        (r:77,g:96,b:139),
+        (r:77,g:107,b:146),
+        (r:82,g:105,b:149),
+        (r:80,g:107,b:148),
+        (r:83,g:102,b:135),
+        (r:89,g:96,b:139),
+        (r:90,g:100,b:144),
+        (r:87,g:99,b:145),
+        (r:84,g:103,b:149),
+        (r:88,g:107,b:135),
+        (r:78,g:102,b:138),
+        (r:80,g:96,b:143),
+        (r:76,g:106,b:149),
+        (r:81,g:98,b:140),
+        (r:81,g:106,b:139),
+        (r:80,g:110,b:149),
+        (r:86,g:103,b:146),
+        (r:81,g:109,b:143),
+        (r:86,g:106,b:145),
+        (r:81,g:98,b:146),
+        (r:78,g:95,b:147),
+        (r:90,g:99,b:135),
+        (r:78,g:104,b:149),
+        (r:75,g:103,b:148),
+        (r:84,g:100,b:137),
+        (r:78,g:95,b:137),
+        (r:83,g:105,b:143),
+        (r:85,g:110,b:135),
+        (r:74,g:97,b:138),
+        (r:81,g:110,b:141),
+        (r:85,g:107,b:142),
+        (r:87,g:102,b:144),
+        (r:82,g:103,b:132),
+        (r:75,g:102,b:139),
+        (r:75,g:95,b:143),
+        (r:90,g:103,b:138),
+        (r:90,g:98,b:141),
+        (r:77,g:107,b:142),
+        (r:87,g:97,b:136),
+        (r:78,g:95,b:136),
+        (r:89,g:102,b:148),
+        (r:87,g:108,b:140),
+        (r:85,g:103,b:139),
+        (r:85,g:95,b:138),
+        (r:78,g:103,b:141),
+        (r:75,g:103,b:138),
+        (r:81,g:104,b:148),
+        (r:83,g:108,b:148),
+        (r:78,g:101,b:148),
+        (r:81,g:98,b:137),
+        (r:89,g:97,b:144),
+        (r:79,g:95,b:143),
+        (r:85,g:95,b:145),
+        (r:75,g:102,b:135),
+        (r:82,g:97,b:150),
+        (r:77,g:105,b:136),
+        (r:84,g:101,b:144),
+        (r:87,g:98,b:141),
+        (r:90,g:102,b:141),
+        (r:73,g:96,b:141),
+    ],
+    Rock: [
+        (r:90,g:110,b:150),
+        (r:63,g:77,b:105),
+        (r:90,g:94,b:122),
+        (r:95,g:81,b:93),
+        (r:115,g:112,b:112),
+        (r:59,g:107,b:116),
+        (r:150,g:150,b:175),
+        (r:55,g:53,b:74),
+        (r:85,g:59,b:58),
+        (r:91,g:122,b:181),
+        (r:40,g:98,b:87),
+        (r:119,g:89,b:76),
+        (r:69,g:90,b:79),
+        (r:77,g:64,b:84),
+        (r:66,g:86,b:130),
+        (r:40,g:74,b:78),
+        (r:68,g:112,b:139),
+        (r:90,g:92,b:118),
+        (r:108,g:111,b:122),
+        (r:101,g:72,b:70),
+        (r:56,g:105,b:120),
+        (r:83,g:131,b:157),
+        (r:54,g:55,b:97),
+        (r:77,g:95,b:100),
+        (r:89,g:114,b:119),
+        (r:112,g:95,b:96),
+        (r:79,g:84,b:119),
+        (r:80,g:70,b:78),
+        (r:70,g:63,b:60),
+        (r:90,g:101,b:99),
+        (r:80,g:78,b:107),
+        (r:56,g:95,b:99),
+        (r:59,g:73,b:85),
+        (r:78,g:95,b:145),
+        (r:93,g:119,b:132),
+        (r:75,g:108,b:122),
+        (r:86,g:109,b:168),
+        (r:77,g:104,b:117),
+        (r:44,g:108,b:102),
+        (r:61,g:72,b:120),
+        (r:79,g:77,b:97),
+        (r:43,g:67,b:62),
+        (r:49,g:77,b:90),
+        (r:66,g:67,b:90),
+        (r:99,g:129,b:150),
+        (r:60,g:87,b:119),
+        (r:55,g:90,b:89),
+        (r:103,g:100,b:110),
+        (r:56,g:64,b:113),
+        (r:79,g:81,b:89),
+        (r:62,g:55,b:89),
+        (r:67,g:86,b:90),
+        (r:91,g:102,b:136),
+        (r:75,g:115,b:158),
+        (r:102,g:107,b:125),
+        (r:71,g:53,b:73),
+        (r:78,g:84,b:120),
+        (r:90,g:116,b:153),
+        (r:84,g:101,b:154),
+        (r:81,g:123,b:147),
+        (r:93,g:134,b:171),
+        (r:106,g:82,b:82),
+        (r:80,g:82,b:89),
+        (r:68,g:70,b:73),
+        (r:80,g:93,b:107),
+        (r:43,g:98,b:91),
+        (r:78,g:96,b:130),
+        (r:43,g:51,b:66),
+        (r:126,g:120,b:107),
+        (r:95,g:89,b:105),
+        (r:86,g:88,b:116),
+        (r:99,g:90,b:100),
+        (r:116,g:90,b:83),
+        (r:66,g:96,b:109),
+        (r:54,g:68,b:72),
+        (r:67,g:96,b:120),
+        (r:48,g:53,b:86),
+        (r:93,g:73,b:82),
+        (r:67,g:75,b:118),
+        (r:79,g:80,b:111),
+        (r:51,g:82,b:95),
+        (r:72,g:83,b:107),
+        (r:67,g:81,b:91),
+        (r:106,g:89,b:94),
+        (r:78,g:52,b:61),
+        (r:47,g:77,b:88),
+        (r:62,g:77,b:87),
+        (r:58,g:79,b:72),
+        (r:79,g:82,b:95),
+        (r:81,g:103,b:119),
+        (r:81,g:111,b:135),
+        (r:87,g:101,b:123),
+        (r:79,g:101,b:145),
+        (r:88,g:70,b:67),
+        (r:101,g:120,b:118),
+        (r:105,g:118,b:133),
+        (r:90,g:100,b:134),
+        (r:82,g:89,b:100),
+        (r:117,g:107,b:100),
+        (r:81,g:59,b:71),
+        (r:80,g:69,b:91),
+        (r:48,g:66,b:85),
+        (r:57,g:83,b:107),
+        (r:82,g:121,b:171),
+        (r:76,g:75,b:78),
+        (r:66,g:99,b:133),
+        (r:63,g:64,b:102),
+        (r:79,g:65,b:69),
+        (r:90,g:90,b:91),
+        (r:71,g:101,b:134),
+        (r:40,g:75,b:78),
+        (r:105,g:108,b:119),
+        (r:75,g:112,b:149),
+        (r:95,g:125,b:192),
+        (r:93,g:120,b:144),
+        (r:100,g:100,b:120),
+        (r:71,g:74,b:86),
+        (r:92,g:103,b:113),
+        (r:61,g:56,b:63),
+        (r:60,g:68,b:87),
+        (r:60,g:58,b:76),
+        (r:59,g:61,b:86),
+        (r:45,g:59,b:76),
+        (r:58,g:56,b:63),
+        (r:77,g:93,b:112),
+        (r:97,g:125,b:151),
+        (r:117,g:118,b:120),
+        (r:51,g:102,b:109),
+        (r:98,g:111,b:139),
+        (r:55,g:112,b:129),
+        (r:78,g:120,b:141),
+        (r:78,g:102,b:143),
+        (r:79,g:68,b:90),
+        (r:55,g:71,b:98),
+        (r:91,g:124,b:161),
+        (r:89,g:112,b:124),
+        (r:73,g:72,b:105),
+        (r:67,g:96,b:95),
+        (r:65,g:104,b:119),
+        (r:61,g:86,b:101),
+        (r:68,g:86,b:117),
+        (r:60,g:95,b:111),
+        (r:78,g:73,b:77),
+        (r:81,g:100,b:120),
+        (r:79,g:101,b:131),
+        (r:65,g:108,b:127),
+        (r:86,g:77,b:98),
+        (r:83,g:81,b:86),
+        (r:89,g:74,b:87),
+        (r:56,g:63,b:90),
+        (r:91,g:94,b:107),
+        (r:102,g:98,b:108),
+        (r:102,g:104,b:119),
+        (r:103,g:90,b:99),
+        (r:110,g:121,b:116),
+        (r:68,g:80,b:121),
+        (r:80,g:112,b:147),
+        (r:78,g:109,b:135),
+        (r:60,g:86,b:91),
+        (r:54,g:81,b:101),
+        (r:113,g:89,b:85),
+        (r:80,g:90,b:119),
+        (r:76,g:93,b:90),
+        (r:93,g:83,b:86),
+        (r:67,g:101,b:120),
+        (r:100,g:100,b:98),
+        (r:67,g:64,b:81),
+        (r:46,g:49,b:77),
+        (r:89,g:89,b:92),
+        (r:106,g:114,b:108),
+        (r:59,g:51,b:86),
+        (r:75,g:90,b:87),
+        (r:107,g:90,b:89),
+        (r:50,g:111,b:113),
+        (r:102,g:118,b:128),
+        (r:36,g:67,b:69),
+        (r:59,g:75,b:90),
+        (r:103,g:83,b:87),
+        (r:81,g:110,b:152),
+        (r:46,g:87,b:87),
+        (r:61,g:83,b:111),
+        (r:71,g:96,b:119),
+        (r:64,g:87,b:87),
+        (r:65,g:69,b:110),
+        (r:65,g:79,b:108),
+        (r:64,g:74,b:99),
+        (r:64,g:63,b:99),
+        (r:62,g:71,b:116),
+        (r:63,g:81,b:115),
+        (r:49,g:90,b:90),
+        (r:84,g:116,b:161),
+        (r:60,g:71,b:78),
+        (r:86,g:100,b:146),
+        (r:111,g:105,b:107),
+        (r:72,g:81,b:102),
+        (r:85,g:70,b:86),
+        (r:65,g:77,b:78),
+        (r:67,g:61,b:70),
+        (r:54,g:48,b:66),
+        (r:54,g:82,b:80),
+        (r:70,g:88,b:99),
+        (r:85,g:90,b:99),
+        (r:67,g:47,b:67),
+        (r:97,g:101,b:120),
+        (r:88,g:83,b:106),
+        (r:86,g:107,b:142),
+        (r:94,g:105,b:134),
+        (r:80,g:101,b:135),
+        (r:74,g:81,b:119),
+        (r:71,g:76,b:89),
+        (r:86,g:110,b:134),
+        (r:60,g:54,b:90),
+        (r:50,g:88,b:102),
+        (r:89,g:117,b:136),
+        (r:90,g:116,b:174),
+        (r:100,g:122,b:135),
+        (r:101,g:111,b:134),
+        (r:80,g:88,b:109),
+        (r:78,g:101,b:128),
+        (r:98,g:96,b:116),
+        (r:50,g:74,b:89),
+        (r:72,g:67,b:97),
+        (r:61,g:96,b:117),
+        (r:78,g:86,b:104),
+        (r:61,g:98,b:103),
+        (r:75,g:87,b:129),
+        (r:49,g:101,b:99),
+        (r:79,g:62,b:59),
+        (r:60,g:56,b:73),
+        (r:74,g:65,b:74),
+        (r:73,g:56,b:75),
+        (r:58,g:61,b:77),
+        (r:53,g:72,b:77),
+        (r:44,g:69,b:73),
+        (r:43,g:60,b:72),
+        (r:70,g:61,b:89),
+        (r:45,g:49,b:75),
+        (r:55,g:47,b:77),
+        (r:82,g:99,b:138),
+        (r:62,g:81,b:96),
+        (r:52,g:62,b:102),
+        (r:79,g:88,b:105),
+        (r:66,g:51,b:77),
+        (r:82,g:91,b:124),
+        (r:107,g:99,b:102),
+        (r:61,g:90,b:105),
+        (r:118,g:118,b:118),
+        (r:62,g:65,b:64),
+        (r:92,g:75,b:73),
+        (r:70,g:93,b:138),
+        (r:76,g:97,b:121),
+        (r:81,g:99,b:129),
+        (r:103,g:110,b:129),
+        (r:77,g:100,b:138),
+        (r:87,g:65,b:74),
+        (r:72,g:74,b:90),
+    ],
+}
\ No newline at end of file
diff --git a/world/examples/world_block_statistics.rs b/world/examples/world_block_statistics.rs
index dbd4d2948c..a6c0138e8b 100644
--- a/world/examples/world_block_statistics.rs
+++ b/world/examples/world_block_statistics.rs
@@ -1,5 +1,6 @@
+use clap::{App, Arg, SubCommand};
 use common::{
-    terrain::TerrainChunkSize,
+    terrain::{BlockKind, TerrainChunkSize},
     vol::{IntoVolIterator, RectVolSize},
 };
 use fallible_iterator::FallibleIterator;
@@ -12,6 +13,9 @@ use rusqlite::{Connection, ToSql, Transaction, TransactionBehavior, NO_PARAMS};
 use std::{
     collections::{HashMap, HashSet},
     error::Error,
+    fs::File,
+    io::Write,
+    str::FromStr,
     sync::mpsc,
     time::{SystemTime, UNIX_EPOCH},
 };
@@ -21,8 +25,8 @@ use veloren_world::{
     World,
 };
 
-fn block_statistics_db() -> Result<Connection, Box<dyn Error>> {
-    let conn = Connection::open("block_statistics.sqlite")?;
+fn block_statistics_db(db_path: &str) -> Result<Connection, Box<dyn Error>> {
+    let conn = Connection::open(db_path)?;
     #[rustfmt::skip]
     conn.execute_batch("
     CREATE TABLE IF NOT EXISTS chunk (
@@ -54,7 +58,7 @@ fn block_statistics_db() -> Result<Connection, Box<dyn Error>> {
     Ok(conn)
 }
 
-fn main() -> Result<(), Box<dyn Error>> {
+fn generate(db_path: &str, ymin: Option<i32>, ymax: Option<i32>) -> Result<(), Box<dyn Error>> {
     common_frontend::init_stdout(None);
     println!("Loading world");
     let pool = ThreadPoolBuilder::new().build().unwrap();
@@ -68,7 +72,7 @@ fn main() -> Result<(), Box<dyn Error>> {
     );
     println!("Loaded world");
 
-    let conn = block_statistics_db()?;
+    let conn = block_statistics_db(db_path)?;
 
     let existing_chunks: HashSet<(i32, i32)> = conn
         .prepare("SELECT xcoord, ycoord FROM chunk")?
@@ -79,13 +83,13 @@ fn main() -> Result<(), Box<dyn Error>> {
     let sz = world.sim().get_size();
     let (tx, rx) = mpsc::channel();
     rayon::spawn(move || {
-        let coords: Vec<_> = (1..sz.y)
+        let coords: Vec<_> = (ymin.unwrap_or(1)..ymax.unwrap_or(sz.y as i32))
             .into_iter()
             .flat_map(move |y| {
                 let tx = tx.clone();
-                (1..sz.x)
+                (1..sz.x as i32)
                     .into_iter()
-                    .map(move |x| (tx.clone(), x as i32, y as i32))
+                    .map(move |x| (tx.clone(), x, y))
             })
             .collect();
         coords.into_par_iter().for_each(|(tx, x, y)| {
@@ -107,7 +111,7 @@ fn main() -> Result<(), Box<dyn Error>> {
                 let hi = TerrainChunkSize::RECT_SIZE.as_().with_z(chunk.get_max_z());
                 let height = chunk.get_max_z() - chunk.get_min_z();
                 for (_, block) in chunk.vol_iter(lo, hi) {
-                    let mut rgb = block.get_color().unwrap_or(Rgb::new(0, 0, 0));
+                    let mut rgb = block.get_color().unwrap_or_else(|| Rgb::new(0, 0, 0));
                     let color: [f32; 3] = [rgb.r as _, rgb.g as _, rgb.b as _];
                     if let Ok((dist, nearest)) =
                         block_colors.nearest_one(&color, &squared_euclidean)
@@ -152,7 +156,7 @@ fn main() -> Result<(), Box<dyn Error>> {
             REPLACE INTO chunk (xcoord, ycoord, height, start_time, end_time)
             VALUES (?1, ?2, ?3, ?4, ?5)
         ")?;
-        println!("Inserting results for chunk at ({}, {})", x, y);
+        println!("Inserting results for chunk at ({}, {}): {}", x, y, i);
         for ((kind, color), count) in block_counts.iter() {
             insert_block.execute(&[
                 &x as &dyn ToSql,
@@ -182,3 +186,99 @@ fn main() -> Result<(), Box<dyn Error>> {
     }
     Ok(())
 }
+
+fn palette(conn: Connection) -> Result<(), Box<dyn Error>> {
+    let mut stmt =
+        conn.prepare("SELECT kind, r, g, b, SUM(quantity) FROM block GROUP BY kind, r, g, b")?;
+    let mut block_colors: HashMap<BlockKind, Vec<(Rgb<u8>, i64)>> = HashMap::new();
+
+    let mut rows = stmt.query(NO_PARAMS)?;
+    while let Some(row) = rows.next()? {
+        let kind = BlockKind::from_str(&row.get::<_, String>(0)?)?;
+        let rgb: Rgb<u8> = Rgb::new(row.get(1)?, row.get(2)?, row.get(3)?);
+        let count: i64 = row.get(4)?;
+        block_colors
+            .entry(kind)
+            .or_insert_with(Vec::new)
+            .push((rgb, count));
+    }
+    for (_, v) in block_colors.iter_mut() {
+        v.sort_by(|a, b| b.1.cmp(&a.1));
+    }
+
+    let mut palettes: HashMap<BlockKind, Vec<Rgb<u8>>> = HashMap::new();
+    for (kind, colors) in block_colors.iter() {
+        let palette = palettes.entry(*kind).or_insert_with(Vec::new);
+        if colors.len() <= 256 {
+            for (color, _) in colors {
+                palette.push(*color);
+            }
+            println!("{:?}: {:?}", kind, palette);
+            continue;
+        }
+        let mut radius = 1024.0;
+        let mut tree = KdTree::<f32, Rgb<u8>, 3>::new();
+        while palette.len() < 256 {
+            if let Some((color, _)) = colors.iter().find(|(color, _)| {
+                tree.nearest_one(
+                    &[color.r as f32, color.g as f32, color.b as f32],
+                    &squared_euclidean,
+                )
+                .map(|(dist, _)| dist > radius)
+                .unwrap_or(true)
+            }) {
+                palette.push(*color);
+                tree.add(&[color.r as f32, color.g as f32, color.b as f32], *color)?;
+                println!("{:?}, {:?}: {:?}", kind, radius, *color);
+            } else {
+                radius -= 1.0;
+            }
+        }
+    }
+    let mut f = File::create("palettes.ron")?;
+    let pretty = ron::ser::PrettyConfig::default().with_depth_limit(2);
+    write!(f, "{}", ron::ser::to_string_pretty(&palettes, pretty)?)?;
+    Ok(())
+}
+
+fn main() -> Result<(), Box<dyn Error>> {
+    let mut app = App::new("world_block_statistics")
+        .version(common::util::DISPLAY_VERSION_LONG.as_str())
+        .author("The veloren devs <https://gitlab.com/veloren/veloren>")
+        .about("Compute and process block statistics on generated chunks")
+        .subcommand(
+            SubCommand::with_name("generate")
+                .about("Generate block statistics")
+                .args(&[
+                    Arg::with_name("database")
+                        .required(true)
+                        .help("File to generate/resume generation"),
+                    Arg::with_name("ymin").long("ymin").takes_value(true),
+                    Arg::with_name("ymax").long("ymax").takes_value(true),
+                ]),
+        )
+        .subcommand(
+            SubCommand::with_name("palette")
+                .about("Compute a palette from previously gathered statistics")
+                .args(&[Arg::with_name("database").required(true)]),
+        );
+
+    let matches = app.clone().get_matches();
+    match matches.subcommand() {
+        ("generate", Some(matches)) => {
+            let db_path = matches.value_of("database").expect("database is required");
+            let ymin = matches.value_of("ymin").and_then(|x| i32::from_str(x).ok());
+            let ymax = matches.value_of("ymax").and_then(|x| i32::from_str(x).ok());
+            generate(db_path, ymin, ymax)?;
+        },
+        ("palette", Some(matches)) => {
+            let conn =
+                Connection::open(&matches.value_of("database").expect("database is required"))?;
+            palette(conn)?;
+        },
+        _ => {
+            app.print_help()?;
+        },
+    }
+    Ok(())
+}