Skip to content

Commit

Permalink
Merge pull request #118 from akashic-records-of-the-abyss/proto_rework
Browse files Browse the repository at this point in the history
[Fix]: Fixed lots of bugs in the Level implementation
  • Loading branch information
theaddonn authored Jan 4, 2025
2 parents 2fa8ce6 + 401be96 commit 6e3c9e9
Show file tree
Hide file tree
Showing 20 changed files with 350 additions and 88 deletions.
13 changes: 9 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ bedrockrs_proto_core = { path = "crates/proto_core", optional = true }

bedrockrs_server = { path = "crates/server", optional = true }

bedrockrs_level = {path = "crates/level", optional = true}
bedrockrs_level = { path = "crates/level", optional = true }

[dev-dependencies]
tokio = { version = "1.40", features = ["full"] }
Expand All @@ -35,14 +35,18 @@ log = "0.4"
chrono = "0.4"

[features]
default = ["full"]

addon = ["dep:bedrockrs_addon"]
proto = ["dep:bedrockrs_proto","dep:bedrockrs_proto_core","dep:bedrockrs_macros",]
level = ["dep:bedrockrs_level"]
full = ["addon", "level", "proto", "server"]
form = ["dep:bedrockrs_form"]
proto = ["dep:bedrockrs_proto", "dep:bedrockrs_proto_core", "dep:bedrockrs_macros", ]
level = ["dep:bedrockrs_level", "level-default"]
server = ["dep:bedrockrs_server", "proto", "level", "form"]

level-default = ["bedrockrs_level/default-impl"]

full = ["addon", "form", "proto", "level", "server", "level-default"]

[[example]]
name = "proto_server"
path = "examples/proto/server.rs"
Expand All @@ -52,3 +56,4 @@ required-features = ["proto"]
name = "proto_parsing"
path = "examples/proto_parsing.rs"
required-features = ["proto"]

21 changes: 11 additions & 10 deletions crates/level/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,29 @@ version = "0.1.0"
edition = "2021"

[dependencies]
bedrockrs_core = { path = "../core" }
bedrockrs_shared = { path = "../shared" }

nbtx = { git = "https://github.com/bedrock-crustaceans/nbtx" }


thiserror = "2.0"
byteorder = "1.x"
uuid = { version = "1.x", features = ["v4"] }
byteorder = "1.5"
uuid = { version = "1.11", features = ["v4"] }
bytemuck = { version = "1.19", features = ["must_cast"] }
len-trait = "0.6"
concat-idents = "1.x"
serde = "1.x.x"
rusty-leveldb = "3.x"
serde = "1.0"
rusty-leveldb = "3.0"
miniz_oxide = "0.8"
vek = "0.17"

[dev-dependencies]
rand = "0.8"

[features]
default-impl = []

[[test]]
name = "api_test"
required-features = ["default-impl"]


[features]
default-impl = []
default = ["default-impl"]

23 changes: 13 additions & 10 deletions crates/level/src/level/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub enum FillFilter<UserBlockType: WorldBlockTrait> {
/// # Parameters
/// - A boxed function with the following parameters:
/// - `&UserBlockType`: The current block being evaluated.
/// - `Vec3<u8>`: The local coordinates of the block within the chunk.
/// - `Vec3<u8>`: The local coordinates of the block within the current subchunk.
/// - `Vec2<i32>`: The world-space XZ coordinates of the chunk.
/// - `i8`: The subchunk y.
///
Expand All @@ -40,6 +40,17 @@ pub enum FillFilter<UserBlockType: WorldBlockTrait> {
Precedence(Box<dyn Fn(&UserBlockType, Vec3<u8>, Vec2<i32>, i8) -> bool>),

Check warning on line 40 in crates/level/src/level/chunk.rs

View workflow job for this annotation

GitHub Actions / Clippy

very complex type used. Consider factoring parts into `type` definitions
}

impl<T: WorldBlockTrait> FillFilter<T> {
pub fn may_place(&self, target: &T, position: Vec3<u8>, xz: Vec2<i32>, y: i8) -> bool {
match self {
FillFilter::Blanket => true,
FillFilter::Replace(v) => v == target,
FillFilter::Avoid(v) => v != target,
FillFilter::Precedence(f) => f(target, position, xz, y),
}
}
}

#[derive(Error, Debug)]
pub enum FillError {
#[error("Attempted to fill Subchunk {0} and got none back")]
Expand Down Expand Up @@ -382,15 +393,7 @@ pub mod default_impl {
let blk = subchunk
.get_block((x, y, z).into())
.ok_or(FillError::BlockIndexDidntReturn(x, y, z))?;
if match &filter {
FillFilter::Blanket => true,
FillFilter::Replace(mask) =>
mask == blk,
FillFilter::Avoid(mask) => mask != blk,
FillFilter::Precedence(func) => {
func(blk, (x, y, z).into(), pos, subchunk.get_y())
}
} {
if filter.may_place(blk, (x, y, z).into(), pos, y_level) {
subchunk.set_block((x, y, z).into(), block.clone()).unwrap()
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/level/src/level/db_interface/bedrock_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl LevelDBKey for ChunkKey {
size += std::mem::size_of::<i32>();
}
size += 1; // For the key_type
if let Some(_) = self.y_index {
if self.y_index.is_some() {
size += 1;
}
size
Expand Down
29 changes: 16 additions & 13 deletions crates/level/src/level/db_interface/rusty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,17 @@ impl<UserState> RustyDBInterface<UserState> {
}
}

impl<T> Drop for RustyDBInterface<T> {
fn drop(&mut self) {
self.db.close().unwrap();
}
}

impl<UserState> RawWorldTrait for RustyDBInterface<UserState> {
type Err = DBError;
type UserState = UserState;

fn set_subchunk_raw(
fn write_bytes_to_key(
&mut self,
chunk_info: ChunkKey,
chunk_bytes: &[u8],
Expand All @@ -128,20 +134,20 @@ impl<UserState> RawWorldTrait for RustyDBInterface<UserState> {
Ok(self.db.write(batch, false)?)
}

fn get_subchunk_raw(
fn get_bytes_from_key(
&mut self,
chunk_info: ChunkKey,
_: &mut Self::UserState,
) -> Result<Option<Vec<u8>>, Self::Err> {
Ok(self.db.get(&Self::build_key(&chunk_info)))
}

fn chunk_exists(
fn delete_bytes_at_key(
&mut self,
chunk_info: ChunkKey,
_: &mut Self::UserState,
) -> Result<bool, Self::Err> {
Ok(self.db.get(&Self::build_key(&chunk_info)).is_some())
) -> Result<(), Self::Err> {
Ok(self.db.delete(&Self::build_key(&chunk_info))?)
}

fn write_subchunk_batch(
Expand Down Expand Up @@ -182,14 +188,6 @@ impl<UserState> RawWorldTrait for RustyDBInterface<UserState> {
Ok(self.db.write(batch, false)?)
}

fn exist_chunk(
&mut self,
chunk_info: ChunkKey,
state: &mut Self::UserState,
) -> Result<(), Self::Err> {
Ok(self.set_subchunk_raw(chunk_info, &[], state)?)
}

fn build_key(key: &ChunkKey) -> Vec<u8> {
let mut key_bytes: Vec<u8> = vec![0; key.estimate_size()];
let mut buff: Cursor<&mut [u8]> = Cursor::new(&mut key_bytes);
Expand All @@ -211,6 +209,11 @@ impl<UserState> RawWorldTrait for RustyDBInterface<UserState> {
})
}

fn close(&mut self) -> Result<(), Self::Err> {
self.db.close()?;
Ok(())
}

fn generated_chunks(
&mut self,
_: &mut Self::UserState,
Expand Down
65 changes: 60 additions & 5 deletions crates/level/src/level/file_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,49 @@ pub trait RawWorldTrait: Sized {

type UserState;

fn set_subchunk_raw(
fn write_bytes_to_key(
&mut self,
chunk_info: ChunkKey,
chunk_bytes: &[u8],
state: &mut Self::UserState,
) -> Result<(), Self::Err>;

fn get_subchunk_raw(
fn get_bytes_from_key(
&mut self,
chunk_info: ChunkKey,
state: &mut Self::UserState,
) -> Result<Option<Vec<u8>>, Self::Err>;

fn delete_bytes_at_key(
&mut self,
chunk_info: ChunkKey,
state: &mut Self::UserState,
) -> Result<(), Self::Err>;

fn set_subchunk_raw(
&mut self,
chunk_info: ChunkKey,
chunk_bytes: &[u8],
state: &mut Self::UserState,
) -> Result<(), Self::Err> {
self.write_bytes_to_key(chunk_info, chunk_bytes, state)
}

fn get_subchunk_raw(
&mut self,
chunk_info: ChunkKey,
state: &mut Self::UserState,
) -> Result<Option<Vec<u8>>, Self::Err> {
self.get_bytes_from_key(chunk_info, state)
}

fn chunk_exists(
&mut self,
chunk_info: ChunkKey,
state: &mut Self::UserState,
) -> Result<bool, Self::Err>;
) -> Result<bool, Self::Err> {
Ok(self.get_bytes_from_key(chunk_info, state)?.is_some())
}

fn write_subchunk_batch(
&mut self,
Expand All @@ -65,11 +90,13 @@ pub trait RawWorldTrait: Sized {
state: &mut Self::UserState,
) -> Result<(), Self::Err>;

fn exist_chunk(
fn mark_exist_chunk(
&mut self,
chunk_info: ChunkKey,
state: &mut Self::UserState,
) -> Result<(), Self::Err>;
) -> Result<(), Self::Err> {
self.write_bytes_to_key(chunk_info, &[], state)
}

fn build_key(key: &ChunkKey) -> Vec<u8>;

Expand All @@ -79,8 +106,36 @@ pub trait RawWorldTrait: Sized {
state: &mut Self::UserState,
) -> Result<Self, Self::Err>;

fn close(&mut self) -> Result<(), Self::Err>;

fn generated_chunks(
&mut self,
state: &mut Self::UserState,
) -> Result<HashSet<(Dimension, Vec2<i32>)>, Self::Err>;

fn delete_chunk(
&mut self,
xz: Vec2<i32>,
dimension: Dimension,
subchunk_range: Vec2<i8>,
state: &mut Self::UserState,
) -> Result<(), Self::Err> {
for y in subchunk_range.x..=subchunk_range.y {
self.delete_subchunk(xz, dimension, y, state)?
}

self.delete_bytes_at_key(ChunkKey::chunk_marker(xz, dimension), state)?;

Ok(())
}

fn delete_subchunk(
&mut self,
xz: Vec2<i32>,
dimension: Dimension,
y: i8,
state: &mut Self::UserState,
) -> Result<(), Self::Err> {
self.delete_bytes_at_key(ChunkKey::new_subchunk(xz, dimension, y), state)
}
}
Loading

0 comments on commit 6e3c9e9

Please sign in to comment.