aboutsummaryrefslogtreecommitdiff
path: root/src/dimension.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dimension.rs')
-rw-r--r--src/dimension.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/dimension.rs b/src/dimension.rs
new file mode 100644
index 0000000..39a7fff
--- /dev/null
+++ b/src/dimension.rs
@@ -0,0 +1,64 @@
+use chashmap::{CHashMap, ReadGuard, WriteGuard};
+use fastanvil::{Block, Chunk, CurrentJavaChunk, Region, RegionFileLoader, RegionLoader};
+use log::{info, debug};
+use std::{fs::File, path::Path};
+
+pub struct Dimension {
+ loader: RegionFileLoader,
+ regions: CHashMap<(isize, isize), Option<Region<File>>>,
+ chunks: CHashMap<(isize, isize), Option<CurrentJavaChunk>>,
+}
+impl Dimension {
+ pub fn new(path: &str) -> Self {
+ let loader = fastanvil::RegionFileLoader::new(Path::new(path).to_path_buf());
+ Self {
+ loader,
+ regions: Default::default(),
+ chunks: Default::default(),
+ }
+ }
+ pub fn region(
+ &self,
+ rx: isize,
+ rz: isize,
+ ) -> WriteGuard<'_, (isize, isize), Option<Region<File>>> {
+ if self.regions.contains_key(&(rx, rz)) {
+ self.regions.get_mut(&(rx, rz)).unwrap()
+ } else {
+ info!("loading region {:?}", (rx, rz));
+ self.regions.insert(
+ (rx, rz),
+ self.loader
+ .region(fastanvil::RCoord(rx), fastanvil::RCoord(rz)),
+ );
+ self.region(rx, rz)
+ }
+ }
+ pub fn chunk(
+ &self,
+ cx: isize,
+ cz: isize,
+ ) -> ReadGuard<'_, (isize, isize), Option<CurrentJavaChunk>> {
+ if self.chunks.contains_key(&(cx, cz)) {
+ self.chunks.get(&(cx, cz)).unwrap()
+ } else {
+ let mut guard = self.region(cx / 32, cz / 32);
+ let reg = guard.as_mut().unwrap();
+ debug!("loading chunk {:?}", (cx, cz));
+ let chunk: Option<CurrentJavaChunk> = reg
+ .read_chunk(cx.rem_euclid(32) as usize, cz.rem_euclid(32) as usize)
+ .ok()
+ .flatten()
+ .map(|chunk| fastnbt::from_bytes(&chunk).ok())
+ .flatten();
+ self.chunks.insert((cx, cz), chunk);
+ self.chunk(cx, cz)
+ }
+ }
+ pub fn block(&self, x: isize, y: isize, z: isize) -> Option<Block> {
+ self.chunk(x / 16, z / 16)
+ .as_ref()?
+ .block(x.rem_euclid(16) as usize, y, z.rem_euclid(16) as usize)
+ .map(|e| e.to_owned())
+ }
+}