mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
Introduce ChunkArray type
A generic array for per-chunk data, indexed by ChunkCoords.
This commit is contained in:
parent
48e03aa266
commit
28b22ce423
4 changed files with 71 additions and 26 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -90,6 +90,12 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -170,6 +176,15 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.139"
|
||||||
|
@ -190,6 +205,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"fastnbt",
|
"fastnbt",
|
||||||
"flate2",
|
"flate2",
|
||||||
|
"itertools",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,5 @@ anyhow = "1.0.68"
|
||||||
clap = { version = "4.1.4", features = ["derive"] }
|
clap = { version = "4.1.4", features = ["derive"] }
|
||||||
fastnbt = "2.3.2"
|
fastnbt = "2.3.2"
|
||||||
flate2 = "1.0.25"
|
flate2 = "1.0.25"
|
||||||
|
itertools = "0.10.5"
|
||||||
serde = "1.0.152"
|
serde = "1.0.152"
|
||||||
|
|
|
@ -22,29 +22,19 @@ struct ChunkDesc {
|
||||||
fn parse_header(header: &[u8; BLOCKSIZE]) -> HashMap<u32, ChunkDesc> {
|
fn parse_header(header: &[u8; BLOCKSIZE]) -> HashMap<u32, ChunkDesc> {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
for z in 0..CHUNKS_PER_REGION {
|
for coords in ChunkArray::<()>::keys() {
|
||||||
for x in 0..CHUNKS_PER_REGION {
|
let chunk = &header[(4
|
||||||
let chunk =
|
* (usize::from(CHUNKS_PER_REGION) * usize::from(coords.z.0)
|
||||||
&header[(4 * (usize::from(CHUNKS_PER_REGION) * usize::from(z) + usize::from(x)))..];
|
+ usize::from(coords.x.0)))..];
|
||||||
|
|
||||||
let offset = u32::from(chunk[0]) << 16 | u32::from(chunk[1]) << 8 | u32::from(chunk[2]);
|
let offset = u32::from(chunk[0]) << 16 | u32::from(chunk[1]) << 8 | u32::from(chunk[2]);
|
||||||
if offset == 0 {
|
if offset == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
let len = chunk[3];
|
|
||||||
|
|
||||||
map.insert(
|
|
||||||
offset,
|
|
||||||
ChunkDesc {
|
|
||||||
coords: ChunkCoords {
|
|
||||||
x: ChunkX(x),
|
|
||||||
z: ChunkZ(z),
|
|
||||||
},
|
|
||||||
len,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let len = chunk[3];
|
||||||
|
|
||||||
|
map.insert(offset, ChunkDesc { coords, len });
|
||||||
}
|
}
|
||||||
|
|
||||||
map
|
map
|
||||||
|
@ -100,7 +90,7 @@ impl<R: Read + Seek> Region<R> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut index = 1;
|
let mut index = 1;
|
||||||
let mut seen = [[false; CHUNKS_PER_REGION as usize]; CHUNKS_PER_REGION as usize];
|
let mut seen = ChunkArray::<bool>::default();
|
||||||
|
|
||||||
while !chunk_map.is_empty() {
|
while !chunk_map.is_empty() {
|
||||||
let Some(ChunkDesc { coords, len }) = chunk_map.remove(&index) else {
|
let Some(ChunkDesc { coords, len }) = chunk_map.remove(&index) else {
|
||||||
|
@ -109,11 +99,10 @@ impl<R: Read + Seek> Region<R> {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let chunk_seen = &mut seen[coords.x.0 as usize][coords.z.0 as usize];
|
if seen[coords] {
|
||||||
if *chunk_seen {
|
|
||||||
bail!("Duplicate chunk");
|
bail!("Duplicate chunk");
|
||||||
}
|
}
|
||||||
*chunk_seen = true;
|
seen[coords] = true;
|
||||||
|
|
||||||
let mut buffer = vec![0; (len as usize) * BLOCKSIZE];
|
let mut buffer = vec![0; (len as usize) * BLOCKSIZE];
|
||||||
reader
|
reader
|
||||||
|
|
41
src/types.rs
41
src/types.rs
|
@ -1,4 +1,9 @@
|
||||||
use std::fmt::Debug;
|
use std::{
|
||||||
|
fmt::Debug,
|
||||||
|
ops::{Index, IndexMut},
|
||||||
|
};
|
||||||
|
|
||||||
|
use itertools::iproduct;
|
||||||
|
|
||||||
pub const CHUNKS_PER_REGION: u8 = 32;
|
pub const CHUNKS_PER_REGION: u8 = 32;
|
||||||
|
|
||||||
|
@ -22,3 +27,37 @@ impl Debug for ChunkCoords {
|
||||||
write!(f, "({}, {})", self.x.0, self.z.0)
|
write!(f, "({}, {})", self.x.0, self.z.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct ChunkArray<T>(pub [[T; CHUNKS_PER_REGION as usize]; CHUNKS_PER_REGION as usize]);
|
||||||
|
|
||||||
|
impl<T> ChunkArray<T> {
|
||||||
|
pub fn keys() -> impl Iterator<Item = ChunkCoords> {
|
||||||
|
iproduct!(0..CHUNKS_PER_REGION, 0..CHUNKS_PER_REGION).map(|(z, x)| ChunkCoords {
|
||||||
|
x: ChunkX(x),
|
||||||
|
z: ChunkZ(z),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn values(&self) -> impl Iterator<Item = &T> {
|
||||||
|
Self::keys().map(|k| &self[k])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = (ChunkCoords, &T)> {
|
||||||
|
Self::keys().map(|k| (k, &self[k]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Index<ChunkCoords> for ChunkArray<T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, index: ChunkCoords) -> &Self::Output {
|
||||||
|
&self.0[index.z.0 as usize][index.x.0 as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IndexMut<ChunkCoords> for ChunkArray<T> {
|
||||||
|
fn index_mut(&mut self, index: ChunkCoords) -> &mut Self::Output {
|
||||||
|
&mut self.0[index.z.0 as usize][index.x.0 as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue