diff --git a/Cargo.lock b/Cargo.lock index e7d6abc..1a59f70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,6 +158,17 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +[[package]] +name = "bitfield-struct" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc92b6a6ac8f8176ab4764440f5129ad73d557c532b7f5c324a71846fd25a9c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -296,9 +307,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", @@ -400,7 +411,7 @@ dependencies = [ [[package]] name = "egui-inspect" version = "0.1.0" -source = "git+https://github.com/crumblingstatue/egui-inspect.git#5cf1f05c0f4f6625eb9a46ee0faebdb27919f9bf" +source = "git+https://github.com/crumblingstatue/egui-inspect.git#77b02370966aad6be6eeb94ce88ae9268986fc0d" dependencies = [ "egui", "egui-inspect-derive", @@ -409,11 +420,11 @@ dependencies = [ [[package]] name = "egui-inspect-derive" version = "0.1.0" -source = "git+https://github.com/crumblingstatue/egui-inspect.git#5cf1f05c0f4f6625eb9a46ee0faebdb27919f9bf" +source = "git+https://github.com/crumblingstatue/egui-inspect.git#77b02370966aad6be6eeb94ce88ae9268986fc0d" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -504,7 +515,7 @@ dependencies = [ "flume", "half", "lebe", - "miniz_oxide", + "miniz_oxide 0.6.2", "rayon-core", "smallvec", "zune-inflate", @@ -519,6 +530,15 @@ dependencies = [ "instant", ] +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + [[package]] name = "flate2" version = "1.0.25" @@ -526,7 +546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.6.2", ] [[package]] @@ -930,6 +950,7 @@ name = "mantle-diver" version = "0.1.0" dependencies = [ "anyhow", + "bitfield-struct", "clap", "derivative", "directories", @@ -980,6 +1001,16 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + [[package]] name = "nanorand" version = "0.7.0" @@ -1166,14 +1197,15 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "png" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" dependencies = [ "bitflags", "crc32fast", + "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.1", ] [[package]] @@ -1978,9 +2010,9 @@ dependencies = [ [[package]] name = "zune-inflate" -version = "0.2.51" +version = "0.2.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01728b79fb9b7e28a8c11f715e1cd8dc2cda7416a007d66cac55cebb3a8ac6b" +checksum = "440a08fd59c6442e4b846ea9b10386c38307eae728b216e1ab2c305d1c9daaf8" dependencies = [ "simd-adler32", ] diff --git a/Cargo.toml b/Cargo.toml index d92c34b..fae2495 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ directories = "5.0.0" texture_packer = "0.25.0" walkdir = "2.3.3" image = "0.24.6" +bitfield-struct = "0.4.1" [dependencies.s2dc] #git = "https://github.com/crumblingstatue/s2dc.git" diff --git a/design/data.md b/design/data.md new file mode 100644 index 0000000..8cc7246 --- /dev/null +++ b/design/data.md @@ -0,0 +1,11 @@ +Tile + +9 bits bg +9 bits mid +9 bits fg 32 bits +3 bits slope +2 bits fg state (0: fg has ore, 1: bg has ore, 2: both have ores) + +5 bits liquid type +6 bits paint 16 bits +5 bits reserved \ No newline at end of file diff --git a/res/graphics/tiles/unknown_bg.png b/res/graphics/tiles/unknown_bg.png new file mode 100644 index 0000000..cf5f15e Binary files /dev/null and b/res/graphics/tiles/unknown_bg.png differ diff --git a/res/graphics/tiles/unknown_fg.png b/res/graphics/tiles/unknown_fg.png new file mode 100644 index 0000000..3be1c3c Binary files /dev/null and b/res/graphics/tiles/unknown_fg.png differ diff --git a/res/graphics/tiles/unknown_mid.png b/res/graphics/tiles/unknown_mid.png new file mode 100644 index 0000000..0367625 Binary files /dev/null and b/res/graphics/tiles/unknown_mid.png differ diff --git a/src/app.rs b/src/app.rs index 2357f3e..d5f17dd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -23,6 +23,7 @@ use crate::{ inventory::{ItemId, Slot, TileLayer, UseAction}, math::{center_offset, TILE_SIZE}, res::Res, + tiles::TileId, CliArgs, }; @@ -158,9 +159,12 @@ impl App { .clamp(-terminal_velocity, terminal_velocity); let mut on_screen_tile_ents = Vec::new(); for_each_tile_on_screen(self.game.camera_offset, self.rt.size(), |tp, _sp| { - let tid = self.game.world.tile_at_mut(tp, &self.game.worldgen).mid; - let tdef = &self.game.tile_db[tid]; - let Some(bb) = tdef.bb else { + let tile = self.game.world.tile_at_mut(tp, &self.game.worldgen).mid; + if tile.empty() { + return; + } + let tdef = &self.game.tile_db[tile]; + let Some(bb) = tdef.layer.bb else { return; }; let x = tp.x as i32 * TILE_SIZE as i32; @@ -173,7 +177,7 @@ impl App { ); on_screen_tile_ents.push(TileColEn { col: en, - platform: tdef.platform, + platform: tdef.layer.platform, }); }); imm_dbg!(on_screen_tile_ents.len()); @@ -264,27 +268,25 @@ impl App { let def = &self.game.itemdb.db[active_slot.id as usize]; let t = self.game.world.tile_at_mut(mouse_tpos, &self.game.worldgen); match &def.use_action { - UseAction::PlaceTile { layer, id } => match layer { - TileLayer::Bg => { - if t.bg == 0 { - t.bg = *id - } + UseAction::PlaceBgTile { id } => { + if t.bg.empty() { + t.bg = *id } - TileLayer::Mid => { - if t.mid == 0 { - t.mid = *id - } + } + UseAction::PlaceMidTile { id } => { + if t.mid.empty() { + t.mid = *id } - TileLayer::Fg => { - if t.fg == 0 { - t.fg = *id - } + } + UseAction::PlaceFgTile { id } => { + if t.fg.empty() { + t.fg = *id } - }, + } UseAction::RemoveTile { layer } => match layer { - TileLayer::Bg => t.bg = 0, - TileLayer::Mid => t.mid = 0, - TileLayer::Fg => t.fg = 0, + TileLayer::Bg => t.bg = TileId::EMPTY, + TileLayer::Mid => t.mid = TileId::EMPTY, + TileLayer::Fg => t.fg = TileId::EMPTY, }, } } diff --git a/src/game.rs b/src/game.rs index 5d39a50..8a69efd 100644 --- a/src/game.rs +++ b/src/game.rs @@ -17,7 +17,7 @@ use crate::{ math::{smoothwave, wp_to_tp, WorldPos}, res::Res, tiles::TileDb, - world::{Tile, TilePos, World}, + world::{TilePos, World}, worldgen::Worldgen, }; @@ -77,11 +77,11 @@ impl GameState { for_each_tile_on_screen(self.camera_offset, rt.size(), |tp, sp| { let tile = self.world.tile_at_mut(tp, &self.worldgen); s.set_position(sp.to_sf_vec()); - if tile.bg != Tile::EMPTY { + if !tile.bg.empty() { s.set_texture_rect(self.tile_db[tile.bg].tex_rect.to_sf()); rt.draw(&s); } - if tile.mid != Tile::EMPTY { + if !tile.mid.empty() { s.set_texture_rect(self.tile_db[tile.mid].tex_rect.to_sf()); if let Some(light) = self.tile_db[tile.mid].light { let pos = ScreenVec { @@ -92,7 +92,7 @@ impl GameState { } rt.draw(&s); } - if tile.fg != Tile::EMPTY { + if !tile.fg.empty() { s.set_texture_rect(self.tile_db[tile.fg].tex_rect.to_sf()); rt.draw(&s); } diff --git a/src/inventory.rs b/src/inventory.rs index 7c2f22e..6c4f841 100644 --- a/src/inventory.rs +++ b/src/inventory.rs @@ -1,6 +1,9 @@ use egui_inspect::derive::Inspect; -use crate::{math::IntRect, world::TileId}; +use crate::{ + math::IntRect, + tiles::{BgTileId, FgTileId, MidTileId}, +}; /// We won't have more than 65535 different items pub type ItemId = u16; @@ -63,7 +66,9 @@ pub enum TileLayer { #[derive(Debug)] pub enum UseAction { - PlaceTile { layer: TileLayer, id: TileId }, + PlaceBgTile { id: BgTileId }, + PlaceMidTile { id: MidTileId }, + PlaceFgTile { id: FgTileId }, RemoveTile { layer: TileLayer }, } @@ -80,9 +85,8 @@ impl Default for ItemDb { name: String::from("Dirt Block"), graphic_name: String::from("tiles/dirt"), tex_rect: IntRect::default(), - use_action: UseAction::PlaceTile { - layer: TileLayer::Mid, - id: 3, + use_action: UseAction::PlaceMidTile { + id: MidTileId::DIRT, }, consumable: true, }, @@ -90,9 +94,8 @@ impl Default for ItemDb { name: String::from("Torch"), graphic_name: String::from("tiles/torch"), tex_rect: IntRect::default(), - use_action: UseAction::PlaceTile { - layer: TileLayer::Mid, - id: 4, + use_action: UseAction::PlaceMidTile { + id: MidTileId::TORCH, }, consumable: true, }, @@ -100,9 +103,8 @@ impl Default for ItemDb { name: String::from("Platform"), graphic_name: String::from("tiles/platform"), tex_rect: IntRect::default(), - use_action: UseAction::PlaceTile { - layer: TileLayer::Mid, - id: 5, + use_action: UseAction::PlaceMidTile { + id: MidTileId::PLATFORM, }, consumable: true, }, @@ -119,9 +121,8 @@ impl Default for ItemDb { name: String::from("Panzerium"), graphic_name: String::from("tiles/panzerium"), tex_rect: IntRect::default(), - use_action: UseAction::PlaceTile { - layer: TileLayer::Mid, - id: 6, + use_action: UseAction::PlaceMidTile { + id: MidTileId::PANZERIUM, }, consumable: true, }, diff --git a/src/tiles.rs b/src/tiles.rs index fbdbd26..4b6288e 100644 --- a/src/tiles.rs +++ b/src/tiles.rs @@ -1,26 +1,186 @@ pub mod tiledb_edit_ui; -use std::ops::Index; +use std::{fmt::Debug, marker::PhantomData, ops::Index}; -use egui_inspect::derive::Inspect; +use egui_inspect::{derive::Inspect, Inspect}; use serde::{Deserialize, Serialize}; use crate::{ - graphics::{ScreenSc, ScreenVec}, + graphics::ScreenVec, math::{IntRect, TILE_SIZE}, texture_atlas::RectMap, - world::TileId, }; -#[derive(Serialize, Deserialize, Default, Debug, Inspect)] -pub struct TileDef { - pub bb: Option, +#[derive(Inspect, PartialEq, Eq)] +pub struct TileId(pub u16, PhantomData); + +impl Copy for TileId {} +impl Clone for TileId { + fn clone(&self) -> Self { + Self(self.0, PhantomData) + } +} +impl Debug for TileId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("TileId").field(&self.0).finish() + } +} + +impl TileId { + pub fn empty(&self) -> bool { + self.0 == 0 + } + pub const EMPTY: Self = Self(0, PhantomData); +} + +#[derive(Debug)] +pub enum Bg {} +#[derive(Debug)] +pub enum Mid {} +#[derive(Debug)] +pub enum Fg {} + +impl Bg { + pub fn unknown_def() -> TileDef { + TileDef { + light: Some(ScreenVec { x: 0, y: 0 }), + graphic_name: String::from("tiles/unknown_bg"), + tex_rect: IntRect { + x: 0, + y: 0, + w: 0, + h: 0, + }, + layer: (), + } + } +} + +impl Mid { + pub fn unknown_def() -> TileDef { + TileDef { + light: Some(ScreenVec { x: 0, y: 0 }), + graphic_name: String::from("tiles/unknown_mid"), + tex_rect: IntRect { + x: 0, + y: 0, + w: 0, + h: 0, + }, + layer: MidDef { + platform: true, + bb: Some(TileBb { + x: 0, + y: 0, + w: 32, + h: 32, + }), + }, + } + } +} + +impl Fg { + pub fn unknown_def() -> TileDef { + TileDef { + light: Some(ScreenVec { x: 0, y: 0 }), + graphic_name: String::from("tiles/unknown_fg"), + tex_rect: IntRect { + x: 0, + y: 0, + w: 0, + h: 0, + }, + layer: (), + } + } +} + +pub trait TileLayer { + /// Definitions specific to this layer + type SpecificDef; +} + +impl TileLayer for Bg { + type SpecificDef = (); +} + +impl TileLayer for Mid { + type SpecificDef = MidDef; +} + +impl TileLayer for Fg { + type SpecificDef = (); +} + +pub type BgTileId = TileId; +pub type MidTileId = TileId; +pub type FgTileId = TileId; + +impl BgTileId { + pub const DIRT: Self = Self(1, PhantomData); + pub const STONE: Self = Self(2, PhantomData); +} + +impl MidTileId { + pub const DIRT: Self = Self(1, PhantomData); + pub const STONE: Self = Self(2, PhantomData); + pub const TORCH: Self = Self(3, PhantomData); + pub const PLATFORM: Self = Self(4, PhantomData); + pub const PANZERIUM: Self = Self(5, PhantomData); + pub const UNBREAKANIUM: Self = Self(6, PhantomData); +} + +impl FgTileId { + pub const COAL: Self = Self(1, PhantomData); +} + +#[derive(Serialize, Deserialize, Inspect)] +pub struct TileDef +where + Layer::SpecificDef: Debug + Inspect, +{ /// Whether the tile emits light, and the light source offset pub light: Option, - /// Platform behavior: Horizontally passable, vertically passable upwards - pub platform: bool, pub graphic_name: String, pub tex_rect: IntRect, + pub layer: Layer::SpecificDef, +} + +#[derive(Debug, Inspect, Default, Serialize, Deserialize)] +pub struct MidDef { + /// Platform behavior: Horizontally passable, vertically passable upwards + pub platform: bool, + /// Collision bounding box + pub bb: Option, +} + +impl Debug for TileDef +where + Layer::SpecificDef: Debug + Inspect, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TileDef") + .field("light", &self.light) + .field("graphic_name", &self.graphic_name) + .field("tex_rect", &self.tex_rect) + .field("layer", &self.layer) + .finish() + } +} + +impl Default for TileDef +where + Layer::SpecificDef: Default + Debug + Inspect, +{ + fn default() -> Self { + Self { + light: Default::default(), + graphic_name: Default::default(), + tex_rect: Default::default(), + layer: Layer::SpecificDef::default(), + } + } } const DEFAULT_TILE_BB: TileBb = TileBb { @@ -40,49 +200,54 @@ pub struct TileBb { #[derive(Serialize, Deserialize, Debug, Inspect)] pub struct TileDb { - db: Vec, + unknown_bg: TileDef, + unknown_mid: TileDef, + unknown_fg: TileDef, + bg: Vec>, + mid: Vec>, + fg: Vec>, } impl Default for TileDb { fn default() -> Self { - let unknown = TileDef { - bb: None, - light: Some(ScreenVec { - x: TILE_SIZE as ScreenSc / 2, - y: TILE_SIZE as ScreenSc / 2, - }), - platform: false, - graphic_name: String::from("tiles/unknown"), - tex_rect: IntRect::default(), - }; Self { - db: vec![EMPTY, unknown], + unknown_bg: Bg::unknown_def(), + unknown_mid: Mid::unknown_def(), + unknown_fg: Fg::unknown_def(), + bg: vec![], + mid: vec![], + fg: vec![], } } } -const EMPTY: TileDef = TileDef { - bb: None, - light: None, - // Rendering empty tile is actually special cased, and no rendering is done. - // But just in case, put the offset to UNKNOWN - tex_rect: IntRect { - x: 0, - y: 0, - w: 0, - h: 0, - }, - platform: false, - graphic_name: String::new(), -}; +impl Index for TileDb { + type Output = TileDef; -impl Index for TileDb { - type Output = TileDef; + fn index(&self, index: BgTileId) -> &Self::Output { + self.bg + .get(index.0 as usize - 1) + .unwrap_or(&self.unknown_bg) + } +} - fn index(&self, index: TileId) -> &Self::Output { - self.db.get(index as usize).unwrap_or_else(|| { - &self.db[1] // Unknown tile def is stored at index 1 - }) +impl Index for TileDb { + type Output = TileDef; + + fn index(&self, index: MidTileId) -> &Self::Output { + self.mid + .get(index.0 as usize - 1) + .unwrap_or(&self.unknown_mid) + } +} + +impl Index for TileDb { + type Output = TileDef; + + fn index(&self, index: FgTileId) -> &Self::Output { + self.fg + .get(index.0 as usize - 1) + .unwrap_or(&self.unknown_fg) } } @@ -115,14 +280,38 @@ impl TileDb { } pub(crate) fn update_rects(&mut self, rects: &RectMap) { - for def in &mut self.db { - if !def.graphic_name.is_empty() { - if let Some(rect) = rects.get(&def.graphic_name) { - def.tex_rect = *rect; - } else { - log::error!("Missing texture for {}", def.graphic_name); - } - } - } + update_rect_def(&mut self.unknown_bg, rects); + update_rect_def(&mut self.unknown_mid, rects); + update_rect_def(&mut self.unknown_fg, rects); + update_rect_db(&mut self.bg, rects); + update_rect_db(&mut self.mid, rects); + update_rect_db(&mut self.fg, rects); + } +} + +fn update_rect_db(db: &mut Vec>, rects: &RectMap) +where + Layer::SpecificDef: Debug + Inspect, +{ + for def in db { + update_rect_def(def, rects); + } +} + +fn update_rect_def( + def: &mut TileDef, + rects: &std::collections::HashMap, +) where + Layer::SpecificDef: Debug + Inspect, +{ + if !def.graphic_name.is_empty() { + if let Some(rect) = rects.get(def.graphic_name.as_str()) { + def.tex_rect = *rect; + log::info!("Updated rect for {}: {:?}", def.graphic_name.as_str(), rect); + } else { + log::error!("Missing texture for {:?}", def.graphic_name.as_str()); + } + } else { + log::warn!("Empty graphic name!"); } } diff --git a/src/tiles/tiledb_edit_ui.rs b/src/tiles/tiledb_edit_ui.rs index 634eded..6986541 100644 --- a/src/tiles/tiledb_edit_ui.rs +++ b/src/tiles/tiledb_edit_ui.rs @@ -1,57 +1,91 @@ +use std::fmt::Debug; + +use egui_inspect::Inspect; + use crate::{ graphics::{ScreenSc, ScreenVec}, math::TILE_SIZE, }; -use super::{TileDb, DEFAULT_TILE_BB}; +use super::{Bg, Fg, Mid, TileDb, TileDef, TileLayer, DEFAULT_TILE_BB}; pub fn tiledb_edit_ui(ctx: &egui::Context, tile_db: &mut TileDb) { egui::Window::new("Tiledb editor").show(ctx, |ui| { - ui.label(format!("Number of tile defs: {}", tile_db.db.len())); ui.separator(); egui::ScrollArea::vertical() .max_height(400.0) .show(ui, |ui| { - for (i, def) in tile_db.db.iter_mut().enumerate() { - ui.label(i.to_string()); - match &mut def.light { - Some(light) => { - ui.label("x"); - ui.add(egui::DragValue::new(&mut light.x)); - ui.label("y"); - ui.add(egui::DragValue::new(&mut light.y)); - } - None => { - if ui.button("Insert light emit").clicked() { - def.light = Some(ScreenVec { - x: TILE_SIZE as ScreenSc / 2, - y: TILE_SIZE as ScreenSc / 2, - }); - } - } - } - match &mut def.bb { - Some(bb) => { - ui.label("x"); - ui.add(egui::DragValue::new(&mut bb.x)); - ui.label("y"); - ui.add(egui::DragValue::new(&mut bb.y)); - ui.label("w"); - ui.add(egui::DragValue::new(&mut bb.w)); - ui.label("h"); - ui.add(egui::DragValue::new(&mut bb.h)); - } - None => { - if ui.button("Insert bb").clicked() { - def.bb = Some(DEFAULT_TILE_BB); - } - } - } - } + ui.heading("Bg"); + db_ui(&mut tile_db.bg, ui); + ui.heading("Mid"); + db_ui(&mut tile_db.mid, ui); + ui.heading("Fg"); + db_ui(&mut tile_db.fg, ui); }); - ui.separator(); - if ui.button("Add new default").clicked() { - tile_db.db.push(super::TileDef::default()); - } }); } + +trait SpecialUi { + fn special_ui(&mut self, ui: &mut egui::Ui); +} + +impl SpecialUi for TileDef { + fn special_ui(&mut self, ui: &mut egui::Ui) { + match &mut self.layer.bb { + Some(bb) => { + ui.label("x"); + ui.add(egui::DragValue::new(&mut bb.x)); + ui.label("y"); + ui.add(egui::DragValue::new(&mut bb.y)); + ui.label("w"); + ui.add(egui::DragValue::new(&mut bb.w)); + ui.label("h"); + ui.add(egui::DragValue::new(&mut bb.h)); + } + None => { + if ui.button("Insert bb").clicked() { + self.layer.bb = Some(DEFAULT_TILE_BB); + } + } + } + } +} + +impl SpecialUi for TileDef { + fn special_ui(&mut self, _ui: &mut egui::Ui) {} +} + +impl SpecialUi for TileDef { + fn special_ui(&mut self, _ui: &mut egui::Ui) {} +} + +fn db_ui(db: &mut Vec>, ui: &mut egui::Ui) +where + ::SpecificDef: Debug + Default + Inspect, + TileDef: SpecialUi, +{ + for (i, def) in db.iter_mut().enumerate() { + ui.label(i.to_string()); + match &mut def.light { + Some(light) => { + ui.label("x"); + ui.add(egui::DragValue::new(&mut light.x)); + ui.label("y"); + ui.add(egui::DragValue::new(&mut light.y)); + } + None => { + if ui.button("Insert light emit").clicked() { + def.light = Some(ScreenVec { + x: TILE_SIZE as ScreenSc / 2, + y: TILE_SIZE as ScreenSc / 2, + }); + } + } + } + def.special_ui(ui); + } + ui.separator(); + if ui.button("Add new default").clicked() { + db.push(Default::default()); + } +} diff --git a/src/world.rs b/src/world.rs index 8f4477b..9077106 100644 --- a/src/world.rs +++ b/src/world.rs @@ -13,7 +13,11 @@ use fnv::FnvHashMap; use serde::{Deserialize, Serialize}; use crate::{ - math::WorldPos, player::Player, world::reg_chunk_existence::ExistenceBitset, worldgen::Worldgen, + math::WorldPos, + player::Player, + tiles::{BgTileId, FgTileId, MidTileId, TileId}, + world::reg_chunk_existence::ExistenceBitset, + worldgen::Worldgen, }; use self::serialization::save_chunk; @@ -203,9 +207,9 @@ type ChunkTiles = [Tile; CHUNK_N_TILES]; fn default_chunk_tiles() -> ChunkTiles { [Tile { - bg: 0, - mid: 0, - fg: 0, + bg: TileId::EMPTY, + mid: TileId::EMPTY, + fg: TileId::EMPTY, }; CHUNK_N_TILES] } @@ -229,7 +233,7 @@ impl Chunk { // Unbreakable layer at bottom if pos.y > 798 { for b in &mut tiles { - b.mid = Tile::UNBREAKANIUM; + b.mid = MidTileId::UNBREAKANIUM; } } Self { tiles } @@ -269,21 +273,14 @@ fn chunk_exists(reg_path: &Path, pos: ChunkPos) -> bool { crate::bitmanip::nth_bit_set(bitset.0, idx as usize) } -pub type TileId = u16; - #[derive(Clone, Copy, Debug, Inspect)] pub struct Tile { /// Background wall behind entities - pub bg: TileId, + pub bg: BgTileId, /// The solid wall on the same level as entities - pub mid: TileId, + pub mid: MidTileId, /// A layer on top of the mid wall. Usually ores or decorative pieces. - pub fg: TileId, -} - -impl Tile { - pub const EMPTY: TileId = 0; - pub const UNBREAKANIUM: TileId = 5; + pub fg: FgTileId, } pub const REGION_CHUNK_EXTENT: u8 = 8; diff --git a/src/world/serialization.rs b/src/world/serialization.rs index 93c149b..065e2ed 100644 --- a/src/world/serialization.rs +++ b/src/world/serialization.rs @@ -42,9 +42,9 @@ pub(super) fn save_chunk(pos: &ChunkPos, chk: &Chunk, world_dir: &Path) { let byte_idx = loc_byte_idx(loc_idx); for (i, tile) in chk.tiles.iter().enumerate() { let off = byte_idx + (i * TILE_BYTES); - region_tile_data[off..off + 2].copy_from_slice(&tile.bg.to_le_bytes()); - region_tile_data[off + 2..off + 4].copy_from_slice(&tile.mid.to_le_bytes()); - region_tile_data[off + 4..off + 6].copy_from_slice(&tile.fg.to_le_bytes()); + region_tile_data[off..off + 2].copy_from_slice(&tile.bg.0.to_le_bytes()); + region_tile_data[off + 2..off + 4].copy_from_slice(&tile.mid.0.to_le_bytes()); + region_tile_data[off + 4..off + 6].copy_from_slice(&tile.fg.0.to_le_bytes()); } f.rewind().unwrap(); f.write_all(&u64::to_le_bytes(existence_bitset.0)[..]) @@ -65,9 +65,9 @@ impl Chunk { let mut tiles = default_chunk_tiles(); for (i, t) in tiles.iter_mut().enumerate() { let off = byte_idx + (i * TILE_BYTES); - t.bg = u16::from_le_bytes(data[off..off + 2].try_into().unwrap()); - t.mid = u16::from_le_bytes(data[off + 2..off + 4].try_into().unwrap()); - t.fg = u16::from_le_bytes(data[off + 4..off + 6].try_into().unwrap()); + t.bg.0 = u16::from_le_bytes(data[off..off + 2].try_into().unwrap()); + t.mid.0 = u16::from_le_bytes(data[off + 2..off + 4].try_into().unwrap()); + t.fg.0 = u16::from_le_bytes(data[off + 4..off + 6].try_into().unwrap()); } Self { tiles } } @@ -83,7 +83,7 @@ fn test_chunk_seri() { tiles: super::default_chunk_tiles(), }; for t in &mut chk.tiles { - t.bg = 1; + t.bg = crate::tiles::BgTileId::DIRT; } save_chunk(&ChunkPos { x: 2, y: 0 }, &chk, "testworld".as_ref()); save_chunk(&ChunkPos { x: 3, y: 0 }, &chk, "testworld".as_ref()); diff --git a/src/worldgen.rs b/src/worldgen.rs index 97ad339..9ac53b3 100644 --- a/src/worldgen.rs +++ b/src/worldgen.rs @@ -8,7 +8,10 @@ use worldgen::{ }, }; -use crate::world::{ChunkPos, Tile as Tl, CHUNK_EXTENT}; +use crate::{ + tiles::{BgTileId, FgTileId, MidTileId, TileId}, + world::{ChunkPos, Tile as Tl, CHUNK_EXTENT}, +}; pub struct Worldgen { world: World, @@ -33,35 +36,35 @@ impl Worldgen { // Dirt coal .add( Tile::new(Tl { - bg: 9, - mid: 3, - fg: 6, + bg: BgTileId::DIRT, + mid: MidTileId::DIRT, + fg: FgTileId::COAL, }) .when(constraint!(nm.clone(), < -0.8)), ) // Dirt .add( Tile::new(Tl { - bg: 9, - mid: 3, - fg: 0, + bg: BgTileId::DIRT, + mid: MidTileId::DIRT, + fg: TileId::EMPTY, }) .when(constraint!(nm.clone(), < -0.1)), ) // Stone .add( Tile::new(Tl { - bg: 7, - mid: 2, - fg: 0, + bg: BgTileId::STONE, + mid: MidTileId::STONE, + fg: TileId::EMPTY, }) .when(constraint!(nm, < 0.45)), ) // Dirt wall .add(Tile::new(Tl { - bg: 9, - mid: 0, - fg: 0, + bg: BgTileId::DIRT, + mid: TileId::EMPTY, + fg: TileId::EMPTY, })); Self { world } } diff --git a/tiles.dat b/tiles.dat index 63551ed..6b55e19 100644 Binary files a/tiles.dat and b/tiles.dat differ