Refactor structure, implement layers, add Erode/Fill/layer panel
- Restructure folder hierarchy: max 4 .rs per dir using subfolders (ops/operations -> brush/ + shaping/, model/ -> world/, io/* -> subtypes, etc.) - Fix golden_test.rs comment, extract BrushApply helper, add World::with_heightmap - Implement 6 layer data generators (Caves, River, Frost, Trees, Biome, Resources) with noise-based (OpenSimplex) and terrain-derived algorithms - Fix clippy warnings, dead code cleanup, import path fixes - GUI: add Erode&Fill tool modes with radio buttons/sliders/apply_tool - GUI: add Layers panel with 6 checkboxes + CPU viewport overlay rendering
This commit is contained in:
parent
3d3798136d
commit
bdd4564240
104 changed files with 5184 additions and 3912 deletions
4
crates/palette-compress/src/palette/mod.rs
Normal file
4
crates/palette-compress/src/palette/mod.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
mod palette;
|
||||
mod palette_io;
|
||||
|
||||
pub use palette::*;
|
||||
82
crates/palette-compress/src/palette/palette.rs
Executable file
82
crates/palette-compress/src/palette/palette.rs
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BlockState {
|
||||
pub name: String,
|
||||
pub properties: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Hash for BlockState {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.name.hash(state);
|
||||
let mut keys: Vec<&String> = self.properties.keys().collect();
|
||||
keys.sort();
|
||||
for k in keys {
|
||||
k.hash(state);
|
||||
self.properties[k].hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockState {
|
||||
pub fn new(name: &str) -> Self {
|
||||
BlockState {
|
||||
name: name.to_string(),
|
||||
properties: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_property(mut self, key: &str, val: &str) -> Self {
|
||||
self.properties.insert(key.to_string(), val.to_string());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A palette mapping unique `BlockState`s to compact indices.
|
||||
pub struct BlockPalette {
|
||||
pub entries: Vec<BlockState>,
|
||||
index_map: HashMap<BlockState, u32>,
|
||||
}
|
||||
|
||||
impl Default for BlockPalette {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockPalette {
|
||||
pub fn new() -> Self {
|
||||
BlockPalette {
|
||||
entries: Vec::new(),
|
||||
index_map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a block state, or return its existing index.
|
||||
pub fn add_or_get(&mut self, state: BlockState) -> u32 {
|
||||
if let Some(&idx) = self.index_map.get(&state) {
|
||||
return idx;
|
||||
}
|
||||
let idx = self.entries.len() as u32;
|
||||
self.index_map.insert(state.clone(), idx);
|
||||
self.entries.push(state);
|
||||
idx
|
||||
}
|
||||
|
||||
pub fn get(&self, index: u32) -> Option<&BlockState> {
|
||||
self.entries.get(index as usize)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.entries.len()
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
/// Minimum bits per entry needed for this palette.
|
||||
pub fn bits_per_entry(&self) -> u8 {
|
||||
crate::bits::BitArray::bits_needed(self.entries.len())
|
||||
}
|
||||
}
|
||||
81
crates/palette-compress/src/palette.rs → crates/palette-compress/src/palette/palette_io.rs
Executable file → Normal file
81
crates/palette-compress/src/palette.rs → crates/palette-compress/src/palette/palette_io.rs
Executable file → Normal file
|
|
@ -1,39 +1,9 @@
|
|||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use terrafier_nbt::Tag;
|
||||
|
||||
/// A Minecraft block state — name plus key-value properties.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BlockState {
|
||||
pub name: String,
|
||||
pub properties: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Hash for BlockState {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.name.hash(state);
|
||||
let mut keys: Vec<&String> = self.properties.keys().collect();
|
||||
keys.sort();
|
||||
for k in keys {
|
||||
k.hash(state);
|
||||
self.properties[k].hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
use super::palette::{BlockPalette, BlockState};
|
||||
|
||||
impl BlockState {
|
||||
pub fn new(name: &str) -> Self {
|
||||
BlockState {
|
||||
name: name.to_string(),
|
||||
properties: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_property(mut self, key: &str, val: &str) -> Self {
|
||||
self.properties.insert(key.to_string(), val.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Parse from `TAG_Compound` with `"Name"` and optional `"Properties"`.
|
||||
pub fn from_nbt(tag: &Tag) -> Option<Self> {
|
||||
let map = match tag {
|
||||
|
|
@ -78,53 +48,7 @@ impl BlockState {
|
|||
}
|
||||
}
|
||||
|
||||
/// A palette mapping unique `BlockState`s to compact indices.
|
||||
pub struct BlockPalette {
|
||||
pub entries: Vec<BlockState>,
|
||||
index_map: HashMap<BlockState, u32>,
|
||||
}
|
||||
|
||||
impl Default for BlockPalette {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockPalette {
|
||||
pub fn new() -> Self {
|
||||
BlockPalette {
|
||||
entries: Vec::new(),
|
||||
index_map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a block state, or return its existing index.
|
||||
pub fn add_or_get(&mut self, state: BlockState) -> u32 {
|
||||
if let Some(&idx) = self.index_map.get(&state) {
|
||||
return idx;
|
||||
}
|
||||
let idx = self.entries.len() as u32;
|
||||
self.index_map.insert(state.clone(), idx);
|
||||
self.entries.push(state);
|
||||
idx
|
||||
}
|
||||
|
||||
pub fn get(&self, index: u32) -> Option<&BlockState> {
|
||||
self.entries.get(index as usize)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.entries.len()
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.entries.is_empty()
|
||||
}
|
||||
|
||||
/// Minimum bits per entry needed for this palette.
|
||||
pub fn bits_per_entry(&self) -> u8 {
|
||||
crate::bits::BitArray::bits_needed(self.entries.len())
|
||||
}
|
||||
|
||||
/// Import from NBT palette list + block data `LongArray`.
|
||||
pub fn from_nbt(palette_list: &[Tag], data: &[i64]) -> (Self, crate::bits::BitArray) {
|
||||
let mut palette = BlockPalette::new();
|
||||
|
|
@ -149,7 +73,8 @@ impl BlockPalette {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::super::palette::{BlockPalette, BlockState};
|
||||
use terrafier_nbt::Tag;
|
||||
|
||||
#[test]
|
||||
fn test_add_get() {
|
||||
Loading…
Add table
Add a link
Reference in a new issue