Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
296fc5d
remove `vek` from bedrockrs_level
RadiatedMonkey Apr 20, 2026
ee311f1
also add types from shared crate
RadiatedMonkey Apr 20, 2026
bc60901
add (incomplete) definitions for many block entities
RadiatedMonkey Apr 23, 2026
855d1aa
Merge branch 'main' into block-entities
RadiatedMonkey Apr 23, 2026
13ef9d2
add block entity data to struct and use debug test level
RadiatedMonkey Apr 29, 2026
79ce908
add chest block entity
RadiatedMonkey Apr 29, 2026
1d80da2
add shulker box and shelf
RadiatedMonkey Apr 29, 2026
03069a1
add copper golem statue
RadiatedMonkey Apr 29, 2026
c7f68f0
add sign, hanging sign, flower pot and nether reactor
RadiatedMonkey Apr 29, 2026
2483805
add end portal, comparator and command block
RadiatedMonkey Apr 30, 2026
662dfb8
add chiseled bookshelf, mob spawner, noteblock
RadiatedMonkey Apr 30, 2026
5e16efc
add beehives, calibrated sculk sensors, lecterns, bells, banners
RadiatedMonkey Apr 30, 2026
9304fb8
parse full list of block entities per chunk
RadiatedMonkey Apr 30, 2026
9cd63f3
add item frame block entities
RadiatedMonkey Apr 30, 2026
da8018d
add effect IDs
RadiatedMonkey Apr 30, 2026
edc0bdf
add end gateway, hopper and jukebox
RadiatedMonkey Apr 30, 2026
ee3b17b
add book support to lecterns
RadiatedMonkey Apr 30, 2026
e0e564e
add piston arms
RadiatedMonkey Apr 30, 2026
f18439a
add trial chamber vaults
RadiatedMonkey May 1, 2026
52c3896
add dispenser
RadiatedMonkey May 1, 2026
1d7d507
add trial spawner
RadiatedMonkey May 1, 2026
f8b52ba
add barrel
RadiatedMonkey May 1, 2026
532bc6c
add brushable block, decorated pot, barrel and jigsaw block
RadiatedMonkey May 1, 2026
f52d860
add structure block
RadiatedMonkey May 1, 2026
986d1b3
Merge branch 'main' into block-entities
RadiatedMonkey May 2, 2026
8ed6863
Make fields in `ShulkerBox` public
RadiatedMonkey May 3, 2026
ae7a259
Make `Noteblock::note` public
RadiatedMonkey May 3, 2026
032aab5
Merge branch 'main' into block-entities
RadiatedMonkey May 3, 2026
f3cd77f
Merge branch 'main' into block-entities
RadiatedMonkey May 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions crates/level/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ version = "0.1.0"
edition = "2024"

[features]
# default = ["rusty-leveldb"]
default = ["mojang-leveldb"]
deny-unknown-fields = []
default = ["mojang-leveldb", "deny-unknown-fields"]
mojang-leveldb = ["dep:leveldb-sys"]
# rusty-leveldb = ["dep:rusty-leveldb", "dep:miniz_oxide"]

Expand Down Expand Up @@ -33,6 +33,8 @@ bytemuck = { workspace = true }
smallvec = "1.15.1"
rustc-hash = "2.1.1"
nohash-hasher = "0.2.0"
paste.workspace = true
serde_repr.workspace = true

[dev-dependencies]
tar = { workspace = true }
Expand Down
1,447 changes: 1,447 additions & 0 deletions crates/level/output.txt

Large diffs are not rendered by default.

68 changes: 68 additions & 0 deletions crates/level/src/block_entities/banner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::color::Color;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum BannerPatternType {
Base,
BottomStripe,
TopStripe,
LeftStripe,
RightStripe,
CenterStripe,
MiddleStripe,
DownRightStripe,
DownLeftStripe,
SmallStripes,
DiagonalCross,
SquareCross,
LeftOfDiagonal,
RightOfUpsideDownDiagonal,
LeftOfUpsideDownDiagonal,
RightOfDiagonal,
VerticalHalf,
VerticalHalfRight,
HorizontalHalf,
HorizontalHalfBottom,
BottomLeftCorner,
TopLeftCorner,
TopRightCorner,
BottomTriangle,
TopTriangle,
BottomTriangleSawtooth,
TopTriangleSawtooth,
MiddleCircle,
MiddleRhombus,
Border,
CurlyBorder,
Brick,
Gradient,
GradientUpsideDown,
Creeper,
Skull,
Flower,
Mojang,
Globe,
Piglin,
Flow,
Guster,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct BannerPattern {
pub color: Color,
pub pattern: BannerPatternType,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Banner {
/// Base colour of the banner.
pub base: Color,
#[serde(rename = "Type")]
pub ty: i32,
/// The patterns displayed on this banner.
///
/// May not exist.
pub patterns: Option<Vec<BannerPattern>>,
}
8 changes: 8 additions & 0 deletions crates/level/src/block_entities/beacon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::types::Effect;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Beacon {
pub primary: Effect,
pub secondary: Effect,
}
8 changes: 8 additions & 0 deletions crates/level/src/block_entities/bed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::color::Color;

#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Bed {
/// Color of the bed.
pub color: Color,
}
10 changes: 10 additions & 0 deletions crates/level/src/block_entities/beehive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::deserialize_bool;

#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Beehive {
/// Whether the beehive should spawn bees.
#[serde(deserialize_with = "deserialize_bool")]
pub should_spawn_bees: bool,
}
14 changes: 14 additions & 0 deletions crates/level/src/block_entities/bell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::deserialize_bool;

#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Bell {
/// The direction the bell is facing.
pub direction: i32,
/// Whether the bell is currently ringing.
#[serde(deserialize_with = "deserialize_bool")]
pub ringing: bool,
/// Unknown.
pub ticks: i32,
}
12 changes: 12 additions & 0 deletions crates/level/src/block_entities/brewing_stand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::types::ItemStack;

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct BrewingStand {
pub cook_time: i16,
pub fuel_amount: i16,
pub fuel_total: i16,
/// The items currently contained in the brewing stand.
pub items: Vec<ItemStack>,
}
13 changes: 13 additions & 0 deletions crates/level/src/block_entities/brushable_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct BrushableBlock {
pub brush_count: i32,
pub brush_direction: i8,
#[serde(rename = "LootTableSeed")]
pub loot_table_seed: i32,
#[serde(rename = "LootTable")]
pub loot_table: String,
/// Types are (presumably) `minecraft:suspicious_gravel` and `minecraft:suspicious_sand`.
#[serde(rename = "type")]
pub ty: String,
}
24 changes: 24 additions & 0 deletions crates/level/src/block_entities/campfire.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::types::ItemStack;

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Campfire {
/// The item in position 1.
pub item1: Option<ItemStack>,
/// The item in position 2.
pub item2: Option<ItemStack>,
/// The item in position 3.
pub item3: Option<ItemStack>,
/// The item in position 4.
pub item4: Option<ItemStack>,

/// How long item 1 has been cooking.
pub item_time1: i32,
/// How long item 2 has been cooking.
pub item_time2: i32,
/// How long item 3 has been cooking.
pub item_time3: i32,
/// How long item 4 has been cooking.
pub item_time4: i32,
}
10 changes: 10 additions & 0 deletions crates/level/src/block_entities/cauldron.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::types::ItemStack;

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Cauldron {
pub potion_type: i16,
pub potion_id: i16,
pub items: Vec<ItemStack>,
}
20 changes: 20 additions & 0 deletions crates/level/src/block_entities/chest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
pub use crate::types::ItemStack;

// TODO: TEST ITEMS AND PAIRING
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Chest {
pub findable: i32,
#[serde(rename = "forceunpair")]
pub force_unpair: Option<bool>,
pub loot_table: Option<String>,
pub loot_table_seed: Option<i32>,
#[serde(rename = "pairlead")]
pub pair_lead: Option<i8>,
#[serde(rename = "pairx")]
pub pair_x: Option<i32>,
#[serde(rename = "pairz")]
pub pair_z: Option<i32>,
pub items: Vec<ItemStack>,
}
9 changes: 9 additions & 0 deletions crates/level/src/block_entities/chiseled_shelf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use crate::types::ItemStack;

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct ChiseledShelf {
pub items: Option<Vec<ItemStack>>,
pub last_interacted_slot: Option<i32>,
}
38 changes: 38 additions & 0 deletions crates/level/src/block_entities/command_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::deserialize_bool;

/// A command block tile entity.
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct CommandBlock {
#[serde(deserialize_with = "deserialize_bool")]
pub execute_on_first_tick: bool,
#[serde(deserialize_with = "deserialize_bool")]
#[serde(rename = "powered")]
pub powered: bool,
pub success_count: i32,
#[serde(deserialize_with = "deserialize_bool")]
// Yes this really is "Condional"
#[serde(rename = "LPCondionalMode")]
pub conditional_mode: bool,
pub last_execution: i64,
#[serde(rename = "LPCommandMode")]
pub command_mode: i32,
pub command: String,
pub last_output_params: Vec<String>,
#[serde(deserialize_with = "deserialize_bool")]
#[serde(rename = "conditionMet")]
pub condition_met: bool,
#[serde(deserialize_with = "deserialize_bool")]
pub track_output: bool,
#[serde(deserialize_with = "deserialize_bool")]
#[serde(rename = "auto")]
pub auto: bool,
pub last_output: String,
pub version: i32,
pub tick_delay: i32,
pub custom_name: String,
#[serde(deserialize_with = "deserialize_bool")]
#[serde(rename = "LPRedstoneMode")]
pub redstone_mode: bool,
}
8 changes: 8 additions & 0 deletions crates/level/src/block_entities/comparator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// A redstone comparator.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Comparator {
/// The strength of the signal output of this redstone comparator.
#[serde(rename = "OutputSignal")]
pub output_signal: i32,
}
11 changes: 11 additions & 0 deletions crates/level/src/block_entities/conduit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// A conduit tile entity.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Conduit {
/// Whether the conduit is active.
pub active: bool,
/// The unique ID of the hostile mob the conduit is currently attacking. If there is no target,
/// this is set to -1.
pub target: i64,
}
37 changes: 37 additions & 0 deletions crates/level/src/block_entities/copper_golem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct CopperGolemActor {
#[serde(rename = "ActorIdentifier")]
pub identifier: String,
#[serde(rename = "SaveData")]
pub save_data: nbtx::Value, // TODO: entity data
}

#[derive(
Debug,
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
serde_repr::Serialize_repr,
serde_repr::Deserialize_repr,
)]
#[repr(i32)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub enum CopperGolemPose {
Standing = 0,
Sitting = 1,
Running = 2,
Star = 3,
}

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct CopperGolemStatue {
pub actor: CopperGolemActor,
pub pose: CopperGolemPose,
}
17 changes: 17 additions & 0 deletions crates/level/src/block_entities/decorated_pot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::types::ItemStack;

// Known sherds are: minecraft:brick, minecraft:guster_pottery_sherd

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct DecoratedPot {
pub loot_table: Option<String>,
pub loot_table_seed: Option<i32>,
#[serde(rename = "animation")]
pub animation: i8,
#[serde(rename = "item")]
pub item: ItemStack,
#[serde(rename = "sherds")]
pub sherds: Option<Vec<String>>,
}
10 changes: 10 additions & 0 deletions crates/level/src/block_entities/dispenser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::types::ItemSlot;

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct Dispenser {
pub loot_table: String,
pub items: Vec<ItemSlot>,
pub loot_table_seed: i32,
}
13 changes: 13 additions & 0 deletions crates/level/src/block_entities/enchantment_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/// An enchantment table tile entity.
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct EnchantmentTable {
/// The custom name of this enchantment table.
///
/// May not exist.
pub custom_name: Option<String>,
/// The clockwise rotation of the book on the enchantment table in radians.
///
/// Top of the book points west when set to 0.
pub rotation: f32,
}
11 changes: 11 additions & 0 deletions crates/level/src/block_entities/end_gateway.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use crate::deserialize_bool;

#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct EndGateway {
pub age: i32,
pub exit_portal: [i32; 3],
#[serde(deserialize_with = "deserialize_bool")]
pub end_gateway_bad_pos_checked: bool,
}
8 changes: 8 additions & 0 deletions crates/level/src/block_entities/flower_pot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::subchunk::BlockDef;

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[cfg_attr(feature = "deny-unknown-fields", serde(deny_unknown_fields))]
pub struct FlowerPot {
pub plant_block: Option<BlockDef>,
}
Loading
Loading