feat: implement missing effects

also migrate loot tables from our own extractor to datapack
This commit is contained in:
Alexander Medvedev 2026-09-01 14:16:05 +02:00
parent 0d58f3bfca
commit 3f88eeaba7
72 changed files with 48193 additions and 50117 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -40,8 +40,6 @@ pub struct Block {
pub states: &'static [BlockState],
/// Fire behavior settings. If `None`, the block is not flammable.
pub flammable: Option<Flammable>,
/// Defines the items dropped when this block is destroyed.
pub loot_table: Option<LootTable>,
/// Defines the amount of XP dropped when the block is mined (e.g., Coal or Diamond).
pub experience: Option<Experience>,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -81,12 +81,34 @@ pub struct ConditionalEffect<T> {
pub effect: T,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ReplaceDiskPredicate {
MatchingBlockTag {
offset: pumpkin_util::math::vector3::Vector3<i32>,
tag: &'static crate::tag::Tag,
},
MatchingBlocks {
offset: pumpkin_util::math::vector3::Vector3<i32>,
blocks: &'static [&'static str],
},
MatchingFluids {
offset: pumpkin_util::math::vector3::Vector3<i32>,
fluids: &'static [&'static str],
},
Unobstructed,
AllOf(&'static [ReplaceDiskPredicate]),
}
#[derive(Clone, Debug, PartialEq)]
pub enum EnchantmentEntityEffect {
Ignite {
duration: LevelBasedValue,
},
DamageEntity {
damage: LevelBasedValue,
min_damage: LevelBasedValue,
max_damage: LevelBasedValue,
damage_type: Option<&'static crate::damage::DamageType>,
},
ChangeItemDamage {
amount: LevelBasedValue,
},
PlaySound {
sound: &'static str,
@ -97,6 +119,53 @@ pub enum EnchantmentEntityEffect {
offset_z: i32,
trigger_game_event: Option<crate::game_event::GameEvent>,
},
SetBlockProperties {
properties: &'static [(&'static str, &'static str)],
offset_x: i32,
offset_y: i32,
offset_z: i32,
trigger_game_event: Option<crate::game_event::GameEvent>,
},
ReplaceDisk {
radius: LevelBasedValue,
height: LevelBasedValue,
offset_x: i32,
offset_y: i32,
offset_z: i32,
predicate: Option<ReplaceDiskPredicate>,
block_state: &'static crate::block_state::BlockState,
trigger_game_event: Option<crate::game_event::GameEvent>,
},
SummonEntity {
entity_types: &'static [&'static crate::entity::EntityType],
join_team: bool,
},
SpawnParticles {
particle: crate::particle::Particle,
horizontal_position: PositionSource,
vertical_position: PositionSource,
horizontal_velocity: VelocitySource,
vertical_velocity: VelocitySource,
speed: pumpkin_util::math::float_provider::FloatProvider,
},
RunFunction {
function: &'static str,
},
ApplyExhaustion {
amount: LevelBasedValue,
},
ApplyImpulse {
direction: pumpkin_util::math::vector3::Vector3<f64>,
coordinate_scale: pumpkin_util::math::vector3::Vector3<f64>,
magnitude: LevelBasedValue,
},
ApplyMobEffect {
to_apply: &'static [&'static crate::effect::StatusEffect],
min_duration: LevelBasedValue,
max_duration: LevelBasedValue,
min_amplifier: LevelBasedValue,
max_amplifier: LevelBasedValue,
},
Explode {
attribute_to_user: bool,
damage_type: Option<&'static crate::damage::DamageType>,
@ -115,6 +184,114 @@ pub enum EnchantmentEntityEffect {
AllOf(&'static [EnchantmentEntityEffect]),
Other,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub enum PositionSourceType {
#[default]
EntityPosition,
InBoundingBox,
}
impl PositionSourceType {
#[must_use]
pub fn get_coordinate(
self,
position: f64,
center: f64,
bounding_box_span: f32,
random: &mut impl pumpkin_util::random::RandomImpl,
) -> f64 {
match self {
Self::EntityPosition => position,
Self::InBoundingBox => {
let random_offset = f64::from(random.next_f32()) - 0.5;
center + random_offset * f64::from(bounding_box_span)
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct PositionSource {
pub source_type: PositionSourceType,
pub offset: f32,
pub scale: f32,
}
impl PositionSource {
#[must_use]
pub const fn new(source_type: PositionSourceType, offset: f32, scale: f32) -> Self {
Self {
source_type,
offset,
scale,
}
}
#[must_use]
pub const fn offset_from_entity_position(offset: f32) -> Self {
Self {
source_type: PositionSourceType::EntityPosition,
offset,
scale: 1.0,
}
}
#[must_use]
pub const fn in_bounding_box() -> Self {
Self {
source_type: PositionSourceType::InBoundingBox,
offset: 0.0,
scale: 1.0,
}
}
#[must_use]
pub fn get_coordinate(
&self,
position: f64,
center: f64,
bounding_box_span: f32,
random: &mut impl pumpkin_util::random::RandomImpl,
) -> f64 {
self.source_type
.get_coordinate(position, center, bounding_box_span * self.scale, random)
+ f64::from(self.offset)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct VelocitySource {
pub movement_scale: f32,
pub base: pumpkin_util::math::float_provider::FloatProvider,
}
impl VelocitySource {
#[must_use]
pub const fn new(
movement_scale: f32,
base: pumpkin_util::math::float_provider::FloatProvider,
) -> Self {
Self {
movement_scale,
base,
}
}
#[must_use]
pub const fn movement_scaled(scale: f32) -> Self {
Self {
movement_scale: scale,
base: pumpkin_util::math::float_provider::FloatProvider::Constant(0.0),
}
}
#[must_use]
pub const fn fixed_velocity(
provider: pumpkin_util::math::float_provider::FloatProvider,
) -> Self {
Self {
movement_scale: 0.0,
base: provider,
}
}
pub fn get_velocity(
&self,
movement: f64,
random: &mut impl pumpkin_util::random::RandomImpl,
) -> f64 {
f64::from(self.movement_scale).mul_add(movement, f64::from(self.base.get(random)))
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum EnchantmentValueEffect {
Add(LevelBasedValue),
@ -166,6 +343,7 @@ pub struct EnchantmentEffects {
pub trident_return_acceleration: &'static [ConditionalEffect<EnchantmentValueEffect>],
pub trident_spin_attack_strength: Option<EnchantmentValueEffect>,
pub crossbow_charge_time: Option<EnchantmentValueEffect>,
pub location_changed: &'static [ConditionalEffect<EnchantmentEntityEffect>],
pub prevent_armor_change: bool,
pub prevent_equipment_drop: bool,
}
@ -324,6 +502,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -352,7 +531,16 @@ impl Enchantment {
post_attack: &[TargetedConditionalEffect {
enchanted: Some(EnchantmentTarget::Attacker),
affected: Some(EnchantmentTarget::Victim),
effect: EnchantmentEntityEffect::Other,
effect: EnchantmentEntityEffect::ApplyMobEffect {
to_apply: &[&crate::effect::StatusEffect::SLOWNESS],
min_duration: LevelBasedValue::Constant(1.5f32),
max_duration: LevelBasedValue::Linear {
base: 1.5f32,
per_level_above_first: 0.5f32,
},
min_amplifier: LevelBasedValue::Constant(3f32),
max_amplifier: LevelBasedValue::Constant(3f32),
},
}],
projectile_count: &[],
projectile_spread: &[],
@ -379,6 +567,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -425,6 +614,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: true,
prevent_equipment_drop: false,
},
@ -476,6 +666,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -527,6 +718,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -556,7 +748,10 @@ impl Enchantment {
enchanted: Some(EnchantmentTarget::Attacker),
affected: Some(EnchantmentTarget::Victim),
effect: EnchantmentEntityEffect::AllOf(&[
EnchantmentEntityEffect::Other,
EnchantmentEntityEffect::SummonEntity {
entity_types: &[&crate::entity::EntityType::LIGHTNING_BOLT],
join_team: false,
},
EnchantmentEntityEffect::PlaySound {
sound: "minecraft:item.trident.thunder",
},
@ -572,7 +767,10 @@ impl Enchantment {
damage_protection: &[],
hit_block: &[ConditionalEffect {
effect: EnchantmentEntityEffect::AllOf(&[
EnchantmentEntityEffect::Other,
EnchantmentEntityEffect::SummonEntity {
entity_types: &[&crate::entity::EntityType::LIGHTNING_BOLT],
join_team: false,
},
EnchantmentEntityEffect::PlaySound {
sound: "minecraft:item.trident.thunder",
},
@ -589,6 +787,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -640,6 +839,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -686,6 +886,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -732,6 +933,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -783,6 +985,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -838,6 +1041,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -889,6 +1093,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -939,6 +1144,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -985,6 +1191,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1031,6 +1238,39 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[ConditionalEffect {
effect: EnchantmentEntityEffect::ReplaceDisk {
radius: LevelBasedValue::Clamped {
value: &LevelBasedValue::Linear {
base: 3f32,
per_level_above_first: 1f32,
},
min: 0f32,
max: 16f32,
},
height: LevelBasedValue::Constant(1f32),
offset_x: 0i32,
offset_y: -1i32,
offset_z: 0i32,
predicate: Some(ReplaceDiskPredicate::AllOf(&[
ReplaceDiskPredicate::MatchingBlockTag {
offset: pumpkin_util::math::vector3::Vector3::new(0i32, 1i32, 0i32),
tag: &crate::tag::Block::MINECRAFT_AIR,
},
ReplaceDiskPredicate::MatchingBlocks {
offset: pumpkin_util::math::vector3::Vector3::new(0i32, 0i32, 0i32),
blocks: &["minecraft:water"],
},
ReplaceDiskPredicate::MatchingFluids {
offset: pumpkin_util::math::vector3::Vector3::new(0i32, 0i32, 0i32),
fluids: &["minecraft:water"],
},
ReplaceDiskPredicate::Unobstructed,
])),
block_state: crate::Block::FROSTED_ICE.default_state,
trigger_game_event: Some(crate::game_event::GameEvent::BlockPlace),
},
}],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1082,6 +1322,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1130,6 +1371,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1181,6 +1423,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1234,6 +1477,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1285,6 +1529,7 @@ impl Enchantment {
}],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1336,6 +1581,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1382,6 +1628,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1433,6 +1680,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1481,6 +1729,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1537,6 +1786,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1588,6 +1838,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1639,6 +1890,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1690,6 +1942,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1741,6 +1994,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1792,6 +2046,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1844,6 +2099,7 @@ impl Enchantment {
base: -0.25f32,
per_level_above_first: -0.25f32,
})),
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1890,6 +2146,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1941,6 +2198,7 @@ impl Enchantment {
},
)),
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -1992,6 +2250,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2040,6 +2299,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2091,6 +2351,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2137,6 +2398,19 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[
ConditionalEffect {
effect: EnchantmentEntityEffect::AllOf(&[
EnchantmentEntityEffect::Other,
EnchantmentEntityEffect::Other,
]),
},
ConditionalEffect {
effect: EnchantmentEntityEffect::ChangeItemDamage {
amount: LevelBasedValue::Constant(1f32),
},
},
],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2183,6 +2457,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2229,6 +2504,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2259,9 +2535,13 @@ impl Enchantment {
affected: Some(EnchantmentTarget::Attacker),
effect: EnchantmentEntityEffect::AllOf(&[
EnchantmentEntityEffect::DamageEntity {
damage: LevelBasedValue::Constant(1f32),
min_damage: LevelBasedValue::Constant(1f32),
max_damage: LevelBasedValue::Constant(5f32),
damage_type: Some(&crate::damage::DamageType::THORNS),
},
EnchantmentEntityEffect::ChangeItemDamage {
amount: LevelBasedValue::Constant(2f32),
},
EnchantmentEntityEffect::Other,
]),
}],
projectile_count: &[],
@ -2284,6 +2564,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2355,6 +2636,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2401,6 +2683,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: true,
},
@ -2471,6 +2754,7 @@ impl Enchantment {
trident_return_acceleration: &[],
trident_spin_attack_strength: None,
crossbow_charge_time: None,
location_changed: &[],
prevent_armor_change: false,
prevent_equipment_drop: false,
},
@ -2714,4 +2998,9 @@ impl Enchantment {
) -> &'static [ConditionalEffect<EnchantmentEntityEffect>] {
self.effects.projectile_spawned
}
pub fn get_location_changed_effects(
&self,
) -> &'static [ConditionalEffect<EnchantmentEntityEffect>] {
self.effects.location_changed
}
}

File diff suppressed because it is too large Load Diff

View File

@ -64,6 +64,72 @@ pub enum GameEvent {
Resonate15,
}
impl GameEvent {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
Self::BlockActivate => "block_activate",
Self::BlockAttach => "block_attach",
Self::BlockChange => "block_change",
Self::BlockClose => "block_close",
Self::BlockDeactivate => "block_deactivate",
Self::BlockDestroy => "block_destroy",
Self::BlockDetach => "block_detach",
Self::BlockOpen => "block_open",
Self::BlockPlace => "block_place",
Self::Bounce => "bounce",
Self::ContainerClose => "container_close",
Self::ContainerOpen => "container_open",
Self::Drink => "drink",
Self::Eat => "eat",
Self::ElytraGlide => "elytra_glide",
Self::EntityDamage => "entity_damage",
Self::EntityDie => "entity_die",
Self::EntityDismount => "entity_dismount",
Self::EntityInteract => "entity_interact",
Self::EntityMount => "entity_mount",
Self::EntityPlace => "entity_place",
Self::EntityAction => "entity_action",
Self::Equip => "equip",
Self::Explode => "explode",
Self::Flap => "flap",
Self::FluidPickup => "fluid_pickup",
Self::FluidPlace => "fluid_place",
Self::HitGround => "hit_ground",
Self::InstrumentPlay => "instrument_play",
Self::ItemInteractFinish => "item_interact_finish",
Self::ItemInteractStart => "item_interact_start",
Self::JukeboxPlay => "jukebox_play",
Self::JukeboxStopPlay => "jukebox_stop_play",
Self::LightningStrike => "lightning_strike",
Self::NoteBlockPlay => "note_block_play",
Self::PrimeFuse => "prime_fuse",
Self::ProjectileLand => "projectile_land",
Self::ProjectileShoot => "projectile_shoot",
Self::SculkSensorTendrilsClicking => "sculk_sensor_tendrils_clicking",
Self::Shear => "shear",
Self::Shriek => "shriek",
Self::Splash => "splash",
Self::Step => "step",
Self::Swim => "swim",
Self::Teleport => "teleport",
Self::Unequip => "unequip",
Self::Resonate1 => "resonate_1",
Self::Resonate2 => "resonate_2",
Self::Resonate3 => "resonate_3",
Self::Resonate4 => "resonate_4",
Self::Resonate5 => "resonate_5",
Self::Resonate6 => "resonate_6",
Self::Resonate7 => "resonate_7",
Self::Resonate8 => "resonate_8",
Self::Resonate9 => "resonate_9",
Self::Resonate10 => "resonate_10",
Self::Resonate11 => "resonate_11",
Self::Resonate12 => "resonate_12",
Self::Resonate13 => "resonate_13",
Self::Resonate14 => "resonate_14",
Self::Resonate15 => "resonate_15",
}
}
#[must_use]
pub fn from_name(name: &str) -> Option<Self> {
match name {

View File

@ -84931,7 +84931,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const APPLE : Self = Self { id : 878 , registry_key : "minecraft:apple" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x17minecraft:use_animation\x08\x05value\x03eat\0\n\x0Eminecraft:tags\t\x04tags\x08\x02\x11minecraft:is_food\0\n\x0Eminecraft:food\n\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\tnutrition\x08\0\n\x0Fitem_properties\x03\x11enchantable_value\0\x01\x04foil\0\x08\x0Ecreative_group\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x05apple\0\0\x03\x0Bframe_count\x02\x01\rhand_equipped\0\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x01\x12hidden_in_commands\x02\x05\x0Cmining_speed\0\0\x80?\x03\x0Emax_stack_size\x80\x01\x03\ruse_animation\x02\x03\x11creative_category\x04\x01\x0Eliquid_clipped\0\x01\x0Fstacked_by_data\0\x01\x17can_destroy_in_creative\x01\x03\x06damage\0\x03\x0Cuse_duration@\x08\x10enchantable_slot\x04none\0\n\x16minecraft:display_name\x08\x05value\x0Fitem.apple.name\0\t\titem_tags\x08\x02\x11minecraft:is_food\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\x01\x05\x11movement_modifier33\xB3>\x05\x0Cuse_duration\xCD\xCC\xCC?\x08\x0Bstart_using\x06always\0\0\0" } ;
pub const APPLE : Self = Self { id : 878 , registry_key : "minecraft:apple" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\n\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x03\tnutrition\x08\x05\x13saturation_modifier\x9A\x99\x99>\0\n\x0Fitem_properties\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x05apple\0\0\x01\x04foil\0\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x01\x17can_destroy_in_creative\x01\x03\ruse_animation\x02\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration@\x08\x0Ecreative_group\0\x01\x0Eliquid_clipped\0\x01\x0Eallow_off_hand\0\x03\x06damage\0\x03\x11enchantable_value\0\x03\x0Emax_stack_size\x80\x01\x01\rhand_equipped\0\x03\x11creative_category\x04\x03\x0Bframe_count\x02\0\n\x16minecraft:display_name\x08\x05value\x0Fitem.apple.name\0\n\x17minecraft:use_animation\x08\x05value\x03eat\0\n\x0Eminecraft:tags\t\x04tags\x08\x02\x11minecraft:is_food\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\x01\x08\x0Bstart_using\x06always\x05\x0Cuse_duration\xCD\xCC\xCC?\x05\x11movement_modifier33\xB3>\0\t\titem_tags\x08\x02\x11minecraft:is_food\0\0" } ;
pub const ARCHER_POTTERY_SHERD: Self = Self {
id: 671,
registry_key: "minecraft:archer_pottery_sherd",
@ -85016,7 +85016,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BAKED_POTATO : Self = Self { id : 281 , registry_key : "minecraft:baked_potato" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x19?\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\n\x03\rcooldown_time\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const BAKED_POTATO : Self = Self { id : 281 , registry_key : "minecraft:baked_potato" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\0\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x19?\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x03\tnutrition\n\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const BALLOON: Self = Self {
id: 612,
registry_key: "minecraft:balloon",
@ -85269,7 +85269,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BEEF : Self = Self { id : 273 , registry_key : "minecraft:beef" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x03\tnutrition\x06\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\0\0" } ;
pub const BEEF : Self = Self { id : 273 , registry_key : "minecraft:beef" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x06\x08\rcooldown_type\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\0\0\0" } ;
pub const BEEHIVE: Self = Self {
id: -219,
registry_key: "minecraft:beehive",
@ -85277,9 +85277,9 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BEETROOT : Self = Self { id : 285 , registry_key : "minecraft:beetroot" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x19?\x03\ron_use_action\x01\x08\rcooldown_type\0\x03\tnutrition\x02\0\0\0" } ;
pub const BEETROOT_SEEDS : Self = Self { id : 295 , registry_key : "minecraft:beetroot_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\x0Bcrop_result\x12minecraft:beetroot\x01\x1Aplant_at_any_solid_surface\0\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\0\0\0" } ;
pub const BEETROOT_SOUP : Self = Self { id : 286 , registry_key : "minecraft:beetroot_soup" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x19?\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\x04bowl\x01\x0Ecan_always_eat\0\x03\tnutrition\x0C\x03\ron_use_action\x01\0\x03\x16minecraft:use_duration@\x03\x18minecraft:max_stack_size\x02\0\0" } ;
pub const BEETROOT : Self = Self { id : 285 , registry_key : "minecraft:beetroot" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x19?\x03\tnutrition\x02\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\0\0\0" } ;
pub const BEETROOT_SEEDS : Self = Self { id : 295 , registry_key : "minecraft:beetroot_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\x0Bcrop_result\x12minecraft:beetroot\x08\rplant_at_face\x02up\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\0\0\0" } ;
pub const BEETROOT_SOUP : Self = Self { id : 286 , registry_key : "minecraft:beetroot_soup" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x19?\x03\tnutrition\x0C\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x08\x11using_converts_to\x04bowl\x03\rcooldown_time\0\0\x03\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\0\0" } ;
pub const BELL: Self = Self {
id: -206,
registry_key: "minecraft:bell",
@ -85441,7 +85441,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BLACK_BUNDLE : Self = Self { id : 857 , registry_key : "minecraft:black_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\0\n\x0Fitem_properties\x03\x06damage\0\x08\x10enchantable_slot\x04none\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x16bundle_black_open_back\x08\x11bundle_open_front\x17bundle_black_open_front\x08\x07default\x0Cbundle_black\0\0\x01\x17can_destroy_in_creative\x01\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x03\x11creative_category\x06\x03\ruse_animation\0\x08\x0Ecreative_group\0\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\0\x01\x04foil\0\x01\x0Eshould_despawn\x01\x03\x11enchantable_value\0\x01\rhand_equipped\0\x03\x0Emax_stack_size\x02\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\0\0" } ;
pub const BLACK_BUNDLE : Self = Self { id : 857 , registry_key : "minecraft:black_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x16minecraft:storage_item\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\0\n\x0Fitem_properties\x08\x0Ecreative_group\0\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x03\x06damage\0\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x04none\x01\x04foil\0\x01\rhand_equipped\0\x03\x11enchantable_value\0\x03\ruse_animation\0\x03\x0Cuse_duration\0\x03\x0Emax_stack_size\x02\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x17bundle_black_open_front\x08\x10bundle_open_back\x16bundle_black_open_back\x08\x07default\x0Cbundle_black\0\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const BLACK_CANDLE: Self = Self {
id: -428,
registry_key: "minecraft:black_candle",
@ -85617,7 +85617,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BLUE_BUNDLE : Self = Self { id : 858 , registry_key : "minecraft:blue_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\t\titem_tags\0\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\0\n\x0Fitem_properties\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x16bundle_blue_open_front\x08\x07default\x0Bbundle_blue\x08\x10bundle_open_back\x15bundle_blue_open_back\0\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x01\x04foil\0\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\x03\x06damage\0\x03\x11enchantable_value\0\x01\rhand_equipped\0\x03\x11creative_category\x06\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const BLUE_BUNDLE : Self = Self { id : 858 , registry_key : "minecraft:blue_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x0Fitem_properties\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x08\x10enchantable_slot\x04none\x01\rhand_equipped\0\x01\x17can_destroy_in_creative\x01\x03\ruse_animation\0\x03\x06damage\0\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bbundle_blue\x08\x11bundle_open_front\x16bundle_blue_open_front\x08\x10bundle_open_back\x15bundle_blue_open_back\0\0\x03\x11enchantable_value\0\x03\x11creative_category\x06\x01\x04foil\0\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\0\t\titem_tags\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\0\0" } ;
pub const BLUE_CANDLE: Self = Self {
id: -424,
registry_key: "minecraft:blue_candle",
@ -85856,8 +85856,8 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BREAD : Self = Self { id : 261 , registry_key : "minecraft:bread" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x19?\x03\ron_use_action\x01\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\tnutrition\n\x03\rcooldown_time\0\0\0\0" } ;
pub const BREEZE_ROD : Self = Self { id : 874 , registry_key : "minecraft:breeze_rod" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x03\x0Bframe_count\x02\x03\ruse_animation\0\x03\x0Cuse_duration\0\x08\x10enchantable_slot\x04none\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nbreeze_rod\0\0\x01\x0Fstacked_by_data\0\x01\rhand_equipped\x01\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x08\x08\x0Ecreative_group\0\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x80\x01\x03\x06damage\0\x01\x04foil\0\0\n\x16minecraft:display_name\x08\x05value\x14item.breeze_rod.name\0\t\titem_tags\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\0\0" } ;
pub const BREAD : Self = Self { id : 261 , registry_key : "minecraft:bread" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\x03\tnutrition\n\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x19?\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const BREEZE_ROD : Self = Self { id : 874 , registry_key : "minecraft:breeze_rod" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x17minecraft:hand_equipped\x01\x05value\x01\0\t\titem_tags\0\0\n\x0Fitem_properties\x01\rhand_equipped\x01\x01\x12hidden_in_commands\x02\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nbreeze_rod\0\0\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x80\x01\x03\x11enchantable_value\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x03\x0Cuse_duration\0\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\x0Eallow_off_hand\0\x03\x06damage\0\x03\x11creative_category\x08\x01\x17can_destroy_in_creative\x01\x01\x04foil\0\0\n\x16minecraft:display_name\x08\x05value\x14item.breeze_rod.name\0\0\0" } ;
pub const BREEZE_SPAWN_EGG: Self = Self {
id: 506,
registry_key: "minecraft:breeze_spawn_egg",
@ -85921,7 +85921,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BROWN_BUNDLE : Self = Self { id : 859 , registry_key : "minecraft:brown_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Cbundle_brown\x08\x10bundle_open_back\x16bundle_brown_open_back\x08\x11bundle_open_front\x17bundle_brown_open_front\0\0\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x03\ruse_animation\0\x01\rhand_equipped\0\x03\x0Bframe_count\x02\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x03\x06damage\0\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\t\titem_tags\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const BROWN_BUNDLE : Self = Self { id : 859 , registry_key : "minecraft:brown_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x0Fitem_properties\x03\x06damage\0\x01\rhand_equipped\0\x08\x0Ecreative_group\0\x03\x11enchantable_value\0\x05\x0Cmining_speed\0\0\x80?\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x02\x01\x12hidden_in_commands\x02\x01\x17can_destroy_in_creative\x01\x01\x0Fstacked_by_data\0\x03\x0Bframe_count\x02\x01\x04foil\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x16bundle_brown_open_back\x08\x11bundle_open_front\x17bundle_brown_open_front\x08\x07default\x0Cbundle_brown\0\0\x08\x10enchantable_slot\x04none\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\0\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const BROWN_CANDLE: Self = Self {
id: -425,
registry_key: "minecraft:brown_candle",
@ -86097,7 +86097,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const BUNDLE : Self = Self { id : 860 , registry_key : "minecraft:bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\0\t\titem_tags\0\0\n\x0Fitem_properties\x01\x04foil\0\x01\x12hidden_in_commands\x02\x03\ruse_animation\0\x08\x0Ecreative_group\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x06bundle\x08\x11bundle_open_front\x11bundle_open_front\x08\x10bundle_open_back\x10bundle_open_back\0\0\x03\x11creative_category\x06\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\x08\x10enchantable_slot\x04none\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x01\x17can_destroy_in_creative\x01\x03\x06damage\0\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x03\x11enchantable_value\0\x01\x0Eallow_off_hand\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const BUNDLE : Self = Self { id : 860 , registry_key : "minecraft:bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x03\x06damage\0\x03\x0Cuse_duration\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x06bundle\x08\x11bundle_open_front\x11bundle_open_front\x08\x10bundle_open_back\x10bundle_open_back\0\0\x08\x0Ecreative_group\0\x01\x0Eallow_off_hand\0\x03\ruse_animation\0\x01\x0Fstacked_by_data\0\x03\x0Emax_stack_size\x02\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\x01\rhand_equipped\0\x03\x0Bframe_count\x02\x01\x04foil\0\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\0\0\0" } ;
pub const BURN_POTTERY_SHERD: Self = Self {
id: 675,
registry_key: "minecraft:burn_pottery_sherd",
@ -86161,7 +86161,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const CAMERA : Self = Self { id : 607 , registry_key : "minecraft:camera" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration\xC0\x9A\x0C\x08\x0Fminecraft:block\x10minecraft:camera\n\x10minecraft:camera\x05\x10picture_duration\0\0\x80?\x05\x13black_bars_duration\xCD\xCCL>\x05\x10shutter_duration\xCD\xCCL>\x05\x17black_bars_screen_ratio\n\xD7\xA3=\x05\x14shutter_screen_ratio\0\0\0?\x05\x13slide_away_duration\xCD\xCCL>\0\0\0" } ;
pub const CAMERA : Self = Self { id : 607 , registry_key : "minecraft:camera" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x08\x0Fminecraft:block\x10minecraft:camera\n\x10minecraft:camera\x05\x14shutter_screen_ratio\0\0\0?\x05\x13black_bars_duration\xCD\xCCL>\x05\x10picture_duration\0\0\x80?\x05\x10shutter_duration\xCD\xCCL>\x05\x17black_bars_screen_ratio\n\xD7\xA3=\x05\x13slide_away_duration\xCD\xCCL>\0\x03\x16minecraft:use_duration\xC0\x9A\x0C\0\0" } ;
pub const CAMPFIRE: Self = Self {
id: 601,
registry_key: "minecraft:campfire",
@ -86190,7 +86190,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const CARROT : Self = Self { id : 279 , registry_key : "minecraft:carrot" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\x0Bcrop_result\x11minecraft:carrots\x08\rplant_at_face\x02up\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\0\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\x08\rcooldown_type\0\x03\tnutrition\x06\x05\x13saturation_modifier\x9A\x99\x19?\0\0\0" } ;
pub const CARROT : Self = Self { id : 279 , registry_key : "minecraft:carrot" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x19?\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x03\tnutrition\x06\x03\rcooldown_time\0\0\x03\x16minecraft:use_duration@\n\x0Eminecraft:seed\x08\x0Bcrop_result\x11minecraft:carrots\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\t\x08plant_at\x08\x02\x12minecraft:farmland\0\0\0" } ;
pub const CARROT_ON_A_STICK: Self = Self {
id: 527,
registry_key: "minecraft:carrot_on_a_stick",
@ -86492,7 +86492,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const CHICKEN : Self = Self { id : 275 , registry_key : "minecraft:chicken" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x04\t\x07effects\n\x02\x03\tamplifier\0\x08\rdescriptionId\rpotion.hunger\x03\x02id\"\x08\x04name\x06hunger\x05\x06chance\x9A\x99\x99>\x03\x08duration<\0\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const CHICKEN : Self = Self { id : 275 , registry_key : "minecraft:chicken" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\ron_use_action\x01\x03\tnutrition\x04\x08\rcooldown_type\0\t\x07effects\n\x02\x03\tamplifier\0\x05\x06chance\x9A\x99\x99>\x08\x04name\x06hunger\x03\x08duration<\x03\x02id\"\x08\rdescriptionId\rpotion.hunger\0\x03\rcooldown_time\0\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x99>\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\0\0\0" } ;
pub const CHICKEN_SPAWN_EGG: Self = Self {
id: 439,
registry_key: "minecraft:chicken_spawn_egg",
@ -86612,7 +86612,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const CHORUS_FRUIT : Self = Self { id : 568 , registry_key : "minecraft:chorus_fruit" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\rcooldown_time(\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\x01\x03\ron_use_action\0\x03\tnutrition\x08\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x08\rcooldown_type\x0Bchorusfruit\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const CHORUS_FRUIT : Self = Self { id : 568 , registry_key : "minecraft:chorus_fruit" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x01\x0Ecan_always_eat\x01\x08\rcooldown_type\x0Bchorusfruit\x03\tnutrition\x08\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x03\ron_use_action\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time(\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const CHORUS_PLANT: Self = Self {
id: 240,
registry_key: "minecraft:chorus_plant",
@ -86837,7 +86837,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const COD : Self = Self { id : 264 , registry_key : "minecraft:cod" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\tnutrition\x04\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\x03\rcooldown_time\0\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCC\xCC=\0\0\0" } ;
pub const COD : Self = Self { id : 264 , registry_key : "minecraft:cod" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x03\tnutrition\x04\x03\rcooldown_time\0\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCC\xCC=\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COD_BUCKET: Self = Self {
id: 367,
registry_key: "minecraft:cod_bucket",
@ -86964,14 +86964,14 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const COOKED_BEEF : Self = Self { id : 274 , registry_key : "minecraft:cooked_beef" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\tnutrition\x10\x08\rcooldown_type\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCCL?\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_CHICKEN : Self = Self { id : 276 , registry_key : "minecraft:cooked_chicken" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x19?\x03\ron_use_action\x01\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\tnutrition\x0C\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_COD : Self = Self { id : 268 , registry_key : "minecraft:cooked_cod" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x03\ron_use_action\x01\x03\tnutrition\n\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\0\0\0" } ;
pub const COOKED_MUTTON : Self = Self { id : 561 , registry_key : "minecraft:cooked_mutton" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\tnutrition\x0C\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCCL?\x08\rcooldown_type\0\x03\rcooldown_time\0\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_PORKCHOP : Self = Self { id : 263 , registry_key : "minecraft:cooked_porkchop" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x03\ron_use_action\x01\x03\tnutrition\x10\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x05\x13saturation_modifier\xCD\xCCL?\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_RABBIT : Self = Self { id : 289 , registry_key : "minecraft:cooked_rabbit" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\tnutrition\n\x05\x13saturation_modifier\x9A\x99\x19?\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_SALMON : Self = Self { id : 269 , registry_key : "minecraft:cooked_salmon" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\ron_use_action\x01\x05\x13saturation_modifier\xCD\xCCL?\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\tnutrition\x0C\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKIE : Self = Self { id : 271 , registry_key : "minecraft:cookie" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\ron_use_action\x01\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x01\x0Ecan_always_eat\0\x03\tnutrition\x04\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\rcooldown_time\0\0\0\0" } ;
pub const COOKED_BEEF : Self = Self { id : 274 , registry_key : "minecraft:cooked_beef" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x05\x13saturation_modifier\xCD\xCCL?\x08\rcooldown_type\0\x03\tnutrition\x10\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_CHICKEN : Self = Self { id : 276 , registry_key : "minecraft:cooked_chicken" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x19?\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\x03\tnutrition\x0C\x08\rcooldown_type\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_COD : Self = Self { id : 268 , registry_key : "minecraft:cooked_cod" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\n\x03\rcooldown_time\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x19?\0\0\0" } ;
pub const COOKED_MUTTON : Self = Self { id : 561 , registry_key : "minecraft:cooked_mutton" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x03\tnutrition\x0C\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCCL?\x03\ron_use_action\x01\x08\rcooldown_type\0\x08\x11using_converts_to\0\0\0\0" } ;
pub const COOKED_PORKCHOP : Self = Self { id : 263 , registry_key : "minecraft:cooked_porkchop" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\0\x05\x13saturation_modifier\xCD\xCCL?\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x10\x03\ron_use_action\x01\x08\rcooldown_type\0\x03\rcooldown_time\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_RABBIT : Self = Self { id : 289 , registry_key : "minecraft:cooked_rabbit" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x03\rcooldown_time\0\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x19?\x03\tnutrition\n\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COOKED_SALMON : Self = Self { id : 269 , registry_key : "minecraft:cooked_salmon" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x08\rcooldown_type\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCCL?\x03\rcooldown_time\0\x08\x11using_converts_to\0\x03\tnutrition\x0C\0\0\0" } ;
pub const COOKIE : Self = Self { id : 271 , registry_key : "minecraft:cookie" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\0\x03\rcooldown_time\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\tnutrition\x04\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const COPPER_AXE: Self = Self {
id: 750,
registry_key: "minecraft:copper_axe",
@ -87133,7 +87133,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const COPPER_SPEAR : Self = Self { id : 850 , registry_key : "minecraft:copper_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x10minecraft:damage\x02\x05value\x02\0\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Ditem.copper_spear.attack_miss\x08\nattack_hit\x1Citem.copper_spear.attack_hit\0\n\x16minecraft:display_name\x08\x05value\x16item.copper_spear.name\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xFC\x02\0\n\x18minecraft:swing_duration\x05\x05value\x9A\x99Y?\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x16minecraft:copper_spear\0\0\t\x05items\n\x02\x08\x04name\x16minecraft:copper_ingot\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x08\x04type\x06attack\x05\x08duration\x9A\x99Y?\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\x11damage_multiplier\x85\xEBQ?\x05\x0Fdamage_modifier\0\0\0\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\x02\x0Cmax_duration\xFA\0\0\x02\x05delay\r\0\x05\rhitbox_margin\0\0\x80>\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\xA5\0\0\n\x13dismount_conditions\x02\x0Cmax_durationP\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0@A\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\0\0\n\x15minecraft:enchantable\x01\x05value\r\x08\x04slot\x0Bmelee_spear\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x17minecraft:use_modifiers\x08\x0Bstart_sound\x15item.copper_spear.use\x08\x0Bstart_using\x06always\x05\x0Cuse_duration\0\xA0\x8CG\x05\x11movement_modifier\0\0\x80?\x01\x0Femit_vibrations\0\0\n\x19minecraft:piercing_weapon\x05\rhitbox_margin\0\0\x80>\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Ccopper_spear\0\0\x01\x0Fstacked_by_data\0\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x02\x01\x0Eallow_off_hand\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x08\x0Ecreative_group\0\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x05\x0Cmining_speed\0\0\x80?\x03\ruse_animation\0\x03\x11creative_category\x06\x08\x10enchantable_slot\x0Bmelee_spear\x01\x0Eshould_despawn\x01\x01\x04foil\0\x01\rhand_equipped\x01\x03\x06damage\x04\x03\x11enchantable_value\x1A\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\0\0\0" } ;
pub const COPPER_SPEAR : Self = Self { id : 850 , registry_key : "minecraft:copper_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x12minecraft:cooldown\x08\x08category\x05spear\x05\x08duration\x9A\x99Y?\x08\x04type\x06attack\0\n\x15minecraft:enchantable\x01\x05value\r\x08\x04slot\x0Bmelee_spear\0\n\x17minecraft:use_modifiers\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_sound\x15item.copper_spear.use\x01\x0Femit_vibrations\0\x08\x0Bstart_using\x06always\x05\x0Cuse_duration\0\xA0\x8CG\0\n\x19minecraft:piercing_weapon\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Citem.copper_spear.attack_hit\x08\x0Battack_miss\x1Ditem.copper_spear.attack_miss\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x11damage_conditions\x05\x12min_relative_speed33\x93@\x02\x0Cmax_duration\xFA\0\x05\tmin_speed\0\0\0\0\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x13dismount_conditions\x05\tmin_speed\0\0@A\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_durationP\0\0\x02\x05delay\r\0\n\x14knockback_conditions\x02\x0Cmax_duration\xA5\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\0\x05\x0Fdamage_modifier\0\0\0\0\x05\rhitbox_margin\0\0\x80>\x05\x11damage_multiplier\x85\xEBQ?\0\0\n\x0Fitem_properties\x03\x11enchantable_value\x1A\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x01\rhand_equipped\x01\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x08\x10enchantable_slot\x0Bmelee_spear\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x08\x0Ecreative_group\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x04foil\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Ccopper_spear\0\0\x01\x12hidden_in_commands\x02\x03\x06damage\x04\0\n\x10minecraft:damage\x02\x05value\x02\0\0\n\x16minecraft:display_name\x08\x05value\x16item.copper_spear.name\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xFC\x02\0\n\x18minecraft:swing_duration\x05\x05value\x9A\x99Y?\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x16minecraft:copper_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x16minecraft:copper_ingot\0\0\0\0\0" } ;
pub const COPPER_SWORD: Self = Self {
id: 747,
registry_key: "minecraft:copper_sword",
@ -87498,7 +87498,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const CYAN_BUNDLE : Self = Self { id : 861 , registry_key : "minecraft:cyan_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x03\x0Emax_stack_size\x02\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x08\x10enchantable_slot\x04none\x01\rhand_equipped\0\x03\x0Bframe_count\x02\x03\ruse_animation\0\x03\x11creative_category\x06\x01\x17can_destroy_in_creative\x01\x08\x0Ecreative_group\0\x01\x0Eshould_despawn\x01\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\x01\x0Fstacked_by_data\0\x03\x06damage\0\x01\x0Eallow_off_hand\0\x03\x0Cuse_duration\0\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x16bundle_cyan_open_front\x08\x07default\x0Bbundle_cyan\x08\x10bundle_open_back\x15bundle_cyan_open_back\0\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\0\0\0" } ;
pub const CYAN_BUNDLE : Self = Self { id : 861 , registry_key : "minecraft:cyan_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\0\n\x0Fitem_properties\x03\x0Cuse_duration\0\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x04none\x01\x04foil\0\x03\x0Emax_stack_size\x02\x03\ruse_animation\0\x03\x06damage\0\x08\x0Ecreative_group\0\x01\x0Eallow_off_hand\0\x01\x0Fstacked_by_data\0\x03\x11creative_category\x06\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x16bundle_cyan_open_front\x08\x10bundle_open_back\x15bundle_cyan_open_back\x08\x07default\x0Bbundle_cyan\0\0\x03\x11enchantable_value\0\x01\rhand_equipped\0\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\0\0\0" } ;
pub const CYAN_CANDLE: Self = Self {
id: -422,
registry_key: "minecraft:cyan_candle",
@ -88220,7 +88220,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const DIAMOND_SPEAR : Self = Self { id : 851 , registry_key : "minecraft:diamond_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x16minecraft:display_name\x08\x05value\x17item.diamond_spear.name\0\n\x19minecraft:piercing_weapon\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\n\x17minecraft:use_modifiers\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\0\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x16item.diamond_spear.use\0\n\x18minecraft:swing_duration\x05\x05valueff\x86?\0\n\x0Fitem_properties\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x01\x0Fstacked_by_data\0\x08\x10enchantable_slot\x0Bmelee_spear\x03\x0Emax_stack_size\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\rdiamond_spear\0\0\x08\x0Ecreative_group\0\x03\x0Bframe_count\x02\x03\x11creative_category\x06\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x04foil\0\x01\x0Eliquid_clipped\0\x03\x06damage\x08\x01\x0Eallow_off_hand\0\x01\x12hidden_in_commands\x02\x03\x11enchantable_value\x14\x01\x17can_destroy_in_creative\x01\x01\rhand_equipped\x01\0\n\x12minecraft:cooldown\x05\x08durationff\x86?\x08\x08category\x05spear\x08\x04type\x06attack\0\t\titem_tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Ditem.diamond_spear.attack_hit\x08\x0Battack_miss\x1Eitem.diamond_spear.attack_miss\0\n\x10minecraft:damage\x02\x05value\x04\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x14knockback_conditions\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\x82\0\x05\x12min_relative_speed\0\0\0\0\0\x05\x11damage_multiplier\x9A\x99\x89?\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\xC8\0\x05\x12min_relative_speed33\x93@\0\x02\x05delay\n\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\x0Fdamage_modifier\0\0\0\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x13dismount_conditions\x02\x0Cmax_duration<\0\x05\tmin_speed\0\0 A\x05\x12min_relative_speed\0\0\0\0\0\x05\rhitbox_margin\0\0\x80>\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xB0\x18\0\n\x15minecraft:enchantable\x01\x05value\n\x08\x04slot\x0Bmelee_spear\0\n\x0Eminecraft:tags\t\x04tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x17minecraft:diamond_spear\0\0\t\x05items\n\x02\x08\x04name\x11minecraft:diamond\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\0\0" } ;
pub const DIAMOND_SPEAR : Self = Self { id : 851 , registry_key : "minecraft:diamond_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\n\0\n\x16minecraft:display_name\x08\x05value\x17item.diamond_spear.name\0\n\x14minecraft:durability\x03\x0Emax_durability\xB0\x18\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x05\x08durationff\x86?\x08\x04type\x06attack\0\n\x10minecraft:damage\x02\x05value\x04\0\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x17minecraft:diamond_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x11minecraft:diamond\0\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x18minecraft:swing_duration\x05\x05valueff\x86?\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\x11damage_multiplier\x9A\x99\x89?\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\x82\0\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration<\0\x05\tmin_speed\0\0 A\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x11damage_conditions\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\xC8\0\0\x05\x0Fdamage_modifier\0\0\0\0\x02\x05delay\n\0\0\0\n\x19minecraft:piercing_weapon\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\x05\rhitbox_margin\0\0\x80>\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x17minecraft:use_modifiers\x08\x0Bstart_using\x06always\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_sound\x16item.diamond_spear.use\x01\x0Femit_vibrations\0\x05\x0Cuse_duration\0\xA0\x8CG\0\t\titem_tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Eitem.diamond_spear.attack_miss\x08\nattack_hit\x1Ditem.diamond_spear.attack_hit\0\n\x0Eminecraft:tags\t\x04tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\0\n\x0Fitem_properties\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x03\x11creative_category\x06\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\rdiamond_spear\0\0\x03\ruse_animation\0\x05\x0Cmining_speed\0\0\x80?\x03\x06damage\x08\x01\x12hidden_in_commands\x02\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x0Bmelee_spear\x03\x11enchantable_value\x14\x03\x0Emax_stack_size\x02\x01\x04foil\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\rhand_equipped\x01\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\0\0\0" } ;
pub const DIAMOND_SWORD: Self = Self {
id: 318,
registry_key: "minecraft:diamond_sword",
@ -88375,7 +88375,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const DRIED_KELP : Self = Self { id : 270 , registry_key : "minecraft:dried_kelp" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration \n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x08\rcooldown_type\0\x03\tnutrition\x02\x05\x13saturation_modifier\xCD\xCC\xCC=\x08\x11using_converts_to\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\0\0" } ;
pub const DRIED_KELP : Self = Self { id : 270 , registry_key : "minecraft:dried_kelp" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\x03\tnutrition\x02\x08\rcooldown_type\0\x03\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration \0\0" } ;
pub const DRIED_KELP_BLOCK: Self = Self {
id: -139,
registry_key: "minecraft:dried_kelp_block",
@ -89321,7 +89321,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const ENCHANTED_GOLDEN_APPLE : Self = Self { id : 259 , registry_key : "minecraft:enchanted_golden_apple" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x99?\x03\ron_use_action\x01\x03\rcooldown_time\0\x08\x11using_converts_to\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\x01\x03\tnutrition\x08\t\x07effects\n\x08\x03\tamplifier\x02\x03\x02id\x14\x08\x04name\x0Cregeneration\x05\x06chance\0\0\x80?\x03\x08duration<\x08\rdescriptionId\x13potion.regeneration\0\x03\x02id,\x05\x06chance\0\0\x80?\x08\x04name\nabsorption\x03\tamplifier\x06\x03\x08duration\xF0\x01\x08\rdescriptionId\x11potion.absorption\0\x03\x02id\x16\x08\x04name\nresistance\x05\x06chance\0\0\x80?\x08\rdescriptionId\x11potion.resistance\x03\tamplifier\0\x03\x08duration\xD8\x04\0\x03\x08duration\xD8\x04\x08\rdescriptionId\x15potion.fireResistance\x05\x06chance\0\0\x80?\x03\tamplifier\0\x03\x02id\x18\x08\x04name\x0Ffire_resistance\0\0\x01\x19minecraft:stacked_by_data\x01\x01\x0Eminecraft:foil\x01\x03\x16minecraft:use_duration@\0\0" } ;
pub const ENCHANTED_GOLDEN_APPLE : Self = Self { id : 259 , registry_key : "minecraft:enchanted_golden_apple" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\x01\x0Eminecraft:foil\x01\n\x0Eminecraft:food\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x99?\t\x07effects\n\x08\x08\x04name\x0Cregeneration\x08\rdescriptionId\x13potion.regeneration\x03\x08duration<\x03\x02id\x14\x03\tamplifier\x02\x05\x06chance\0\0\x80?\0\x08\rdescriptionId\x11potion.absorption\x03\tamplifier\x06\x03\x02id,\x08\x04name\nabsorption\x05\x06chance\0\0\x80?\x03\x08duration\xF0\x01\0\x05\x06chance\0\0\x80?\x03\tamplifier\0\x08\rdescriptionId\x11potion.resistance\x03\x08duration\xD8\x04\x03\x02id\x16\x08\x04name\nresistance\0\x03\x08duration\xD8\x04\x05\x06chance\0\0\x80?\x03\x02id\x18\x08\rdescriptionId\x15potion.fireResistance\x08\x04name\x0Ffire_resistance\x03\tamplifier\0\0\x08\x11using_converts_to\0\x03\tnutrition\x08\x01\x0Ecan_always_eat\x01\x03\ron_use_action\x01\0\0\0" } ;
pub const ENCHANTING_TABLE: Self = Self {
id: 116,
registry_key: "minecraft:enchanting_table",
@ -89896,7 +89896,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const GLOW_BERRIES : Self = Self { id : 879 , registry_key : "minecraft:glow_berries" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\tnutrition\x04\x05\x13saturation_modifier\x9A\x99\x99>\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x08\x11using_converts_to\0\x03\ron_use_action\x01\0\n\x0Eminecraft:seed\t\x08plant_at\x08\x04\ncave_vines\x1Ccave_vines_head_with_berries\x08\x0Bcrop_result\x14minecraft:cave_vines\x01\x1Aplant_at_any_solid_surface\x01\x08\rplant_at_face\x04down\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const GLOW_BERRIES : Self = Self { id : 879 , registry_key : "minecraft:glow_berries" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x99>\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\tnutrition\x04\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\ron_use_action\x01\0\x03\x16minecraft:use_duration@\n\x0Eminecraft:seed\x08\rplant_at_face\x04down\x01\x1Aplant_at_any_solid_surface\x01\x08\x0Bcrop_result\x14minecraft:cave_vines\t\x08plant_at\x08\x04\ncave_vines\x1Ccave_vines_head_with_berries\0\0\0" } ;
pub const GLOW_FRAME: Self = Self {
id: 636,
registry_key: "minecraft:glow_frame",
@ -89995,7 +89995,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const GOLDEN_APPLE : Self = Self { id : 258 , registry_key : "minecraft:golden_apple" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\tnutrition\x08\x03\rcooldown_time\0\x01\x0Ecan_always_eat\x01\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\t\x07effects\n\x04\x03\tamplifier\x02\x05\x06chance\0\0\x80?\x03\x08duration\n\x03\x02id\x14\x08\x04name\x0Cregeneration\x08\rdescriptionId\x13potion.regeneration\0\x03\x08duration\xF0\x01\x03\tamplifier\0\x03\x02id,\x08\x04name\nabsorption\x05\x06chance\0\0\x80?\x08\rdescriptionId\x11potion.absorption\0\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99?\x08\x11using_converts_to\0\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\0\0" } ;
pub const GOLDEN_APPLE : Self = Self { id : 258 , registry_key : "minecraft:golden_apple" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\tnutrition\x08\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x99?\t\x07effects\n\x04\x08\rdescriptionId\x13potion.regeneration\x03\tamplifier\x02\x03\x08duration\n\x03\x02id\x14\x08\x04name\x0Cregeneration\x05\x06chance\0\0\x80?\0\x03\x08duration\xF0\x01\x08\x04name\nabsorption\x05\x06chance\0\0\x80?\x03\x02id,\x03\tamplifier\0\x08\rdescriptionId\x11potion.absorption\0\x08\x11using_converts_to\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\x01\x03\rcooldown_time\0\0\x01\x19minecraft:stacked_by_data\x01\0\0" } ;
pub const GOLDEN_AXE: Self = Self {
id: 328,
registry_key: "minecraft:golden_axe",
@ -90010,7 +90010,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const GOLDEN_CARROT : Self = Self { id : 283 , registry_key : "minecraft:golden_carrot" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\rcooldown_time\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99?\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x03\tnutrition\x0C\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const GOLDEN_CARROT : Self = Self { id : 283 , registry_key : "minecraft:golden_carrot" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99?\x03\tnutrition\x0C\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\rcooldown_time\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const GOLDEN_CHESTPLATE: Self = Self {
id: 355,
registry_key: "minecraft:golden_chestplate",
@ -90081,7 +90081,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const GOLDEN_SPEAR : Self = Self { id : 852 , registry_key : "minecraft:golden_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability<\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\x0Fdamage_modifier\0\0\0\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\xAA\0\0\x05\x11damage_multiplier333?\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x02\x05delay\x0E\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0PA\x02\x0Cmax_durationF\0\0\x05\rhitbox_margin\0\0\x80>\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\x13\x01\x05\x12min_relative_speed33\x93@\0\0\0\t\titem_tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\n\x18minecraft:swing_duration\x05\x05value33s?\0\n\x15minecraft:enchantable\x01\x05value\x16\x08\x04slot\x0Bmelee_spear\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_using\x06always\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x15item.golden_spear.use\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Citem.golden_spear.attack_hit\x08\x0Battack_miss\x1Ditem.golden_spear.attack_miss\0\n\x0Fitem_properties\x01\x04foil\0\x08\x0Ecreative_group\0\x05\x0Cmining_speed\0\0\x80?\x03\ruse_animation\0\x03\x11creative_category\x06\x08\x10enchantable_slot\x0Bmelee_spear\x01\x0Eshould_despawn\x01\x01\rhand_equipped\x01\x03\x0Emax_stack_size\x02\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x11enchantable_value,\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ngold_spear\0\0\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x06damage\x02\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x10minecraft:damage\x02\x05value\x01\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x05\x08duration33s?\x08\x08category\x05spear\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\n\x16minecraft:display_name\x08\x05value\x16item.golden_spear.name\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x16minecraft:golden_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\t\x05items\n\x02\x08\x04name\x14minecraft:gold_ingot\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\0\0" } ;
pub const GOLDEN_SPEAR : Self = Self { id : 852 , registry_key : "minecraft:golden_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x17minecraft:use_modifiers\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\0\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x15item.golden_spear.use\0\n\x18minecraft:swing_duration\x05\x05value33s?\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x05\x08duration33s?\x08\x04type\x06attack\0\n\x16minecraft:display_name\x08\x05value\x16item.golden_spear.name\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability<\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Ditem.golden_spear.attack_miss\x08\nattack_hit\x1Citem.golden_spear.attack_hit\0\n\x0Fitem_properties\x03\ruse_animation\0\x03\x11enchantable_value,\x01\x12hidden_in_commands\x02\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x06damage\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ngold_spear\0\0\x01\x0Fstacked_by_data\0\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x01\x04foil\0\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\x01\rhand_equipped\x01\x08\x10enchantable_slot\x0Bmelee_spear\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x03\x11creative_category\x06\x01\x0Eliquid_clipped\0\x01\x17can_destroy_in_creative\x01\0\n\x19minecraft:piercing_weapon\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x16minecraft:golden_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x14minecraft:gold_ingot\0\0\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\xAA\0\x05\tmin_speed33\xA3@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\x11damage_multiplier333?\x02\x05delay\x0E\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0PA\x02\x0Cmax_durationF\0\0\x05\rhitbox_margin\0\0\x80>\x05\x0Fdamage_modifier\0\0\0\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\x13\x01\x05\x12min_relative_speed33\x93@\0\0\0\n\x10minecraft:damage\x02\x05value\x01\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\0\t\titem_tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\n\x15minecraft:enchantable\x01\x05value\x16\x08\x04slot\x0Bmelee_spear\0\0\0" } ;
pub const GOLDEN_SWORD: Self = Self {
id: 325,
registry_key: "minecraft:golden_sword",
@ -90145,7 +90145,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const GRAY_BUNDLE : Self = Self { id : 862 , registry_key : "minecraft:gray_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x03\x11creative_category\x06\x01\x17can_destroy_in_creative\x01\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\0\x03\x0Emax_stack_size\x02\x08\x10enchantable_slot\x04none\x01\x04foil\0\x01\rhand_equipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bbundle_gray\x08\x10bundle_open_back\x15bundle_gray_open_back\x08\x11bundle_open_front\x16bundle_gray_open_front\0\0\x01\x0Eshould_despawn\x01\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x01\x0Eallow_off_hand\0\x03\ruse_animation\0\x03\x06damage\0\x03\x0Cuse_duration\0\x01\x0Eliquid_clipped\0\x01\x0Fstacked_by_data\0\x08\x0Ecreative_group\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\t\rallowed_items\0\0\0\0\0" } ;
pub const GRAY_BUNDLE : Self = Self { id : 862 , registry_key : "minecraft:gray_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x16bundle_gray_open_front\x08\x10bundle_open_back\x15bundle_gray_open_back\x08\x07default\x0Bbundle_gray\0\0\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x08\x10enchantable_slot\x04none\x01\rhand_equipped\0\x08\x0Ecreative_group\0\x03\x06damage\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\0\t\titem_tags\0\0\0\0" } ;
pub const GRAY_CANDLE: Self = Self {
id: -420,
registry_key: "minecraft:gray_candle",
@ -90244,7 +90244,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const GREEN_BUNDLE : Self = Self { id : 863 , registry_key : "minecraft:green_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x03\ruse_animation\0\x03\x0Cuse_duration\0\x08\x0Ecreative_group\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x17bundle_green_open_front\x08\x07default\x0Cbundle_green\x08\x10bundle_open_back\x16bundle_green_open_back\0\0\x01\x0Eshould_despawn\x01\x01\x04foil\0\x01\x12hidden_in_commands\x02\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\x03\x11enchantable_value\0\x01\rhand_equipped\0\x03\x06damage\0\0\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const GREEN_BUNDLE : Self = Self { id : 863 , registry_key : "minecraft:green_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Cbundle_green\x08\x10bundle_open_back\x16bundle_green_open_back\x08\x11bundle_open_front\x17bundle_green_open_front\0\0\x08\x0Ecreative_group\0\x01\x0Eallow_off_hand\0\x05\x0Cmining_speed\0\0\x80?\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\x03\ruse_animation\0\x01\x0Eshould_despawn\x01\x03\x06damage\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x03\x11creative_category\x06\x01\x04foil\0\x01\rhand_equipped\0\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\0\0\0" } ;
pub const GREEN_CANDLE: Self = Self {
id: -426,
registry_key: "minecraft:green_candle",
@ -90707,7 +90707,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const HONEY_BOTTLE : Self = Self { id : 604 , registry_key : "minecraft:honey_bottle" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x18minecraft:max_stack_size \n\x0Eminecraft:food\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\rcooldown_time\0\x03\tnutrition\x0C\x03\ron_use_action\x01\x08\rcooldown_type\0\t\x0Eremove_effects\x03\x02&\x08\x11using_converts_to\x0Cglass_bottle\x01\x0Ecan_always_eat\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\x03\x16minecraft:use_durationP\0\0" } ;
pub const HONEY_BOTTLE : Self = Self { id : 604 , registry_key : "minecraft:honey_bottle" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\ron_use_action\x01\x03\rcooldown_time\0\x08\x11using_converts_to\x0Cglass_bottle\t\x0Eremove_effects\x03\x02&\x08\rcooldown_type\0\x03\tnutrition\x0C\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\x01\x05\x13saturation_modifier\xCD\xCC\xCC=\0\x03\x18minecraft:max_stack_size \x03\x16minecraft:use_durationP\0\0" } ;
pub const HONEYCOMB: Self = Self {
id: 603,
registry_key: "minecraft:honeycomb",
@ -91009,7 +91009,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const IRON_SPEAR : Self = Self { id : 853 , registry_key : "minecraft:iron_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x14minecraft:durability\x03\x0Emax_durability\xF4\x03\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x08\x0Bstart_sound\x13item.iron_spear.use\x08\x0Bstart_using\x06always\x05\x0Cuse_duration\0\xA0\x8CG\x05\x11movement_modifier\0\0\x80?\0\n\x18minecraft:swing_duration\x05\x05value33s?\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x02\x05delay\x0C\0\n\x13dismount_conditions\x05\tmin_speed\0\x000A\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration2\0\0\x05\rhitbox_margin\0\0\x80>\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\x87\0\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\x0Fdamage_modifier\0\0\0\0\x05\x11damage_multiplier33s?\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x11damage_conditions\x02\x0Cmax_duration\xE1\0\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\0\0\0\n\x0Fitem_properties\n\x0Eminecraft:icon\n\x08textures\x08\x07default\niron_spear\0\0\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x06damage\x06\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x0Bmelee_spear\x03\x11creative_category\x06\x01\rhand_equipped\x01\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x03\x11enchantable_value\x1C\x01\x04foil\0\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x01\x0Fstacked_by_data\0\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x14minecraft:iron_spear\0\0\t\x05items\n\x02\x08\x04name\x14minecraft:iron_ingot\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\n\x15minecraft:enchantable\x01\x05value\x0E\x08\x04slot\x0Bmelee_spear\0\n\x19minecraft:piercing_weapon\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Aitem.iron_spear.attack_hit\x08\x0Battack_miss\x1Bitem.iron_spear.attack_miss\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x05\x08duration33s?\x08\x08category\x05spear\0\n\x16minecraft:display_name\x08\x05value\x14item.iron_spear.name\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x10minecraft:damage\x02\x05value\x03\0\0\t\titem_tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\0\0" } ;
pub const IRON_SPEAR : Self = Self { id : 853 , registry_key : "minecraft:iron_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x19minecraft:piercing_weapon\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\0\n\x0Fitem_properties\x01\rhand_equipped\x01\x03\x11creative_category\x06\x08\x0Ecreative_group\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x11enchantable_value\x1C\x01\x12hidden_in_commands\x02\x03\ruse_animation\0\x01\x0Eallow_off_hand\0\x05\x0Cmining_speed\0\0\x80?\x03\x0Emax_stack_size\x02\x01\x04foil\0\x03\x0Bframe_count\x02\x01\x17can_destroy_in_creative\x01\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x0Bmelee_spear\x01\x0Fstacked_by_data\0\x01\x0Eshould_despawn\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\niron_spear\0\0\x03\x06damage\x06\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x10minecraft:damage\x02\x05value\x03\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\t\titem_tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\x0Fdamage_modifier\0\0\0\0\x05\x11damage_multiplier33s?\x02\x05delay\x0C\0\n\x11damage_conditions\x02\x0Cmax_duration\xE1\0\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\x87\0\x05\tmin_speed33\xA3@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\x000A\x02\x0Cmax_duration2\0\0\x05\rhitbox_margin\0\0\x80>\0\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x08\x0Bstart_using\x06always\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x13item.iron_spear.use\0\n\x15minecraft:enchantable\x01\x05value\x0E\x08\x04slot\x0Bmelee_spear\0\n\x16minecraft:display_name\x08\x05value\x14item.iron_spear.name\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Bitem.iron_spear.attack_miss\x08\nattack_hit\x1Aitem.iron_spear.attack_hit\0\n\x18minecraft:swing_duration\x05\x05value33s?\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xF4\x03\0\n\x12minecraft:cooldown\x05\x08duration33s?\x08\x08category\x05spear\x08\x04type\x06attack\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x14minecraft:iron_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\t\x05items\n\x02\x08\x04name\x14minecraft:iron_ingot\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\0\0" } ;
pub const IRON_SWORD: Self = Self {
id: 309,
registry_key: "minecraft:iron_sword",
@ -91591,7 +91591,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const LIGHT_BLUE_BUNDLE : Self = Self { id : 864 , registry_key : "minecraft:light_blue_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x03\x11enchantable_value\0\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\x01\x12hidden_in_commands\x02\x03\x06damage\0\x08\x0Ecreative_group\0\x01\x04foil\0\x01\x0Eshould_despawn\x01\x01\rhand_equipped\0\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x11bundle_light_blue\x08\x10bundle_open_back\x1Bbundle_light_blue_open_back\x08\x11bundle_open_front\x1Cbundle_light_blue_open_front\0\0\x03\ruse_animation\0\x03\x11creative_category\x06\x03\x0Emax_stack_size\x02\x08\x10enchantable_slot\x04none\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const LIGHT_BLUE_BUNDLE : Self = Self { id : 864 , registry_key : "minecraft:light_blue_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x16minecraft:storage_item\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\0\n\x0Fitem_properties\x03\ruse_animation\0\x03\x0Cuse_duration\0\x03\x0Bframe_count\x02\x03\x06damage\0\x03\x11creative_category\x06\x03\x11enchantable_value\0\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x17can_destroy_in_creative\x01\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x02\x01\x0Fstacked_by_data\0\x01\x04foil\0\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x1Bbundle_light_blue_open_back\x08\x07default\x11bundle_light_blue\x08\x11bundle_open_front\x1Cbundle_light_blue_open_front\0\0\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\t\titem_tags\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const LIGHT_BLUE_CANDLE: Self = Self {
id: -416,
registry_key: "minecraft:light_blue_candle",
@ -91690,7 +91690,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const LIGHT_GRAY_BUNDLE : Self = Self { id : 865 , registry_key : "minecraft:light_gray_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x03\x06damage\0\x03\ruse_animation\0\x01\x0Eshould_despawn\x01\x03\x0Emax_stack_size\x02\x03\x11creative_category\x06\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x1Bbundle_light_gray_open_back\x08\x07default\x11bundle_light_gray\x08\x11bundle_open_front\x1Cbundle_light_gray_open_front\0\0\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x04none\x05\x0Cmining_speed\0\0\x80?\x03\x0Bframe_count\x02\x03\x11enchantable_value\0\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\x08\x0Ecreative_group\0\x01\x04foil\0\x01\rhand_equipped\0\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x01\x17can_destroy_in_creative\x01\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\0\t\titem_tags\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const LIGHT_GRAY_BUNDLE : Self = Self { id : 865 , registry_key : "minecraft:light_gray_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x01\rhand_equipped\0\x03\x0Emax_stack_size\x02\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x1Bbundle_light_gray_open_back\x08\x11bundle_open_front\x1Cbundle_light_gray_open_front\x08\x07default\x11bundle_light_gray\0\0\x08\x0Ecreative_group\0\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\x03\ruse_animation\0\x03\x0Cuse_duration\0\x01\x0Fstacked_by_data\0\x01\x0Eshould_despawn\x01\x01\x04foil\0\x03\x06damage\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\t\titem_tags\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\0\0" } ;
pub const LIGHT_GRAY_CANDLE: Self = Self {
id: -421,
registry_key: "minecraft:light_gray_candle",
@ -91810,7 +91810,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const LIME_BUNDLE : Self = Self { id : 866 , registry_key : "minecraft:lime_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x01\x0Eallow_off_hand\0\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\x01\x0Eliquid_clipped\0\x03\ruse_animation\0\x08\x0Ecreative_group\0\x01\x17can_destroy_in_creative\x01\x01\x04foil\0\x01\x12hidden_in_commands\x02\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x15bundle_lime_open_back\x08\x11bundle_open_front\x16bundle_lime_open_front\x08\x07default\x0Bbundle_lime\0\0\x01\x0Fstacked_by_data\0\x03\x11creative_category\x06\x03\x06damage\0\x03\x0Cuse_duration\0\x01\rhand_equipped\0\x03\x11enchantable_value\0\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x16minecraft:storage_item\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\0\0" } ;
pub const LIME_BUNDLE : Self = Self { id : 866 , registry_key : "minecraft:lime_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x16minecraft:storage_item\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\0\n\x0Fitem_properties\x01\x04foil\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x15bundle_lime_open_back\x08\x11bundle_open_front\x16bundle_lime_open_front\x08\x07default\x0Bbundle_lime\0\0\x01\rhand_equipped\0\x03\ruse_animation\0\x08\x0Ecreative_group\0\x01\x0Eliquid_clipped\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x03\x06damage\0\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x01\x0Fstacked_by_data\0\x08\x10enchantable_slot\x04none\x03\x11enchantable_value\0\x03\x0Cuse_duration\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const LIME_CANDLE: Self = Self {
id: -418,
registry_key: "minecraft:lime_candle",
@ -92014,7 +92014,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const MAGENTA_BUNDLE : Self = Self { id : 867 , registry_key : "minecraft:magenta_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x0Fitem_properties\x01\x0Eliquid_clipped\0\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x04none\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x18bundle_magenta_open_back\x08\x07default\x0Ebundle_magenta\x08\x11bundle_open_front\x19bundle_magenta_open_front\0\0\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x03\ruse_animation\0\x01\x04foil\0\x03\x0Emax_stack_size\x02\x03\x0Cuse_duration\0\x01\rhand_equipped\0\x08\x0Ecreative_group\0\x03\x06damage\0\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\0\0\0" } ;
pub const MAGENTA_BUNDLE : Self = Self { id : 867 , registry_key : "minecraft:magenta_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x16minecraft:storage_item\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\t\titem_tags\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x03\ruse_animation\0\x05\x0Cmining_speed\0\0\x80?\x08\x0Ecreative_group\0\x03\x0Bframe_count\x02\x01\x0Eshould_despawn\x01\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x04none\x03\x11enchantable_value\0\x01\x0Fstacked_by_data\0\x01\x0Eallow_off_hand\0\x03\x11creative_category\x06\x03\x0Cuse_duration\0\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x19bundle_magenta_open_front\x08\x07default\x0Ebundle_magenta\x08\x10bundle_open_back\x18bundle_magenta_open_back\0\0\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x02\x01\rhand_equipped\0\x01\x04foil\0\x03\x06damage\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const MAGENTA_CANDLE: Self = Self {
id: -415,
registry_key: "minecraft:magenta_candle",
@ -92316,8 +92316,8 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const MELON_SEEDS : Self = Self { id : 293 , registry_key : "minecraft:melon_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\x0Bcrop_result\x14minecraft:melon_stem\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\0\0\0" } ;
pub const MELON_SLICE : Self = Self { id : 272 , registry_key : "minecraft:melon_slice" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x04\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x99>\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const MELON_SEEDS : Self = Self { id : 293 , registry_key : "minecraft:melon_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\x0Bcrop_result\x14minecraft:melon_stem\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\0\0\0" } ;
pub const MELON_SLICE : Self = Self { id : 272 , registry_key : "minecraft:melon_slice" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\rcooldown_time\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x03\tnutrition\x04\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x99>\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const MELON_STEM: Self = Self {
id: 105,
registry_key: "minecraft:melon_stem",
@ -92535,7 +92535,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const MUSHROOM_STEW : Self = Self { id : 260 , registry_key : "minecraft:mushroom_stew" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\x04bowl\x05\x13saturation_modifier\x9A\x99\x19?\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x03\tnutrition\x0C\x03\ron_use_action\x01\0\x03\x16minecraft:use_duration@\x03\x18minecraft:max_stack_size\x02\0\0" } ;
pub const MUSHROOM_STEW : Self = Self { id : 260 , registry_key : "minecraft:mushroom_stew" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\tnutrition\x0C\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\x04bowl\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x03\rcooldown_time\0\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\x03\x18minecraft:max_stack_size\x02\0\0" } ;
pub const MUSIC_DISC_11: Self = Self {
id: 554,
registry_key: "minecraft:music_disc_11",
@ -92690,7 +92690,7 @@ impl BedrockItem {
component_based: true,
definition_components: b"\n\0\0",
};
pub const MUTTON : Self = Self { id : 560 , registry_key : "minecraft:mutton" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x99>\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\rcooldown_time\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x03\tnutrition\x04\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const MUTTON : Self = Self { id : 560 , registry_key : "minecraft:mutton" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\tnutrition\x04\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const MYCELIUM: Self = Self {
id: 110,
registry_key: "minecraft:mycelium",
@ -92782,7 +92782,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const NETHER_WART : Self = Self { id : 294 , registry_key : "minecraft:nether_wart" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x15minecraft:nether_wart\t\x08plant_at\x08\x02\tsoul_sand\x08\rplant_at_face\x02up\0\0\0" } ;
pub const NETHER_WART : Self = Self { id : 294 , registry_key : "minecraft:nether_wart" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\t\x08plant_at\x08\x02\tsoul_sand\x08\x0Bcrop_result\x15minecraft:nether_wart\0\0\0" } ;
pub const NETHER_WART_BLOCK: Self = Self {
id: 214,
registry_key: "minecraft:nether_wart_block",
@ -92888,7 +92888,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const NETHERITE_SPEAR : Self = Self { id : 854 , registry_key : "minecraft:netherite_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x14minecraft:durability\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\x03\x0Emax_durability\xDC\x1F\0\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x01\rhand_equipped\x01\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Fnetherite_spear\0\0\x01\x04foil\0\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x0Bmelee_spear\x03\x06damage\n\x01\x0Eallow_off_hand\0\x03\x11enchantable_value\x1E\x05\x0Cmining_speed\0\0\x80?\x03\ruse_animation\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x0Emax_stack_size\x02\x01\x0Fstacked_by_data\0\x08\x0Ecreative_group\0\0\t\titem_tags\x08\x04\x18minecraft:netherite_tier\x12minecraft:is_spear\n\x18minecraft:swing_duration\x05\x05value33\x93?\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_durationn\0\0\x05\x0Fdamage_modifier\0\0\0\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration2\0\x05\tmin_speed\0\0\x10A\0\n\x11damage_conditions\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\xAF\0\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x02\x05delay\x08\0\x05\rhitbox_margin\0\0\x80>\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\x11damage_multiplier\x9A\x99\x99?\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x10minecraft:damage\x02\x05value\x05\0\0\n\x17minecraft:use_modifiers\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x18item.netherite_spear.use\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\0\0\n\x18minecraft:fire_resistant\x01\x05value\x01\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x15minecraft:enchantable\x01\x05value\x0F\x08\x04slot\x0Bmelee_spear\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x19minecraft:netherite_spear\0\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x19minecraft:netherite_ingot\0\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x18minecraft:netherite_tier\x12minecraft:is_spear\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\n\x12minecraft:cooldown\x05\x08duration33\x93?\x08\x08category\x05spear\x08\x04type\x06attack\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Fitem.netherite_spear.attack_hit\x08\x0Battack_miss item.netherite_spear.attack_miss\0\n\x16minecraft:display_name\x08\x05value\x19item.netherite_spear.name\0\0\0" } ;
pub const NETHERITE_SPEAR : Self = Self { id : 854 , registry_key : "minecraft:netherite_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x03\x06damage\n\x03\ruse_animation\0\x08\x10enchantable_slot\x0Bmelee_spear\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x04foil\0\x01\x12hidden_in_commands\x02\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x03\x11creative_category\x06\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\x1E\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Fnetherite_spear\0\0\x01\rhand_equipped\x01\x01\x0Fstacked_by_data\0\x01\x0Eliquid_clipped\0\0\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\x0F\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x18minecraft:swing_duration\x05\x05value33\x93?\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0\x10A\x02\x0Cmax_duration2\0\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x02\x05delay\x08\0\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\x02\x0Cmax_duration\xAF\0\0\x05\x0Fdamage_modifier\0\0\0\0\x05\x11damage_multiplier\x9A\x99\x99?\n\x14knockback_conditions\x02\x0Cmax_durationn\0\x05\tmin_speed33\xA3@\x05\x12min_relative_speed\0\0\0\0\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x18minecraft:netherite_tier\x12minecraft:is_spear\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x10minecraft:damage\x02\x05value\x05\0\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x08\x0Bstart_using\x06always\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_sound\x18item.netherite_spear.use\x05\x0Cuse_duration\0\xA0\x8CG\0\n\x16minecraft:display_name\x08\x05value\x19item.netherite_spear.name\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\x03\x0Emax_durability\xDC\x1F\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x19minecraft:netherite_spear\0\0\t\x05items\n\x02\x08\x04name\x19minecraft:netherite_ingot\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\n\x19minecraft:piercing_weapon\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Fitem.netherite_spear.attack_hit\x08\x0Battack_miss item.netherite_spear.attack_miss\0\n\x18minecraft:fire_resistant\x01\x05value\x01\0\t\titem_tags\x08\x04\x18minecraft:netherite_tier\x12minecraft:is_spear\n\x12minecraft:cooldown\x08\x04type\x06attack\x08\x08category\x05spear\x05\x08duration33\x93?\0\0\0" } ;
pub const NETHERITE_SWORD: Self = Self {
id: 617,
registry_key: "minecraft:netherite_sword",
@ -93085,7 +93085,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const OMINOUS_TRIAL_KEY : Self = Self { id : 875 , registry_key : "minecraft:ominous_trial_key" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x01\x04foil\0\x03\x11enchantable_value\0\x08\x0Ecreative_group\0\x01\x0Eshould_despawn\x01\x01\rhand_equipped\0\x03\ruse_animation\0\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\x03\x11creative_category\x08\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x11ominous_trial_key\0\0\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x03\x0Emax_stack_size\x80\x01\x03\x06damage\0\x01\x17can_destroy_in_creative\x01\0\t\titem_tags\0\0\n\x16minecraft:display_name\x08\x05value\x1Bitem.ominous_trial_key.name\0\0\0" } ;
pub const OMINOUS_TRIAL_KEY : Self = Self { id : 875 , registry_key : "minecraft:ominous_trial_key" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x08\x0Ecreative_group\0\x01\x04foil\0\x01\x12hidden_in_commands\x02\x03\x0Cuse_duration\0\x03\ruse_animation\0\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\x03\x0Emax_stack_size\x80\x01\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x01\x17can_destroy_in_creative\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x11ominous_trial_key\0\0\x01\x0Eallow_off_hand\0\x01\x0Fstacked_by_data\0\x08\x10enchantable_slot\x04none\x01\rhand_equipped\0\x03\x11creative_category\x08\x03\x06damage\0\x03\x11enchantable_value\0\0\t\titem_tags\0\0\n\x16minecraft:display_name\x08\x05value\x1Bitem.ominous_trial_key.name\0\0\0" } ;
pub const OPEN_EYEBLOSSOM: Self = Self {
id: -1018,
registry_key: "minecraft:open_eyeblossom",
@ -93093,7 +93093,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const ORANGE_BUNDLE : Self = Self { id : 868 , registry_key : "minecraft:orange_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x08\x10enchantable_slot\x04none\x01\x04foil\0\x01\x0Eliquid_clipped\0\x01\rhand_equipped\0\x03\x0Cuse_duration\0\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x01\x0Eallow_off_hand\0\x03\x06damage\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x17bundle_orange_open_back\x08\x07default\rbundle_orange\x08\x11bundle_open_front\x18bundle_orange_open_front\0\0\x05\x0Cmining_speed\0\0\x80?\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\0\0" } ;
pub const ORANGE_BUNDLE : Self = Self { id : 868 , registry_key : "minecraft:orange_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x02\x03\x11enchantable_value\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x03\x0Bframe_count\x02\x01\x17can_destroy_in_creative\x01\x08\x0Ecreative_group\0\x03\x11creative_category\x06\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x03\x0Cuse_duration\0\x08\x10enchantable_slot\x04none\n\x0Eminecraft:icon\n\x08textures\x08\x07default\rbundle_orange\x08\x10bundle_open_back\x17bundle_orange_open_back\x08\x11bundle_open_front\x18bundle_orange_open_front\0\0\x01\x04foil\0\x01\x0Eallow_off_hand\0\x03\x06damage\0\x01\rhand_equipped\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\t\titem_tags\0\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\0\0\0" } ;
pub const ORANGE_CANDLE: Self = Self {
id: -414,
registry_key: "minecraft:orange_candle",
@ -93626,7 +93626,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const PINK_BUNDLE : Self = Self { id : 869 , registry_key : "minecraft:pink_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x08\x10enchantable_slot\x04none\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x01\x0Eallow_off_hand\0\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\x03\ruse_animation\0\x03\x0Cuse_duration\0\x03\x06damage\0\x01\x04foil\0\x01\x17can_destroy_in_creative\x01\x05\x0Cmining_speed\0\0\x80?\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bbundle_pink\x08\x10bundle_open_back\x15bundle_pink_open_back\x08\x11bundle_open_front\x16bundle_pink_open_front\0\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x16minecraft:storage_item\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const PINK_BUNDLE : Self = Self { id : 869 , registry_key : "minecraft:pink_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x0Fitem_properties\x03\x0Emax_stack_size\x02\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x03\x0Cuse_duration\0\x03\x06damage\0\x03\x11creative_category\x06\x03\x0Bframe_count\x02\x01\x0Eshould_despawn\x01\x08\x10enchantable_slot\x04none\x03\x11enchantable_value\0\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bbundle_pink\x08\x10bundle_open_back\x15bundle_pink_open_back\x08\x11bundle_open_front\x16bundle_pink_open_front\0\0\x01\x0Eallow_off_hand\0\x01\x04foil\0\x01\x12hidden_in_commands\x02\x05\x0Cmining_speed\0\0\x80?\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\0\0" } ;
pub const PINK_CANDLE: Self = Self {
id: -419,
registry_key: "minecraft:pink_candle",
@ -93767,7 +93767,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const PITCHER_POD : Self = Self { id : 297 , registry_key : "minecraft:pitcher_pod" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x16minecraft:pitcher_crop\x01\x1Aplant_at_any_solid_surface\0\0\0\0" } ;
pub const PITCHER_POD : Self = Self { id : 297 , registry_key : "minecraft:pitcher_pod" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\x0Bcrop_result\x16minecraft:pitcher_crop\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\0\0\0" } ;
pub const PLANKS: Self = Self {
id: 814,
registry_key: "minecraft:planks",
@ -93803,7 +93803,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const POISONOUS_POTATO : Self = Self { id : 282 , registry_key : "minecraft:poisonous_potato" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\t\x07effects\n\x02\x03\x02id&\x08\x04name\x06poison\x08\rdescriptionId\rpotion.poison\x03\tamplifier\0\x03\x08duration\n\x05\x06chance\x9A\x99\x19?\0\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99>\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x04\x03\ron_use_action\x01\x08\x11using_converts_to\0\x03\rcooldown_time\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const POISONOUS_POTATO : Self = Self { id : 282 , registry_key : "minecraft:poisonous_potato" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\t\x07effects\n\x02\x03\tamplifier\0\x05\x06chance\x9A\x99\x19?\x03\x08duration\n\x03\x02id&\x08\rdescriptionId\rpotion.poison\x08\x04name\x06poison\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\rcooldown_time\0\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x04\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const POLAR_BEAR_SPAWN_EGG: Self = Self {
id: 477,
registry_key: "minecraft:polar_bear_spawn_egg",
@ -94280,7 +94280,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const PORKCHOP : Self = Self { id : 262 , registry_key : "minecraft:porkchop" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x08\rcooldown_type\0\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\tnutrition\x06\0\0\0" } ;
pub const PORKCHOP : Self = Self { id : 262 , registry_key : "minecraft:porkchop" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99>\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\ron_use_action\x01\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x06\0\0\0" } ;
pub const PORTAL: Self = Self {
id: 90,
registry_key: "minecraft:portal",
@ -94288,7 +94288,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const POTATO : Self = Self { id : 280 , registry_key : "minecraft:potato" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x12minecraft:potatoes\x01\x1Aplant_at_any_solid_surface\0\0\n\x0Eminecraft:food\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\tnutrition\x02\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const POTATO : Self = Self { id : 280 , registry_key : "minecraft:potato" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\rcooldown_time\0\x03\tnutrition\x02\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\0\n\x0Eminecraft:seed\x08\x0Bcrop_result\x12minecraft:potatoes\x01\x1Aplant_at_any_solid_surface\0\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const POTATOES: Self = Self {
id: 142,
registry_key: "minecraft:potatoes",
@ -94422,7 +94422,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const PUFFERFISH : Self = Self { id : 267 , registry_key : "minecraft:pufferfish" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\rcooldown_time\0\x03\ron_use_action\x01\t\x07effects\n\x06\x03\x08durationx\x03\tamplifier\x02\x08\x04name\x06poison\x05\x06chance\0\0\x80?\x08\rdescriptionId\rpotion.poison\x03\x02id&\0\x08\rdescriptionId\x10potion.confusion\x03\x02id\x12\x05\x06chance\0\0\x80?\x03\x08duration\x1E\x08\x04name\x06nausea\x03\tamplifier\0\0\x05\x06chance\0\0\x80?\x08\rdescriptionId\rpotion.hunger\x08\x04name\x06hunger\x03\tamplifier\x04\x03\x02id\"\x03\x08duration\x1E\0\x03\tnutrition\x02\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCC\xCC=\x08\x11using_converts_to\0\0\0\0" } ;
pub const PUFFERFISH : Self = Self { id : 267 , registry_key : "minecraft:pufferfish" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\ron_use_action\x01\x05\x13saturation_modifier\xCD\xCC\xCC=\x08\x11using_converts_to\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\t\x07effects\n\x06\x03\x02id&\x03\tamplifier\x02\x08\x04name\x06poison\x05\x06chance\0\0\x80?\x08\rdescriptionId\rpotion.poison\x03\x08durationx\0\x08\x04name\x06nausea\x03\tamplifier\0\x05\x06chance\0\0\x80?\x08\rdescriptionId\x10potion.confusion\x03\x08duration\x1E\x03\x02id\x12\0\x03\tamplifier\x04\x08\rdescriptionId\rpotion.hunger\x08\x04name\x06hunger\x05\x06chance\0\0\x80?\x03\x08duration\x1E\x03\x02id\"\0\x03\tnutrition\x02\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\x01\x19minecraft:stacked_by_data\x01\0\0" } ;
pub const PUFFERFISH_BUCKET: Self = Self {
id: 370,
registry_key: "minecraft:pufferfish_bucket",
@ -94444,8 +94444,8 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const PUMPKIN_PIE : Self = Self { id : 284 , registry_key : "minecraft:pumpkin_pie" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x99>\x03\tnutrition\x10\x08\x11using_converts_to\0\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const PUMPKIN_SEEDS : Self = Self { id : 292 , registry_key : "minecraft:pumpkin_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\x0Bcrop_result\x16minecraft:pumpkin_stem\x01\x1Aplant_at_any_solid_surface\0\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\0\0\0" } ;
pub const PUMPKIN_PIE : Self = Self { id : 284 , registry_key : "minecraft:pumpkin_pie" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x03\rcooldown_time\0\x03\tnutrition\x10\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const PUMPKIN_SEEDS : Self = Self { id : 292 , registry_key : "minecraft:pumpkin_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x16minecraft:pumpkin_stem\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\0\0\0" } ;
pub const PUMPKIN_STEM: Self = Self {
id: 104,
registry_key: "minecraft:pumpkin_stem",
@ -94453,7 +94453,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const PURPLE_BUNDLE : Self = Self { id : 870 , registry_key : "minecraft:purple_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\t\titem_tags\0\0\n\x0Fitem_properties\x01\rhand_equipped\0\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\x04foil\0\x01\x0Eallow_off_hand\0\x03\x11enchantable_value\0\x01\x0Eshould_despawn\x01\x03\x0Cuse_duration\0\x01\x0Eliquid_clipped\0\x01\x17can_destroy_in_creative\x01\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x18bundle_purple_open_front\x08\x07default\rbundle_purple\x08\x10bundle_open_back\x17bundle_purple_open_back\0\0\x05\x0Cmining_speed\0\0\x80?\x03\x06damage\0\x08\x10enchantable_slot\x04none\x03\x0Bframe_count\x02\x08\x0Ecreative_group\0\x03\x11creative_category\x06\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x16minecraft:storage_item\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\0\0\0" } ;
pub const PURPLE_BUNDLE : Self = Self { id : 870 , registry_key : "minecraft:purple_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x03\x11enchantable_value\0\x03\x0Bframe_count\x02\x03\ruse_animation\0\x08\x0Ecreative_group\0\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x03\x06damage\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x18bundle_purple_open_front\x08\x07default\rbundle_purple\x08\x10bundle_open_back\x17bundle_purple_open_back\0\0\x01\x0Eshould_despawn\x01\x01\x12hidden_in_commands\x02\x01\rhand_equipped\0\x01\x04foil\0\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\0\0" } ;
pub const PURPLE_CANDLE: Self = Self {
id: -423,
registry_key: "minecraft:purple_candle",
@ -94643,7 +94643,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const RABBIT : Self = Self { id : 288 , registry_key : "minecraft:rabbit" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\0\x03\rcooldown_time\0\x03\tnutrition\x06\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x99>\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const RABBIT : Self = Self { id : 288 , registry_key : "minecraft:rabbit" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x06\x03\rcooldown_time\0\0\0\0" } ;
pub const RABBIT_FOOT: Self = Self {
id: 538,
registry_key: "minecraft:rabbit_foot",
@ -94665,7 +94665,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const RABBIT_STEW : Self = Self { id : 290 , registry_key : "minecraft:rabbit_stew" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\x04bowl\x03\rcooldown_time\0\x08\rcooldown_type\0\x03\tnutrition\x14\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\x03\x18minecraft:max_stack_size\x02\0\0" } ;
pub const RABBIT_STEW : Self = Self { id : 290 , registry_key : "minecraft:rabbit_stew" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x08\rcooldown_type\0\x08\x11using_converts_to\x04bowl\x03\tnutrition\x14\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x19?\0\x03\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\0\0" } ;
pub const RAIL: Self = Self {
id: 66,
registry_key: "minecraft:rail",
@ -94743,7 +94743,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const RED_BUNDLE : Self = Self { id : 871 , registry_key : "minecraft:red_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x16minecraft:storage_item\t\rallowed_items\0\0\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x0Fitem_properties\x01\x0Eallow_off_hand\0\x03\x06damage\0\x08\x10enchantable_slot\x04none\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x01\x04foil\0\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x01\rhand_equipped\0\x03\ruse_animation\0\x03\x0Cuse_duration\0\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\0\x01\x0Fstacked_by_data\0\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x15bundle_red_open_front\x08\x07default\nbundle_red\x08\x10bundle_open_back\x14bundle_red_open_back\0\0\x08\x0Ecreative_group\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const RED_BUNDLE : Self = Self { id : 871 , registry_key : "minecraft:red_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x0Fitem_properties\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x02\x01\x0Fstacked_by_data\0\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\0\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x04none\x03\ruse_animation\0\x03\x06damage\0\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nbundle_red\x08\x10bundle_open_back\x14bundle_red_open_back\x08\x11bundle_open_front\x15bundle_red_open_front\0\0\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x01\x04foil\0\x03\x11creative_category\x06\x01\rhand_equipped\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\0\0" } ;
pub const RED_CANDLE: Self = Self {
id: -427,
registry_key: "minecraft:red_candle",
@ -95101,7 +95101,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const ROTTEN_FLESH : Self = Self { id : 277 , registry_key : "minecraft:rotten_flesh" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\t\x07effects\n\x02\x03\tamplifier\0\x08\rdescriptionId\rpotion.hunger\x05\x06chance\xCD\xCCL?\x03\x08duration<\x03\x02id\"\x08\x04name\x06hunger\0\x08\x11using_converts_to\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x03\tnutrition\x08\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\rcooldown_time\0\x08\rcooldown_type\0\0\0\0" } ;
pub const ROTTEN_FLESH : Self = Self { id : 277 , registry_key : "minecraft:rotten_flesh" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\t\x07effects\n\x02\x03\x02id\"\x08\rdescriptionId\rpotion.hunger\x05\x06chance\xCD\xCCL?\x03\tamplifier\0\x03\x08duration<\x08\x04name\x06hunger\0\x03\ron_use_action\x01\x03\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCC\xCC=\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\tnutrition\x08\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const SADDLE: Self = Self {
id: 374,
registry_key: "minecraft:saddle",
@ -95109,7 +95109,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const SALMON : Self = Self { id : 265 , registry_key : "minecraft:salmon" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\xCD\xCC\xCC=\x01\x0Ecan_always_eat\0\x03\tnutrition\x04\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\ron_use_action\x01\x08\rcooldown_type\0\0\x01\x19minecraft:stacked_by_data\x01\0\0" } ;
pub const SALMON : Self = Self { id : 265 , registry_key : "minecraft:salmon" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\tnutrition\x04\x03\ron_use_action\x01\0\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\0\0" } ;
pub const SALMON_BUCKET: Self = Self {
id: 368,
registry_key: "minecraft:salmon_bucket",
@ -95670,7 +95670,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const SPIDER_EYE : Self = Self { id : 278 , registry_key : "minecraft:spider_eye" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\rcooldown_time\0\t\x07effects\n\x02\x03\tamplifier\0\x08\rdescriptionId\rpotion.poison\x08\x04name\x06poison\x05\x06chance\0\0\x80?\x03\x08duration\n\x03\x02id&\0\x03\tnutrition\x04\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCCL?\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const SPIDER_EYE : Self = Self { id : 278 , registry_key : "minecraft:spider_eye" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\x03\tnutrition\x04\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x05\x13saturation_modifier\xCD\xCCL?\x03\rcooldown_time\0\t\x07effects\n\x02\x08\rdescriptionId\rpotion.poison\x05\x06chance\0\0\x80?\x03\x08duration\n\x03\x02id&\x03\tamplifier\0\x08\x04name\x06poison\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const SPIDER_SPAWN_EGG: Self = Self {
id: 450,
registry_key: "minecraft:spider_spawn_egg",
@ -96035,7 +96035,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const STONE_SPEAR : Self = Self { id : 855 , registry_key : "minecraft:stone_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x0Fitem_properties\x03\x0Cuse_duration\x80\xE4\xAF\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bstone_spear\0\0\x03\x11creative_category\x06\x08\x10enchantable_slot\x0Bmelee_spear\x08\x0Ecreative_group\0\x03\x11enchantable_value\n\x03\x06damage\x04\x03\x0Bframe_count\x02\x03\x0Emax_stack_size\x02\x01\rhand_equipped\x01\x01\x12hidden_in_commands\x02\x01\x0Fstacked_by_data\0\x01\x17can_destroy_in_creative\x01\x03\ruse_animation\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\x01\x04foil\0\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\0\n\x16minecraft:display_name\x08\x05value\x15item.stone_spear.name\0\n\x19minecraft:piercing_weapon\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\0\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\x05\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x18minecraft:swing_duration\x05\x05value\0\0@?\0\t\titem_tags\x08\x04\x14minecraft:stone_tier\x12minecraft:is_spear\n\x0Eminecraft:tags\t\x04tags\x08\x04\x14minecraft:stone_tier\x12minecraft:is_spear\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x15minecraft:stone_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04tags,q.all_tags('minecraft:stone_tool_materials')\0\0\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x08\x08category\x05spear\x05\x08duration\0\0@?\0\n\x17minecraft:use_modifiers\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_using\x06always\x08\x0Bstart_sound\x14item.stone_spear.use\x01\x0Femit_vibrations\0\x05\x11movement_modifier\0\0\x80?\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\x02\x0Cmax_duration\x13\x01\0\x05\x11damage_multiplier\x85\xEBQ?\n\x14knockback_conditions\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\xB4\0\x05\x12min_relative_speed\0\0\0\0\0\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\x0Fdamage_modifier\0\0\0\0\n\x13dismount_conditions\x02\x0Cmax_durationZ\0\x05\tmin_speed\0\0PA\x05\x12min_relative_speed\0\0\0\0\0\x02\x05delay\x0E\0\0\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\x03\x0Emax_durability\x84\x02\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Citem.stone_spear.attack_miss\x08\nattack_hit\x1Bitem.stone_spear.attack_hit\0\n\x10minecraft:damage\x02\x05value\x02\0\0\0\0" } ;
pub const STONE_SPEAR : Self = Self { id : 855 , registry_key : "minecraft:stone_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x10minecraft:damage\x02\x05value\x02\0\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Citem.stone_spear.attack_miss\x08\nattack_hit\x1Bitem.stone_spear.attack_hit\0\n\x14minecraft:durability\x03\x0Emax_durability\x84\x02\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x15minecraft:stone_spear\0\0\t\x05items\n\x02\x08\x04tags,q.all_tags('minecraft:stone_tool_materials')\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\n\x19minecraft:piercing_weapon\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\n\x12minecraft:cooldown\x05\x08duration\0\0@?\x08\x08category\x05spear\x08\x04type\x06attack\0\n\x18minecraft:swing_duration\x05\x05value\0\0@?\0\n\x17minecraft:use_modifiers\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_sound\x14item.stone_spear.use\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\0\0\t\titem_tags\x08\x04\x14minecraft:stone_tier\x12minecraft:is_spear\n\x15minecraft:enchantable\x01\x05value\x05\x08\x04slot\x0Bmelee_spear\0\n\x0Fitem_properties\x03\x0Emax_stack_size\x02\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bstone_spear\0\0\x08\x0Ecreative_group\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x11enchantable_value\n\x08\x10enchantable_slot\x0Bmelee_spear\x01\x04foil\0\x01\x17can_destroy_in_creative\x01\x03\x06damage\x04\x03\x0Bframe_count\x02\x01\x0Eshould_despawn\x01\x01\rhand_equipped\x01\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\0\n\x16minecraft:display_name\x08\x05value\x15item.stone_spear.name\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x02\x05delay\x0E\0\n\x13dismount_conditions\x05\tmin_speed\0\0PA\x02\x0Cmax_durationZ\0\x05\x12min_relative_speed\0\0\0\0\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\xB4\0\x05\tmin_speed33\xA3@\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\x05\rhitbox_margin\0\0\x80>\x05\x0Fdamage_modifier\0\0\0\0\x05\x11damage_multiplier\x85\xEBQ?\n\x11damage_conditions\x02\x0Cmax_duration\x13\x01\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x14minecraft:stone_tier\x12minecraft:is_spear\0\0\0" } ;
pub const STONE_STAIRS: Self = Self {
id: 67,
registry_key: "minecraft:stone_stairs",
@ -96414,8 +96414,8 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const SUSPICIOUS_STEW : Self = Self { id : 602 , registry_key : "minecraft:suspicious_stew" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x08\x11using_converts_to\x04bowl\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x02\x03\rcooldown_time\0\x01\x0Ecan_always_eat\x01\x05\x13saturation_modifier\x9A\x99\x19?\x08\rcooldown_type\0\x03\tnutrition\x0C\0\x03\x16minecraft:use_duration@\x03\x18minecraft:max_stack_size\x02\0\0" } ;
pub const SWEET_BERRIES : Self = Self { id : 287 , registry_key : "minecraft:sweet_berries" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x08\rplant_at_face\x02up\t\x08plant_at\x08\x14\x08farmland\x05grass\x04dirt\x0Bcoarse_dirt\x06podzol\nmoss_block\x08mycelium\x03mud\x14muddy_mangrove_roots\x0Fdirt_with_roots\x08\x0Bcrop_result\x1Aminecraft:sweet_berry_bush\x01\x1Aplant_at_any_solid_surface\0\0\n\x0Eminecraft:food\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x99>\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\x03\tnutrition\x04\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const SUSPICIOUS_STEW : Self = Self { id : 602 , registry_key : "minecraft:suspicious_stew" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x03\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x08\rcooldown_type\0\x01\x0Ecan_always_eat\x01\x03\rcooldown_time\0\x03\tnutrition\x0C\x03\ron_use_action\x02\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\x04bowl\0\0\0" } ;
pub const SWEET_BERRIES : Self = Self { id : 287 , registry_key : "minecraft:sweet_berries" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x03\tnutrition\x04\x03\ron_use_action\x01\x08\rcooldown_type\0\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\n\x0Eminecraft:seed\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x1Aminecraft:sweet_berry_bush\x01\x1Aplant_at_any_solid_surface\0\t\x08plant_at\x08\x14\x08farmland\x05grass\x04dirt\x0Bcoarse_dirt\x06podzol\nmoss_block\x08mycelium\x03mud\x14muddy_mangrove_roots\x0Fdirt_with_roots\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const SWEET_BERRY_BUSH: Self = Self {
id: -207,
registry_key: "minecraft:sweet_berry_bush",
@ -96514,7 +96514,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const TORCHFLOWER_SEEDS : Self = Self { id : 296 , registry_key : "minecraft:torchflower_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x1Aminecraft:torchflower_crop\0\0\0" } ;
pub const TORCHFLOWER_SEEDS : Self = Self { id : 296 , registry_key : "minecraft:torchflower_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x1Aminecraft:torchflower_crop\t\x08plant_at\x08\x02\x12minecraft:farmland\0\0\0" } ;
pub const TOTEM_OF_UNDYING: Self = Self {
id: 578,
registry_key: "minecraft:totem_of_undying",
@ -96543,7 +96543,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const TRIAL_KEY : Self = Self { id : 876 , registry_key : "minecraft:trial_key" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n\x16minecraft:display_name\x08\x05value\x13item.trial_key.name\0\n\x0Fitem_properties\x03\ruse_animation\0\x03\x06damage\0\x01\x0Eshould_despawn\x01\x03\x0Cuse_duration\0\x01\x04foil\0\x08\x10enchantable_slot\x04none\x01\x17can_destroy_in_creative\x01\x03\x0Emax_stack_size\x80\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ttrial_key\0\0\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\x03\x11creative_category\x08\x08\x0Ecreative_group\0\x01\x0Eallow_off_hand\0\x01\x0Fstacked_by_data\0\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\0\0\0" } ;
pub const TRIAL_KEY : Self = Self { id : 876 , registry_key : "minecraft:trial_key" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\t\titem_tags\0\0\n\x16minecraft:display_name\x08\x05value\x13item.trial_key.name\0\n\x0Fitem_properties\x03\x11enchantable_value\0\x03\x0Bframe_count\x02\x01\x0Eshould_despawn\x01\x03\x11creative_category\x08\x08\x10enchantable_slot\x04none\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ttrial_key\0\0\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\0\x03\x06damage\0\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x80\x01\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x01\x12hidden_in_commands\x02\x01\x0Eallow_off_hand\0\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x01\x04foil\0\x01\x0Fstacked_by_data\0\0\0\0" } ;
pub const TRIAL_SPAWNER: Self = Self {
id: -315,
registry_key: "minecraft:trial_spawner",
@ -96572,7 +96572,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const TROPICAL_FISH : Self = Self { id : 266 , registry_key : "minecraft:tropical_fish" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\tnutrition\x02\x08\x11using_converts_to\0\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\ron_use_action\x01\0\0\0" } ;
pub const TROPICAL_FISH : Self = Self { id : 266 , registry_key : "minecraft:tropical_fish" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x02\x08\x11using_converts_to\0\x03\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCC\xCC=\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\0\0" } ;
pub const TROPICAL_FISH_BUCKET: Self = Self {
id: 369,
registry_key: "minecraft:tropical_fish_bucket",
@ -97623,8 +97623,8 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const WHEAT_SEEDS : Self = Self { id : 291 , registry_key : "minecraft:wheat_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\x0Bcrop_result\x0Fminecraft:wheat\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\0\0\0" } ;
pub const WHITE_BUNDLE : Self = Self { id : 872 , registry_key : "minecraft:white_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x03\tmax_slots\x80\x01\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\0\t\titem_tags\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x03\x11enchantable_value\0\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x01\x17can_destroy_in_creative\x01\x03\ruse_animation\0\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x01\x0Eallow_off_hand\0\x03\x0Bframe_count\x02\x08\x0Ecreative_group\0\x01\rhand_equipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x03\x0Cuse_duration\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x16bundle_white_open_back\x08\x07default\x0Cbundle_white\x08\x11bundle_open_front\x17bundle_white_open_front\0\0\x03\x06damage\0\x01\x12hidden_in_commands\x02\x03\x11creative_category\x06\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\0\0" } ;
pub const WHEAT_SEEDS : Self = Self { id : 291 , registry_key : "minecraft:wheat_seeds" , version : BedrockItemVersion :: Legacy , component_based : false , definition_components : b"\n\0\n\ncomponents\n\x0Eminecraft:seed\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\x0Bcrop_result\x0Fminecraft:wheat\0\0\0" } ;
pub const WHITE_BUNDLE : Self = Self { id : 872 , registry_key : "minecraft:white_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x16minecraft:storage_item\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\t\rallowed_items\0\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x01\rhand_equipped\0\x01\x04foil\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Cbundle_white\x08\x11bundle_open_front\x17bundle_white_open_front\x08\x10bundle_open_back\x16bundle_white_open_back\0\0\x03\x0Cuse_duration\0\x01\x0Fstacked_by_data\0\x03\x11enchantable_value\0\x03\ruse_animation\0\x08\x0Ecreative_group\0\x08\x10enchantable_slot\x04none\x01\x0Eallow_off_hand\0\x03\x0Emax_stack_size\x02\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x03\x11creative_category\x06\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x01\x12hidden_in_commands\x02\x03\x06damage\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\t\titem_tags\0\0\0\0" } ;
pub const WHITE_CANDLE: Self = Self {
id: -413,
registry_key: "minecraft:white_candle",
@ -97744,7 +97744,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const WIND_CHARGE : Self = Self { id : 877 , registry_key : "minecraft:wind_charge" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x14minecraft:projectile\x05\x16minimum_critical_power\0\0\0\0\x08\x11projectile_entity\"minecraft:wind_charge_projectile<>\0\n\x0Fitem_properties\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x08\x10enchantable_slot\x04none\x03\x0Bframe_count\x02\x03\x06damage\0\x03\x11creative_category\x06\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bwind_charge\0\0\x03\x11enchantable_value\0\x01\x17can_destroy_in_creative\x01\x08\x0Ecreative_group\0\x01\x0Eallow_off_hand\0\x01\rhand_equipped\0\x01\x04foil\0\x05\x0Cmining_speed\0\0\x80?\x03\ruse_animation\0\x03\x0Cuse_duration\0\x03\x0Emax_stack_size\x80\x01\0\n\x13minecraft:throwable\x05\x10max_launch_power\0\0\xC0?\x01\x1Cscale_power_by_draw_duration\0\x05\x12launch_power_scale\0\0\xC0?\x05\x11max_draw_duration\0\0\0\0\x01\x12do_swing_animation\x01\x05\x11min_draw_duration\0\0\0\0\0\n\x12minecraft:cooldown\x05\x08duration\0\0\0?\x08\x08category\x0Bwind_charge\x08\x04type\x03use\0\t\titem_tags\0\0\n\x16minecraft:display_name\x08\x05value\x15item.wind_charge.name\0\0\0" } ;
pub const WIND_CHARGE : Self = Self { id : 877 , registry_key : "minecraft:wind_charge" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x14minecraft:projectile\x08\x11projectile_entity\"minecraft:wind_charge_projectile<>\x05\x16minimum_critical_power\0\0\0\0\0\n\x16minecraft:display_name\x08\x05value\x15item.wind_charge.name\0\n\x13minecraft:throwable\x05\x11min_draw_duration\0\0\0\0\x01\x1Cscale_power_by_draw_duration\0\x05\x10max_launch_power\0\0\xC0?\x01\x12do_swing_animation\x01\x05\x11max_draw_duration\0\0\0\0\x05\x12launch_power_scale\0\0\xC0?\0\n\x0Fitem_properties\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x08\x0Ecreative_group\0\x03\x06damage\0\x03\x0Emax_stack_size\x80\x01\x03\ruse_animation\0\x03\x0Cuse_duration\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bwind_charge\0\0\x01\x04foil\0\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x08\x10enchantable_slot\x04none\x01\rhand_equipped\0\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\0\n\x12minecraft:cooldown\x08\x04type\x03use\x08\x08category\x0Bwind_charge\x05\x08duration\0\0\0?\0\t\titem_tags\0\0\0\0" } ;
pub const WITCH_SPAWN_EGG: Self = Self {
id: 456,
registry_key: "minecraft:witch_spawn_egg",
@ -97857,7 +97857,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const WOODEN_SPEAR : Self = Self { id : 856 , registry_key : "minecraft:wooden_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x14minecraft:durability\x03\x0Emax_durabilityx\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x05\x08durationff&?\x08\x04type\x06attack\0\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\x0F\0\n\x0Eminecraft:fuel\x05\x08duration\0\0 A\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x16minecraft:wooden_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\t\x05items\n\x02\x08\x04tags\x1Eq.all_tags('minecraft:planks')\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Citem.wooden_spear.attack_hit\x08\x0Battack_miss\x1Ditem.wooden_spear.attack_miss\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\n\x13dismount_conditions\x02\x0Cmax_durationd\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0`A\0\x02\x05delay\x0F\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\x11damage_multiplier333?\n\x11damage_conditions\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration,\x01\0\x05\x0Fdamage_modifier\0\0\0\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\xC8\0\0\0\0\t\titem_tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\n\x18minecraft:swing_duration\x05\x05valueff&?\0\n\x19minecraft:piercing_weapon\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\0\n\x10minecraft:damage\x02\x05value\x01\0\0\n\x16minecraft:display_name\x08\x05value\x16item.wooden_spear.name\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x08\x0Bstart_using\x06always\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x15item.wooden_spear.use\x05\x11movement_modifier\0\0\x80?\0\n\x0Fitem_properties\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x01\x04foil\0\x01\rhand_equipped\x01\x03\x06damage\x02\x03\ruse_animation\0\x08\x10enchantable_slot\x0Bmelee_spear\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nwood_spear\0\0\x01\x17can_destroy_in_creative\x01\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x0Emax_stack_size\x02\x03\x11enchantable_value\x1E\x01\x0Eallow_off_hand\0\x05\x0Cmining_speed\0\0\x80?\x08\x0Ecreative_group\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const WOODEN_SPEAR : Self = Self { id : 856 , registry_key : "minecraft:wooden_spear" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_duration\xC8\0\0\x05\rhitbox_margin\0\0\x80>\x05\x11damage_multiplier333?\n\x11damage_conditions\x02\x0Cmax_duration,\x01\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\0\x05\x0Fdamage_modifier\0\0\0\0\x02\x05delay\x0F\0\n\x13dismount_conditions\x02\x0Cmax_durationd\0\x05\tmin_speed\0\0`A\x05\x12min_relative_speed\0\0\0\0\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\t\x05items\n\x02\x08\x04name\x16minecraft:wooden_spear\0\x08\rrepair_amount)context.other->query.remaining_durability\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04tags\x1Eq.all_tags('minecraft:planks')\0\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\0\n\x16minecraft:display_name\x08\x05value\x16item.wooden_spear.name\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x05\x08durationff&?\x08\x04type\x06attack\0\n\x18minecraft:swing_duration\x05\x05valueff&?\0\n\x0Eminecraft:fuel\x05\x08duration\0\0 A\0\n\x17minecraft:use_modifiers\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\0\x08\x0Bstart_sound\x15item.wooden_spear.use\x05\x0Cuse_duration\0\xA0\x8CG\0\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\x03\ruse_animation\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x0Bmelee_spear\x03\x11enchantable_value\x1E\x01\x04foil\0\x01\rhand_equipped\x01\x03\x06damage\x02\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nwood_spear\0\0\x05\x0Cmining_speed\0\0\x80?\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\0\n\x10minecraft:damage\x02\x05value\x01\0\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Citem.wooden_spear.attack_hit\x08\x0Battack_miss\x1Ditem.wooden_spear.attack_miss\0\n\x15minecraft:enchantable\x01\x05value\x0F\x08\x04slot\x0Bmelee_spear\0\t\titem_tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\n\x14minecraft:durability\x03\x0Emax_durabilityx\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const WOODEN_SWORD: Self = Self {
id: 310,
registry_key: "minecraft:wooden_sword",
@ -97886,7 +97886,7 @@ impl BedrockItem {
component_based: false,
definition_components: b"\n\0\0",
};
pub const YELLOW_BUNDLE : Self = Self { id : 873 , registry_key : "minecraft:yellow_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n\x16minecraft:storage_item\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x0Fitem_properties\x03\x11creative_category\x06\x08\x0Ecreative_group\0\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x04none\x03\x0Cuse_duration\0\x01\x17can_destroy_in_creative\x01\x03\ruse_animation\0\x03\x06damage\0\x01\rhand_equipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\rbundle_yellow\x08\x10bundle_open_back\x17bundle_yellow_open_back\x08\x11bundle_open_front\x18bundle_yellow_open_front\0\0\x03\x0Emax_stack_size\x02\x03\x11enchantable_value\0\x01\x04foil\0\x01\x0Eallow_off_hand\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x03\x0Bframe_count\x02\0\t\titem_tags\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\0\0" } ;
pub const YELLOW_BUNDLE : Self = Self { id : 873 , registry_key : "minecraft:yellow_bundle" , version : BedrockItemVersion :: DataDriven , component_based : true , definition_components : b"\n\0\n\ncomponents\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x16minecraft:storage_item\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\t\rallowed_items\0\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x03\ruse_animation\0\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x08\x0Ecreative_group\0\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x18bundle_yellow_open_front\x08\x07default\rbundle_yellow\x08\x10bundle_open_back\x17bundle_yellow_open_back\0\0\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x01\rhand_equipped\0\x03\x0Cuse_duration\0\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x08\x10enchantable_slot\x04none\x03\x06damage\0\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x03\x11enchantable_value\0\x03\x0Emax_stack_size\x02\0\t\titem_tags\0\0\0\0" } ;
pub const YELLOW_CANDLE: Self = Self {
id: -417,
registry_key: "minecraft:yellow_candle",

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -16,8 +16,9 @@
pub mod chunk_view_lut;
#[rustfmt::skip]
#[path = "generated/chest_loot.rs"]
pub mod chest_loot_table;
#[path = "generated/loot_table.rs"]
pub mod loot_table;
pub use loot_table as chest_loot_table;
#[cfg(feature = "item")]
#[rustfmt::skip]

View File

@ -0,0 +1,494 @@
use std::any::Any;
use std::borrow::Cow;
use std::sync::Arc;
use std::sync::atomic::{AtomicU8, Ordering};
use pumpkin_data::data_component::DataComponent;
use pumpkin_data::data_component_impl::{EnchantmentsImpl, MaxDamageImpl, StoredEnchantmentsImpl};
use pumpkin_data::enchantment::Enchantment;
use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::screen::WindowType;
use pumpkin_data::tag::Enchantment as EnchantmentTag;
use pumpkin_data::tag::Taggable;
use pumpkin_protocol::java::server::play::SlotActionType;
use pumpkin_world::inventory::Inventory;
use crate::{
anvil::anvil_screen_handler::calculate_increased_repair_cost,
player::player_inventory::PlayerInventory,
screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerBehaviour, offer_or_drop_stack},
slot::Slot,
};
pub struct GrindstoneInputSlot {
pub inventory: Arc<dyn Inventory>,
pub index: usize,
pub id: AtomicU8,
}
impl GrindstoneInputSlot {
#[must_use]
pub fn new(inventory: Arc<dyn Inventory>, index: usize) -> Self {
Self {
inventory,
index,
id: AtomicU8::new(0),
}
}
}
impl Slot for GrindstoneInputSlot {
fn get_inventory(&self) -> Arc<dyn Inventory> {
self.inventory.clone()
}
fn get_index(&self) -> usize {
self.index
}
fn set_id(&self, id: usize) {
self.id.store(id as u8, Ordering::Relaxed);
}
fn can_insert(&self, stack: &ItemStack) -> bool {
stack.is_damageable() || has_any_enchantments(stack)
}
fn mark_dirty(&self) {
self.inventory.mark_dirty();
}
}
pub struct GrindstoneResultSlot {
pub inventory: Arc<dyn Inventory>,
pub index: usize,
pub id: AtomicU8,
}
impl GrindstoneResultSlot {
#[must_use]
pub fn new(inventory: Arc<dyn Inventory>, index: usize) -> Self {
Self {
inventory,
index,
id: AtomicU8::new(0),
}
}
}
impl Slot for GrindstoneResultSlot {
fn get_inventory(&self) -> Arc<dyn Inventory> {
self.inventory.clone()
}
fn get_index(&self) -> usize {
self.index
}
fn set_id(&self, id: usize) {
self.id.store(id as u8, Ordering::Relaxed);
}
fn can_insert(&self, _stack: &ItemStack) -> bool {
false
}
fn on_take_item(&self, player: &dyn InventoryPlayer, _stack: &ItemStack) {
let input = self
.inventory
.get_stack(GrindstoneScreenHandler::INPUT_SLOT);
let additional = self
.inventory
.get_stack(GrindstoneScreenHandler::ADDITIONAL_SLOT);
let xp_amount = GrindstoneScreenHandler::calculate_experience_amount(&input, &additional);
player.use_grindstone(xp_amount);
self.inventory.set_stack(
GrindstoneScreenHandler::INPUT_SLOT,
ItemStack::EMPTY.clone(),
);
self.inventory.set_stack(
GrindstoneScreenHandler::ADDITIONAL_SLOT,
ItemStack::EMPTY.clone(),
);
self.mark_dirty();
}
fn mark_dirty(&self) {
self.inventory.mark_dirty();
}
}
#[must_use]
pub fn get_enchantments_for_crafting(stack: &ItemStack) -> Vec<(&'static Enchantment, i32)> {
if stack.is_empty() {
return Vec::new();
}
if stack.item == &Item::ENCHANTED_BOOK {
if let Some(stored) = stack.get_data_component::<StoredEnchantmentsImpl>() {
return stored
.enchantment
.iter()
.map(|(e, lvl)| (*e, *lvl))
.collect();
}
} else if let Some(ench) = stack.get_data_component::<EnchantmentsImpl>() {
return ench.enchantment.iter().map(|(e, lvl)| (*e, *lvl)).collect();
}
Vec::new()
}
#[must_use]
pub fn has_any_enchantments(stack: &ItemStack) -> bool {
!get_enchantments_for_crafting(stack).is_empty()
}
pub fn set_enchantments(result: &mut ItemStack, enchantments: Vec<(&'static Enchantment, i32)>) {
if result.is_empty() {
return;
}
if enchantments.is_empty() {
result.patch.retain(|(id, _)| {
*id != DataComponent::Enchantments && *id != DataComponent::StoredEnchantments
});
return;
}
if result.item == &Item::ENCHANTED_BOOK
|| result
.get_data_component::<StoredEnchantmentsImpl>()
.is_some()
{
let stored = StoredEnchantmentsImpl {
enchantment: Cow::Owned(enchantments),
};
result.set_data_component(stored);
} else {
let ench = EnchantmentsImpl {
enchantment: Cow::Owned(enchantments),
};
result.set_data_component(ench);
}
}
pub struct GrindstoneScreenHandler {
pub inventory: Arc<dyn Inventory>,
behaviour: ScreenHandlerBehaviour,
}
impl GrindstoneScreenHandler {
pub const MAX_NAME_LENGTH: usize = 35;
pub const INPUT_SLOT: usize = 0;
pub const ADDITIONAL_SLOT: usize = 1;
pub const RESULT_SLOT: usize = 2;
pub const INV_SLOT_START: i32 = 3;
pub const INV_SLOT_END: i32 = 30;
pub const USE_ROW_SLOT_START: i32 = 30;
pub const USE_ROW_SLOT_END: i32 = 39;
pub fn new(
sync_id: u8,
player_inventory: &Arc<PlayerInventory>,
inventory: Arc<dyn Inventory>,
) -> Self {
let mut handler = Self {
inventory: inventory.clone(),
behaviour: ScreenHandlerBehaviour::new(sync_id, Some(WindowType::Grindstone)),
};
// Slot 0: Input slot
handler.add_slot(Arc::new(GrindstoneInputSlot::new(
inventory.clone(),
Self::INPUT_SLOT,
)));
// Slot 1: Additional slot
handler.add_slot(Arc::new(GrindstoneInputSlot::new(
inventory.clone(),
Self::ADDITIONAL_SLOT,
)));
// Slot 2: Result slot
handler.add_slot(Arc::new(GrindstoneResultSlot::new(
inventory,
Self::RESULT_SLOT,
)));
let player_inventory: Arc<dyn Inventory> = player_inventory.clone();
handler.add_player_slots(&player_inventory);
handler
}
pub fn create_result(&mut self) {
let input = self.inventory.get_stack(Self::INPUT_SLOT);
let additional = self.inventory.get_stack(Self::ADDITIONAL_SLOT);
let result = Self::compute_result(&input, &additional);
self.inventory.set_stack(Self::RESULT_SLOT, result);
}
#[must_use]
pub fn compute_result(input: &ItemStack, additional: &ItemStack) -> ItemStack {
let has_an_item = !input.is_empty() || !additional.is_empty();
if !has_an_item {
return ItemStack::EMPTY.clone();
}
if input.item_count <= 1 && additional.item_count <= 1 {
let has_both_items = !input.is_empty() && !additional.is_empty();
if has_both_items {
Self::merge_items(input, additional)
} else {
let item = if input.is_empty() { additional } else { input };
if has_any_enchantments(item) {
Self::remove_non_curses_from(item.clone())
} else {
ItemStack::EMPTY.clone()
}
}
} else {
ItemStack::EMPTY.clone()
}
}
#[must_use]
pub fn merge_items(input: &ItemStack, additional: &ItemStack) -> ItemStack {
if input.item != additional.item {
return ItemStack::EMPTY.clone();
}
let max_damage1 = input.get_max_damage().unwrap_or(0);
let max_damage2 = additional.get_max_damage().unwrap_or(0);
let durability = max_damage1.max(max_damage2);
let remaining1 = max_damage1 - input.get_damage();
let remaining2 = max_damage2 - additional.get_damage();
let remaining = remaining1 + remaining2 + durability * 5 / 100;
let count = if input.is_damageable() {
1
} else {
if input.get_max_stack_size() < 2 || !input.are_equal(additional) {
return ItemStack::EMPTY.clone();
}
2
};
let mut new_item = input.copy_with_count(count);
if new_item.is_damageable() {
new_item.set_data_component(MaxDamageImpl {
max_damage: durability,
});
new_item.set_damage((durability - remaining).max(0));
}
Self::merge_enchants_from(&mut new_item, additional);
Self::remove_non_curses_from(new_item)
}
pub fn merge_enchants_from(target: &mut ItemStack, source: &ItemStack) {
let mut target_enchantments = get_enchantments_for_crafting(target);
let source_enchantments = get_enchantments_for_crafting(source);
for (enchant, level) in source_enchantments {
let is_curse = enchant.has_tag(&EnchantmentTag::MINECRAFT_CURSE);
if let Some(target_entry) = target_enchantments.iter_mut().find(|(e, _)| *e == enchant)
{
if !is_curse || target_entry.1 == 0 {
target_entry.1 = target_entry.1.max(level);
}
} else {
target_enchantments.push((enchant, level));
}
}
set_enchantments(target, target_enchantments);
}
#[must_use]
pub fn remove_non_curses_from(mut item: ItemStack) -> ItemStack {
let enchantments = get_enchantments_for_crafting(&item);
let curses: Vec<(&'static Enchantment, i32)> = enchantments
.into_iter()
.filter(|(ench, _)| ench.has_tag(&EnchantmentTag::MINECRAFT_CURSE))
.collect();
let curses_count = curses.len();
if item.item == &Item::ENCHANTED_BOOK && curses_count == 0 {
item.item = &Item::BOOK;
}
set_enchantments(&mut item, curses);
let mut repair_cost = 0;
for _ in 0..curses_count {
repair_cost = calculate_increased_repair_cost(repair_cost);
}
item.set_repair_cost(repair_cost);
item
}
#[must_use]
pub fn calculate_experience_amount(input: &ItemStack, additional: &ItemStack) -> i32 {
let mut amount = 0;
amount += Self::get_experience_from_item(input);
amount += Self::get_experience_from_item(additional);
if amount > 0 {
let half_amount = ((f64::from(amount)) / 2.0).ceil() as i32;
let random_bonus = if half_amount > 0 {
(rand::random::<u32>() as usize % half_amount as usize) as i32
} else {
0
};
half_amount + random_bonus
} else {
0
}
}
#[must_use]
pub fn get_experience_from_item(item: &ItemStack) -> i32 {
let mut amount = 0;
let enchantments = get_enchantments_for_crafting(item);
for (enchant, lvl) in enchantments {
if !enchant.has_tag(&EnchantmentTag::MINECRAFT_CURSE) {
amount += enchant.min_cost.calculate(lvl);
}
}
amount
}
}
impl ScreenHandler for GrindstoneScreenHandler {
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn get_behaviour(&self) -> &ScreenHandlerBehaviour {
&self.behaviour
}
fn get_behaviour_mut(&mut self) -> &mut ScreenHandlerBehaviour {
&mut self.behaviour
}
fn on_closed(&mut self, player: &dyn InventoryPlayer) {
self.default_on_closed(player);
self.inventory.on_close();
for i in 0..2 {
let stack = self.inventory.remove_stack(i);
if !stack.is_empty() {
offer_or_drop_stack(player, stack);
}
}
self.inventory
.set_stack(Self::RESULT_SLOT, ItemStack::EMPTY.clone());
}
fn quick_move(&mut self, player: &dyn InventoryPlayer, slot_index: i32) -> ItemStack {
let mut stack_left = ItemStack::EMPTY.clone();
let slot = self.get_behaviour().slots.get(slot_index as usize).cloned();
if let Some(slot) = slot
&& slot.has_stack()
{
let mut slot_stack = slot.get_stack();
stack_left = slot_stack.clone();
let input = self.inventory.get_stack(Self::INPUT_SLOT);
let additional = self.inventory.get_stack(Self::ADDITIONAL_SLOT);
if slot_index as usize == Self::RESULT_SLOT {
if !self.insert_item(
&mut slot_stack,
Self::INV_SLOT_START,
Self::USE_ROW_SLOT_END,
true,
) {
return ItemStack::EMPTY.clone();
}
slot.on_quick_move_crafted(slot_stack.clone(), stack_left.clone());
slot.on_take_item(player, &stack_left);
self.create_result();
self.send_content_updates();
return stack_left;
} else if slot_index < Self::INV_SLOT_START {
// Input slots (0, 1): from grindstone to player inventory (3..39, reversed = false)
if !self.insert_item(
&mut slot_stack,
Self::INV_SLOT_START,
Self::USE_ROW_SLOT_END,
false,
) {
return ItemStack::EMPTY.clone();
}
} else {
// Player inventory (3..39)
if !input.is_empty() && !additional.is_empty() {
if slot_index < Self::USE_ROW_SLOT_START {
if !self.insert_item(
&mut slot_stack,
Self::USE_ROW_SLOT_START,
Self::USE_ROW_SLOT_END,
false,
) {
return ItemStack::EMPTY.clone();
}
} else if !self.insert_item(
&mut slot_stack,
Self::INV_SLOT_START,
Self::INV_SLOT_END,
false,
) {
return ItemStack::EMPTY.clone();
}
} else if !self.insert_item(
&mut slot_stack,
Self::INPUT_SLOT as i32,
Self::RESULT_SLOT as i32,
false,
) {
return ItemStack::EMPTY.clone();
}
}
if slot_stack.item_count == stack_left.item_count {
return ItemStack::EMPTY.clone();
}
if slot_stack.is_empty() {
slot.set_stack(ItemStack::EMPTY.clone());
} else {
slot.set_stack(slot_stack.clone());
}
slot.on_take_item(player, &slot_stack);
slot.mark_dirty();
self.create_result();
self.send_content_updates();
}
stack_left
}
fn on_slot_click(
&mut self,
slot_index: i32,
button: i32,
action_type: SlotActionType,
player: &dyn InventoryPlayer,
) {
self.internal_on_slot_click(slot_index, button, action_type, player);
if (slot_index as usize) <= Self::RESULT_SLOT {
self.create_result();
self.send_content_updates();
}
}
}

View File

@ -46,6 +46,7 @@ pub mod entity_equipment;
mod error;
pub mod furnace_like;
pub mod generic_container_screen_handler;
pub mod grindstone_screen_handler;
pub mod gui_builder;
pub mod lectern_screen_handler;
pub mod loom_screen_handler;

View File

@ -211,6 +211,9 @@ pub trait InventoryPlayer: Send + Sync {
/// Performs anvil block damage and plays anvil sound events.
fn use_anvil(&self) {}
/// Performs grindstone experience drop and plays grindstone sound events.
fn use_grindstone(&self, _xp_amount: i32) {}
}
/// Gives a stack to the player or drops it if inventory is full.

View File

@ -1,33 +0,0 @@
/// A single item entry inside a chest loot pool.
#[derive(Clone, Copy, Debug)]
pub struct ChestLootEntry {
/// Registry name of the item (e.g. `"minecraft:diamond"`).
pub item: &'static str,
/// Relative probability weight; higher values are more likely.
pub weight: i32,
/// Minimum stack size (inclusive).
pub min_count: i32,
/// Maximum stack size (inclusive).
pub max_count: i32,
}
/// One roll pool inside a chest loot table.
#[derive(Clone, Copy, Debug)]
pub struct ChestLootPool {
/// Item entries eligible for selection each roll.
pub entries: &'static [ChestLootEntry],
/// Minimum number of roll attempts (inclusive).
pub min_rolls: i32,
/// Maximum number of roll attempts (inclusive).
pub max_rolls: i32,
/// Weight of the implicit "empty" (no item) outcome per roll.
/// In vanilla this is modelled as a `minecraft:empty` entry with the given weight.
pub empty_weight: i32,
}
/// A complete chest loot table consisting of one or more pools.
#[derive(Clone, Copy, Debug)]
pub struct ChestLootTable {
/// All pools to roll when generating loot for this table.
pub pools: &'static [ChestLootPool],
}

View File

@ -16,7 +16,6 @@ pub use permission::PermissionLvl;
use crate::{math::vector3::Axis, random::RandomImpl};
pub mod biome;
pub mod chest_loot_table;
pub mod difficulty;
pub mod gamemode;
pub mod loot_table;

View File

@ -1,369 +1,65 @@
#[cfg(feature = "codegen")]
use proc_macro2::TokenStream;
#[cfg(feature = "codegen")]
use quote::{ToTokens, quote};
use serde::Deserialize;
use crate::random::RandomImpl;
/// Represents a loot table used to generate items or rewards.
#[derive(Clone, Copy, Debug)]
pub struct LootTable {
/// The type of loot table (e.g., `Entity`, `Block`, `Chest`).
pub r#type: LootTableType,
/// Optional random sequence identifier for deterministic rolls.
pub random_sequence: Option<&'static str>,
/// Optional array of loot pools that define item generation.
pub pools: Option<&'static [LootPool]>,
}
/// Defines a loot pool containing entries, rolls, and conditions.
#[derive(Clone, Debug)]
pub struct LootPool {
/// Entries contained in this loot pool.
pub entries: &'static [LootPoolEntry],
/// Number of rolls, specified using a number provider.
pub rolls: LootNumberProviderTypes,
/// Additional bonus rolls to apply.
pub bonus_rolls: LootNumberProviderTypes,
/// Optional conditions that must be met for this pool to be applied.
pub conditions: Option<&'static [LootCondition]>,
/// Optional functions applied to each entry in the pool.
pub functions: Option<&'static [LootFunction]>,
}
/// Represents an individual item entry in a loot pool.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ItemEntry {
/// Name of the item.
pub name: &'static str,
}
/// Represents an alternative loot entry, which chooses one of its children.
#[derive(Clone, Debug)]
pub struct AlternativeEntry {
/// Child entries for this alternative.
pub children: &'static [LootPoolEntry],
}
#[derive(Clone, Debug)]
pub struct TagEntry {
pub name: &'static str,
pub expand: bool,
}
#[derive(Clone, Debug)]
pub struct SequenceEntry {
pub children: &'static [LootPoolEntry],
}
#[derive(Clone, Debug)]
pub struct GroupEntry {
pub children: &'static [LootPoolEntry],
}
#[derive(Clone, Debug)]
pub struct LootTableEntry {
pub value: &'static str,
}
#[derive(Clone, Debug)]
pub struct DynamicEntry {
pub name: &'static str,
}
#[derive(Clone, Debug)]
pub enum LootPoolEntryTypes {
Empty,
Item(ItemEntry),
LootTable(LootTableEntry),
Dynamic(DynamicEntry),
Tag(TagEntry),
Alternatives(AlternativeEntry),
Sequence(SequenceEntry),
Group(GroupEntry),
}
/// Conditions that can modify whether loot entries are applied.
#[derive(Clone, PartialEq, Debug)]
/// Conditions required for an entry or pool to be eligible for loot generation.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum LootCondition {
/// Inverts the result of another condition.
Inverted(&'static Self),
/// Passes if any of the given conditions are met.
AnyOf(&'static [Self]),
/// Passes only if all the given conditions are met.
AllOf(&'static [Self]),
/// Passes based on a random chance.
RandomChance { chance: f32 },
/// Passes based on a random chance modified by item enchantments.
RandomChanceWithEnchantedBonus {
enchantment: &'static str,
chances: Option<&'static [f32]>,
},
/// Checks properties of the entity (e.g. type, flags, equipment).
/// Mirrors vanilla `LootItemEntityPropertyCondition`.
EntityProperties {
/// The entity target to check: "this", "attacker", or "`direct_attacker`".
entity: &'static str,
/// Expected entity type (e.g. "minecraft:cow").
expected_type: Option<&'static str>,
/// When `Some`, the entity must be on fire for the condition to pass.
/// Mirrors vanilla `EntityFlagsPredicate.isOnFire`.
is_on_fire: Option<bool>,
/// When `Some`, the entity's mainhand item must have an enchantment in this tag.
/// Mirrors vanilla `EntityEquipmentPredicate.mainhand` with enchantment tag lookup.
mainhand_enchantment_tag: Option<&'static str>,
},
/// Requires the entity to have been killed by a player.
KilledByPlayer,
/// Checks entity scores against specified criteria.
EntityScores { entity: &'static str },
/// Checks block state properties.
BlockStateProperty {
/// The block to check.
block: &'static str,
/// Key-value pairs of properties and their expected values.
properties: &'static [(&'static str, &'static str)],
},
/// Requires a specific tool to match certain criteria.
MatchTool {
items: Option<&'static [&'static str]>,
},
/// Applies a bonus based on a table.
TableBonus {
enchantment: &'static str,
chances: &'static [f32],
},
/// Survives explosion damage.
#[default]
None,
SilkTouch,
NoSilkTouch,
Shears,
SilkTouchOrShears,
NoSilkTouchOrShears,
SurvivesExplosion,
/// Checks properties of the damage source.
DamageSourceProperties {
expected_source_type: Option<&'static str>,
expected_direct_type: Option<&'static str>,
},
/// Checks the location of the entity.
LocationCheck {
offset_x: i32,
offset_y: i32,
offset_z: i32,
expected_biome: Option<&'static str>,
},
/// Checks weather conditions.
WeatherCheck {
raining: Option<bool>,
thundering: Option<bool>,
},
/// References to another condition or table.
Reference { name: &'static str },
/// Checks the in-game time.
TimeCheck {
range: (Option<f32>, Option<f32>),
period: Option<u64>,
},
/// Checks against a specific value or range.
ValueCheck {
value: LootNumberProviderTypes,
range: (Option<f32>, Option<f32>),
},
/// Checks if a specific enchantment is active.
EnchantmentActiveCheck { active: bool },
KilledByPlayer,
}
/// Functions applied to loot entries.
#[derive(Clone, PartialEq, Debug)]
pub struct LootFunction {
/// The type of function to apply.
pub content: LootFunctionTypes,
/// Optional conditions for the function.
pub conditions: Option<&'static [LootCondition]>,
/// Bonus count formulas when tools have fortune or looting enchantments.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LootBonusFormula {
OreDrops,
UniformBonusCount(i32),
BinomialWithBonusCount { extra: i32, probability: f32 },
}
/// Specific types of loot functions.
#[derive(Clone, PartialEq, Debug)]
pub enum LootFunctionTypes {
/// Sets the number of items in the stack, optionally adding to an existing count.
SetCount {
count: LootFunctionNumberProvider,
add: bool,
},
/// Increases the count of items based on the item's enchantments.
EnchantedCountIncrease {
enchantment: &'static str,
count: LootFunctionNumberProvider,
limit: Option<f32>,
},
/// Smelts the item as if it passed through a furnace.
FurnaceSmelt,
/// Sets the potion type for potion items.
SetPotion { id: &'static str },
/// Sets the amplifier for ominous bottles.
SetOminousBottleAmplifier,
/// Limits the count of items to a minimum and/or maximum value.
LimitCount { min: Option<f32>, max: Option<f32> },
/// Applies a bonus based on an enchantment and a formula, optionally with extra parameters.
ApplyBonus {
enchantment: &'static str,
formula: &'static str,
parameters: Option<LootFunctionBonusParameter>,
},
/// Copies specified components from a source entity or item.
CopyComponents {
source: &'static str,
include: &'static [&'static str],
},
/// Copies state or properties from a block.
CopyState {
block: &'static str,
properties: &'static [&'static str],
},
/// Applies decay to items in case of an explosion.
ExplosionDecay,
}
/// Numeric providers for loot function counts.
#[derive(Clone, PartialEq, Debug)]
pub enum LootFunctionNumberProvider {
/// Constant value.
Constant { value: f32 },
/// Uniform random value between min and max.
Uniform { min: f32, max: f32 },
/// Binomial distribution.
Binomial { n: f32, p: f32 },
}
/// Parameters for loot bonus functions.
#[derive(Clone, PartialEq, Debug)]
pub enum LootFunctionBonusParameter {
/// Multiplier applied to bonus rolls.
Multiplier { bonus_multiplier: i32 },
/// Probability-based bonus application.
Probability { extra: i32, probability: f32 },
}
/// Single entry in a loot pool with optional conditions and functions.
#[derive(Clone, Debug)]
pub struct LootPoolEntry {
/// The type of entry.
pub content: LootPoolEntryTypes,
/// A single item entry inside a loot pool.
#[derive(Clone, Copy, Debug)]
pub struct LootEntry {
/// Registry name of the item (e.g. `"minecraft:diamond"`).
pub item: &'static str,
/// Relative probability weight; higher values are more likely.
pub weight: i32,
/// Quality of the entry, used to modify weight based on luck.
pub quality: i32,
/// Optional conditions for this entry.
pub conditions: Option<&'static [LootCondition]>,
/// Optional functions for this entry.
pub functions: Option<&'static [LootFunction]>,
/// Minimum stack size (inclusive).
pub min_count: i32,
/// Maximum stack size (inclusive).
pub max_count: i32,
/// Condition required for this entry to be eligible.
pub condition: LootCondition,
/// Bonus formula to apply with fortune / looting (if any).
pub bonus_formula: Option<LootBonusFormula>,
}
/// Categories of loot tables.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum LootTableType {
/// Empty loot table.
Empty,
/// Entity loot table.
Entity,
/// Block loot table.
Block,
/// Chest loot table.
Chest,
/// One roll pool inside a loot table.
#[derive(Clone, Copy, Debug)]
pub struct LootPool {
/// Item entries eligible for selection each roll.
pub entries: &'static [LootEntry],
/// Minimum number of roll attempts (inclusive).
pub min_rolls: i32,
/// Maximum number of roll attempts (inclusive).
pub max_rolls: i32,
/// Weight of the implicit "empty" (no item) outcome per roll.
/// In vanilla this is modelled as a `minecraft:empty` entry with the given weight.
pub empty_weight: i32,
/// Condition required for this entire pool to run.
pub condition: LootCondition,
}
/// Represents structured number providers used in loot rolls.
#[derive(Deserialize, PartialEq, Clone, Copy, Debug)]
#[serde(tag = "type")]
pub enum LootNumberProviderTypesProvider {
/// Uniformly distributes a random number between `min` and `max` (inclusive).
#[serde(rename = "minecraft:uniform")]
Uniform(UniformLootNumberProvider),
/// A complete loot table consisting of one or more pools.
#[derive(Clone, Copy, Debug)]
pub struct LootTable {
/// All pools to roll when generating loot for this table.
pub pools: &'static [LootPool],
}
#[cfg(feature = "codegen")]
impl ToTokens for LootNumberProviderTypesProvider {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Self::Uniform(uniform) => {
tokens.extend(quote! {
LootNumberProviderTypesProvider::Uniform(#uniform)
});
}
}
}
}
/// Uniform numeric provider for loot rolls.
#[derive(Deserialize, PartialEq, Clone, Copy, Debug)]
pub struct UniformLootNumberProvider {
/// Minimum value (inclusive).
pub min: f32,
/// Maximum value (inclusive).
pub max: f32,
}
#[cfg(feature = "codegen")]
impl ToTokens for UniformLootNumberProvider {
fn to_tokens(&self, tokens: &mut TokenStream) {
let min_inclusive = self.min;
let max_inclusive = self.max;
tokens.extend(quote! {
UniformLootNumberProvider { min: #min_inclusive, max: #max_inclusive }
});
}
}
impl UniformLootNumberProvider {
/// Generates a random number within the uniform range.
///
/// # Parameters
/// - `random`: A random number generator implementing `RandomImpl`.
///
/// # Returns
/// A `f32` between `min` and `max`.
pub fn get(&self, random: &mut impl RandomImpl) -> f32 {
random.next_f32().mul_add(self.max - self.min, self.min)
}
}
/// Numeric providers for loot table rolls (either object or constant).
#[derive(Deserialize, PartialEq, Clone, Copy, Debug)]
#[serde(untagged)]
pub enum LootNumberProviderTypes {
/// A structured provider object (e.g., uniform).
Object(LootNumberProviderTypesProvider),
/// Constant numeric value.
Constant(f32),
}
#[cfg(feature = "codegen")]
impl ToTokens for LootNumberProviderTypes {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Self::Object(provider) => {
tokens.extend(quote! {
LootNumberProviderTypes::Object(#provider)
});
}
Self::Constant(i) => tokens.extend(quote! {
LootNumberProviderTypes::Constant(#i)
}),
}
}
}
impl LootNumberProviderTypes {
/// Computes a numeric value from this provider.
///
/// # Parameters
/// - `random`: A random number generator implementing `RandomImpl`.
///
/// # Returns
/// A `f32` value as determined by the provider (constant or computed).
pub fn get(&self, random: &mut impl RandomImpl) -> f32 {
match self {
Self::Object(int_provider) => match int_provider {
LootNumberProviderTypesProvider::Uniform(uniform) => uniform.get(random),
},
Self::Constant(i) => *i,
}
}
}
pub type ChestLootEntry = LootEntry;
pub type ChestLootPool = LootPool;
pub type ChestLootTable = LootTable;

View File

@ -8,7 +8,7 @@ use serde::Deserialize;
use syn::LitFloat;
/// Represents different types of number providers that generate floating-point values.
#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Debug, PartialEq)]
#[serde(tag = "type")]
pub enum NormalFloatProvider {
/// Always returns the same constant value.
@ -54,7 +54,7 @@ impl ToTokens for NormalFloatProvider {
}
/// A flexible float provider that can be either a constant value or a complex provider.
#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Debug, PartialEq)]
#[serde(untagged)]
pub enum FloatProvider {
/// A complex provider with configurable distribution.
@ -135,7 +135,7 @@ impl FloatProvider {
}
/// A float provider that always returns the same constant value.
#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct ConstantFloatProvider {
/// The constant value that will always be returned.
value: f32,
@ -195,7 +195,7 @@ impl ConstantFloatProvider {
}
/// A float provider that generates uniformly distributed random values.
#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct UniformFloatProvider {
/// The minimum value (inclusive) that can be generated.
min_inclusive: f32,
@ -264,7 +264,7 @@ impl UniformFloatProvider {
}
/// A float provider that generates values from a normal (Gaussian) distribution.
#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct ClampedNormalFloatProvider {
/// The mean (centre) of the normal distribution.
mean: f32,
@ -351,7 +351,7 @@ impl ClampedNormalFloatProvider {
}
/// A float provider that generates values from a trapezoidal distribution.
#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct TrapezoidFloatProvider {
/// The minimum value (inclusive) that can be generated.
min: f32,

View File

@ -223,14 +223,27 @@ impl BlockPos {
Self(Vector3::new(x, y, z))
}
#[must_use]
pub const fn containing(x: f64, y: f64, z: f64) -> Self {
Self::floored(x, y, z)
}
#[must_use]
pub const fn containing_vec(pos: Vector3<f64>) -> Self {
Self::floored_v(pos)
}
#[must_use]
pub fn min(a: Self, b: Self) -> Self {
Self::new(a.0.x.min(b.0.x), a.0.y.min(b.0.y), a.0.z.min(b.0.z))
}
#[must_use]
pub fn max(a: Self, b: Self) -> Self {
Self::new(a.0.x.max(b.0.x), a.0.y.max(b.0.y), a.0.z.max(b.0.z))
}
/// Iterates through all `BlockPos` within a cuboid region defined by two corner points.
///
/// # Arguments
/// - `start` – One corner of the cuboid region.
/// - `end` – The opposite corner of the cuboid region.
///
/// # Returns
/// A `BlockPosIterator` that yields each `BlockPos` within the defined cuboid.
#[must_use]
pub fn iterate(start: Self, end: Self) -> BlockPosIterator {
BlockPosIterator::new(
@ -243,6 +256,30 @@ impl BlockPos {
)
}
#[must_use]
pub fn between_closed(start: Self, end: Self) -> BlockPosIterator {
Self::iterate(start, end)
}
#[must_use]
pub fn between_closed_coords(
min_x: i32,
min_y: i32,
min_z: i32,
max_x: i32,
max_y: i32,
max_z: i32,
) -> BlockPosIterator {
BlockPosIterator::new(
min_x.min(max_x),
min_y.min(max_y),
min_z.min(max_z),
min_x.max(max_x),
min_y.max(max_y),
min_z.max(max_z),
)
}
/// Iterates through `BlockPos` objects outward from a specified `center` point.
///
/// # Arguments
@ -594,6 +631,15 @@ impl BlockPos {
self.0.squared_distance_to_vec(&other.0)
}
/// Calculates the squared distance from this block's center `(x + 0.5, y + 0.5, z + 0.5)` to `(x, y, z)`.
#[must_use]
pub fn dist_to_center_sqr(&self, x: f64, y: f64, z: f64) -> f64 {
let dx = f64::from(self.0.x) + 0.5 - x;
let dy = f64::from(self.0.y) + 0.5 - y;
let dz = f64::from(self.0.z) + 0.5 - z;
dx * dx + dy * dy + dz * dz
}
/// Packs this block position into a 64-bit integer.
///
/// The packing format is:
@ -746,8 +792,8 @@ pub const fn get_local_cord(cord: i32) -> i32 {
#[must_use]
pub const fn pack_local_chunk_section(block_pos: &BlockPos) -> i16 {
let x = get_local_cord(block_pos.0.x);
let z = get_local_cord(block_pos.0.z);
let y = get_local_cord(block_pos.0.y);
let z = get_local_cord(block_pos.0.z);
vector3::packed_local(&Vector3::new(x, y, z))
}

View File

@ -5,6 +5,7 @@ use pumpkin_data::{Block, BlockDirection, BlockState, BlockStateId};
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
use crate::generation::proto_chunk::GenerationCache;
use crate::world::BlockAccessor;
use crate::{block::BlockStateCodec, world::WorldPortalExt};
pub enum BlockPredicate {
@ -19,9 +20,8 @@ pub enum BlockPredicate {
AnyOf(AnyOfBlockPredicate),
AllOf(AllOfBlockPredicate),
Not(NotBlockPredicate),
Unobstructed(UnobstructedBlockPredicate),
AlwaysTrue,
// Not used
// // Unobstructed(EmptyTODOStruct),
}
impl BlockPredicate {
@ -43,6 +43,30 @@ impl BlockPredicate {
Self::AnyOf(predicate) => predicate.test(block_registry, chunk, pos),
Self::AllOf(predicate) => predicate.test(block_registry, chunk, pos),
Self::Not(predicate) => predicate.test(block_registry, chunk, pos),
Self::Unobstructed(predicate) => predicate.test(chunk, pos),
Self::AlwaysTrue => true,
}
}
pub fn test_world(
&self,
world: &dyn BlockAccessor,
block_registry: Option<&dyn WorldPortalExt>,
pos: &BlockPos,
) -> bool {
match self {
Self::MatchingBlocks(predicate) => predicate.test_world(world, pos),
Self::MatchingBlockTag(predicate) => predicate.test_world(world, pos),
Self::MatchingFluids(predicate) => predicate.test_world(world, pos),
Self::HasSturdyFace(predicate) => predicate.test_world(world, pos),
Self::Solid(predicate) => predicate.test_world(world, pos),
Self::Replaceable(predicate) => predicate.test_world(world, pos),
Self::WouldSurvive(predicate) => predicate.test_world(block_registry, world, pos),
Self::InsideWorldBounds(predicate) => predicate.test_world(world, pos),
Self::AnyOf(predicate) => predicate.test_world(block_registry, world, pos),
Self::AllOf(predicate) => predicate.test_world(block_registry, world, pos),
Self::Not(predicate) => predicate.test_world(block_registry, world, pos),
Self::Unobstructed(predicate) => predicate.test_world(world, pos),
Self::AlwaysTrue => true,
}
}
@ -69,6 +93,22 @@ impl MatchingBlocksBlockPredicate {
.contains(block.name),
}
}
pub fn test_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let block = self.offset.get_block_world(world, pos);
match &self.blocks {
MatchingBlocksWrapper::Single(single_block) => {
single_block
.strip_prefix("minecraft:")
.unwrap_or(single_block)
== block.name
}
MatchingBlocksWrapper::Multiple(blocks) => blocks
.iter()
.map(|s| s.strip_prefix("minecraft:").unwrap_or(s))
.contains(block.name),
}
}
}
pub struct InsideWorldBoundsBlockPredicate {
@ -80,6 +120,11 @@ impl InsideWorldBoundsBlockPredicate {
let pos = pos.offset(self.offset);
!chunk.out_of_height(pos.0.y as i16)
}
pub fn test_world(&self, _world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let pos = pos.offset(self.offset);
pos.0.y >= -64 && pos.0.y < 320
}
}
pub struct MatchingFluidsBlockPredicate {
@ -103,6 +148,27 @@ impl MatchingFluidsBlockPredicate {
.contains(fluid.name),
}
}
pub fn test_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let block = self.offset.get_block_world(world, pos);
let fluid_name = match block.name {
"water" | "flowing_water" => "water",
"lava" | "flowing_lava" => "lava",
_ => "empty",
};
match &self.fluids {
MatchingBlocksWrapper::Single(single_block) => {
single_block
.strip_prefix("minecraft:")
.unwrap_or(single_block)
== fluid_name
}
MatchingBlocksWrapper::Multiple(blocks) => blocks
.iter()
.map(|s| s.strip_prefix("minecraft:").unwrap_or(s))
.contains(fluid_name),
}
}
}
pub struct MatchingBlockTagPredicate {
@ -115,6 +181,11 @@ impl MatchingBlockTagPredicate {
let state = self.offset.get_id(chunk, pos);
state.to_block_id().has_tag(self.tag)
}
pub fn test_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let state = self.offset.get_id_world(world, pos);
state.to_block_id().has_tag(self.tag)
}
}
pub struct HasSturdyFacePredicate {
@ -127,6 +198,11 @@ impl HasSturdyFacePredicate {
let state = self.offset.get_state(chunk, pos);
state.is_side_solid(self.direction)
}
pub fn test_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let state = self.offset.get_state_world(world, pos);
state.is_side_solid(self.direction)
}
}
pub struct AnyOfBlockPredicate {
@ -148,6 +224,20 @@ impl AnyOfBlockPredicate {
}
false
}
pub fn test_world(
&self,
block_registry: Option<&dyn WorldPortalExt>,
world: &dyn BlockAccessor,
pos: &BlockPos,
) -> bool {
for predicate in &self.predicates {
if predicate.test_world(world, block_registry, pos) {
return true;
}
}
false
}
}
pub struct AllOfBlockPredicate {
@ -169,6 +259,20 @@ impl AllOfBlockPredicate {
}
true
}
pub fn test_world(
&self,
block_registry: Option<&dyn WorldPortalExt>,
world: &dyn BlockAccessor,
pos: &BlockPos,
) -> bool {
for predicate in &self.predicates {
if !predicate.test_world(world, block_registry, pos) {
return false;
}
}
true
}
}
pub struct NotBlockPredicate {
@ -184,6 +288,15 @@ impl NotBlockPredicate {
) -> bool {
!self.predicate.test(block_registry, chunk, pos)
}
pub fn test_world(
&self,
block_registry: Option<&dyn WorldPortalExt>,
world: &dyn BlockAccessor,
pos: &BlockPos,
) -> bool {
!self.predicate.test_world(world, block_registry, pos)
}
}
pub struct SolidBlockPredicate {
@ -195,6 +308,11 @@ impl SolidBlockPredicate {
let state = self.offset.get_state(chunk, pos);
state.is_solid()
}
pub fn test_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let state = self.offset.get_state_world(world, pos);
state.is_solid()
}
}
pub struct WouldSurviveBlockPredicate {
@ -215,6 +333,18 @@ impl WouldSurviveBlockPredicate {
let pos = self.offset.get(pos);
block_registry.can_place_at(block, state, chunk, &pos)
}
pub fn test_world(
&self,
block_registry: Option<&dyn WorldPortalExt>,
world: &dyn BlockAccessor,
pos: &BlockPos,
) -> bool {
let block = self.state.get_block();
let state = self.state.get_state();
let pos = self.offset.get(pos);
block_registry.is_none_or(|registry| registry.can_place_at(block, state, world, &pos))
}
}
pub struct ReplaceableBlockPredicate {
@ -226,6 +356,25 @@ impl ReplaceableBlockPredicate {
let state = self.offset.get_state(chunk, pos);
state.replaceable()
}
pub fn test_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let state = self.offset.get_state_world(world, pos);
state.replaceable()
}
}
pub struct UnobstructedBlockPredicate {
pub offset: Option<Vector3<i32>>,
}
impl UnobstructedBlockPredicate {
pub const fn test<T: GenerationCache>(&self, _chunk: &T, _pos: &BlockPos) -> bool {
true
}
pub const fn test_world(&self, _world: &dyn BlockAccessor, _pos: &BlockPos) -> bool {
true
}
}
pub struct OffsetBlocksBlockPredicate {
@ -233,6 +382,7 @@ pub struct OffsetBlocksBlockPredicate {
}
impl OffsetBlocksBlockPredicate {
#[must_use]
pub fn get(&self, pos: &BlockPos) -> BlockPos {
if let Some(offset) = self.offset {
return pos.offset(offset);
@ -262,6 +412,25 @@ impl OffsetBlocksBlockPredicate {
let pos = self.get(pos);
GenerationCache::get_block_state(chunk, &pos.0).to_state()
}
pub fn get_id_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> BlockStateId {
let pos = self.get(pos);
world.get_block_state_id(&pos)
}
pub fn get_block_world(&self, world: &dyn BlockAccessor, pos: &BlockPos) -> &'static Block {
let pos = self.get(pos);
world.get_block(&pos)
}
pub fn get_state_world(
&self,
world: &dyn BlockAccessor,
pos: &BlockPos,
) -> &'static BlockState {
let pos = self.get(pos);
world.get_block_state(&pos)
}
}
pub enum MatchingBlocksWrapper {

View File

@ -13,7 +13,7 @@ use pumpkin_util::{
use super::noise::perlin::DoublePerlinNoiseSampler;
use crate::generation::block_predicate::BlockPredicate;
use crate::generation::proto_chunk::GenerationCache;
use crate::world::WorldPortalExt;
use crate::world::{BlockAccessor, WorldPortalExt};
pub enum BlockStateProvider {
Simple(SimpleStateProvider),
@ -43,6 +43,36 @@ impl BlockStateProvider {
}
}
pub fn get_state_for_world(
&self,
world: &dyn BlockAccessor,
random: &mut RandomGenerator,
pos: BlockPos,
) -> &'static BlockState {
match self {
Self::Simple(provider) => provider.get(pos),
Self::Weighted(provider) => provider.get(random),
Self::NoiseThreshold(provider) => provider.get(random, pos),
Self::NoiseProvider(provider) => provider.get(pos),
Self::DualNoise(provider) => provider.get(pos),
Self::Pillar(provider) => provider.get(pos),
Self::RandomizedInt(provider) => {
provider.source.get_state_for_world(world, random, pos)
}
Self::Rule(provider) => {
for rule in &provider.rules {
if rule.if_true.test_world(world, None, &pos) {
return rule.then.get_state_for_world(world, random, pos);
}
}
provider.fallback.as_ref().map_or_else(
|| world.get_block_state(&pos),
|f| f.get_state_for_world(world, random, pos),
)
}
}
}
pub fn get<T: GenerationCache>(
&self,
random: &mut RandomGenerator,
@ -157,6 +187,7 @@ pub struct PillarBlockStateProvider {
}
impl PillarBlockStateProvider {
#[must_use]
pub const fn get(&self, _pos: BlockPos) -> &'static BlockState {
// TODO: random axis
self.state
@ -171,6 +202,7 @@ pub struct DualNoiseBlockStateProvider {
}
impl DualNoiseBlockStateProvider {
#[must_use]
pub fn get(&self, pos: BlockPos) -> &'static BlockState {
let sampler = DoublePerlinNoiseSampler::new(
&mut RandomGenerator::Legacy(LegacyRand::from_seed(self.base.base.seed as u64)),
@ -226,6 +258,7 @@ pub struct SimpleStateProvider {
}
impl SimpleStateProvider {
#[must_use]
pub const fn get(&self, _pos: BlockPos) -> &'static BlockState {
self.state
}
@ -238,6 +271,7 @@ pub struct NoiseBlockStateProviderBase {
}
impl NoiseBlockStateProviderBase {
#[must_use]
pub fn get_noise(&self, pos: BlockPos) -> f64 {
let sampler = DoublePerlinNoiseSampler::new(
&mut RandomGenerator::Legacy(LegacyRand::from_seed(self.seed as u64)),
@ -260,6 +294,7 @@ pub struct NoiseBlockStateProvider {
}
impl NoiseBlockStateProvider {
#[must_use]
pub fn get(&self, pos: BlockPos) -> &'static BlockState {
let value = self.base.get_noise(pos);
Self::get_state_by_value(&self.states, value)

View File

@ -2,8 +2,8 @@
mod biome;
pub mod blender;
mod block_predicate;
mod block_state_provider;
pub mod block_predicate;
pub mod block_state_provider;
pub mod carver;
pub mod feature;
mod feature_order;

View File

@ -1042,7 +1042,7 @@ mod random_positions_and_hypot {
}
#[test]
#[expect(clippy::too_many_lines, clippy::large_stack_arrays)]
#[expect(clippy::too_many_lines)]
fn get_fluid_block_state() {
let (_, mut router, _, options) = create_aquifer(&PROTO_ROUTER);
let level = FluidLevel::new(0, &WATER_BLOCK);
@ -1634,7 +1634,7 @@ mod random_positions_and_hypot {
}
#[test]
#[expect(clippy::too_many_lines, clippy::large_stack_arrays)]
#[expect(clippy::too_many_lines)]
fn get_fluid_level() {
let (aquifer, mut router, mut height_estimator, env) = create_aquifer(&PROTO_ROUTER);
let values = [

View File

@ -6,8 +6,8 @@ use pumpkin_data::BlockStateId;
use pumpkin_data::block_properties::{
BlockProperties, ChestLikeProperties, ChestType, HorizontalFacing,
};
use pumpkin_data::chest_loot_table::get_chest_loot_table;
use pumpkin_data::entity::EntityPose;
use pumpkin_data::loot_table::get_loot_table;
use pumpkin_data::{Block, BlockDirection, translation};
use pumpkin_inventory::double::DoubleInventory;
use pumpkin_inventory::generic_container_screen_handler::{create_generic_9x3, create_generic_9x6};
@ -191,7 +191,7 @@ fn normal_use_chest_impl(args: &NormalUseArgs<'_>) -> BlockActionResult {
// Unpack deferred loot table on first open (non-spectator only).
if let Some(ref entity) = first_chest
&& let Some((loot_key, seed)) = entity.take_loot_table()
&& let Some(table) = get_chest_loot_table(&loot_key)
&& let Some(table) = get_loot_table(&loot_key)
&& let Some(inv) = entity.clone().get_inventory()
{
fill_chest_inventory(&inv, table, seed);

View File

@ -1,14 +1,26 @@
use std::sync::Arc;
use std::sync::Mutex;
use pumpkin_data::translation;
use pumpkin_data::{
Block, BlockDirection, BlockStateId, HorizontalFacingExt,
block_properties::{AttachFace, BlockProperties, GrindstoneLikeProperties},
};
use pumpkin_inventory::grindstone_screen_handler::GrindstoneScreenHandler;
use pumpkin_inventory::player::player_inventory::PlayerInventory;
use pumpkin_inventory::screen_handler::{
InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
};
use pumpkin_macros::pumpkin_block;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::text::TextComponent;
use pumpkin_world::inventory::SimpleInventory;
use pumpkin_world::world::BlockAccessor;
use crate::block::BlockBehaviour;
use crate::block::CanPlaceAtArgs;
use crate::block::{GetStateForNeighborUpdateArgs, OnPlaceArgs};
use crate::block::registry::BlockActionResult;
use crate::block::{GetStateForNeighborUpdateArgs, NormalUseArgs, OnPlaceArgs};
use super::abstract_wall_mounting::WallMountedBlock;
@ -16,6 +28,18 @@ use super::abstract_wall_mounting::WallMountedBlock;
pub struct GrindstoneBlock;
impl BlockBehaviour for GrindstoneBlock {
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
args.player.increment_stat(
pumpkin_data::statistic::StatisticCategory::Custom,
pumpkin_data::statistic::CustomStatistic::InteractWithGrindstone as i32,
1,
);
args.player
.open_handled_screen(&GrindstoneScreenFactory, Some(*args.position));
BlockActionResult::Success
}
fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
let mut props =
GrindstoneLikeProperties::from_state_id(args.block.default_state.id, args.block);
@ -61,3 +85,27 @@ impl WallMountedBlock for GrindstoneBlock {
}
}
}
struct GrindstoneScreenFactory;
impl ScreenHandlerFactory for GrindstoneScreenFactory {
fn create_screen_handler(
&self,
sync_id: u8,
player_inventory: &Arc<PlayerInventory>,
_player: &dyn InventoryPlayer,
) -> Option<SharedScreenHandler> {
let inventory = Arc::new(SimpleInventory::new(3));
let handler = GrindstoneScreenHandler::new(sync_id, player_inventory, inventory);
let concrete_arc = Arc::new(Mutex::new(handler));
Some(concrete_arc as SharedScreenHandler)
}
fn get_display_name(&self) -> TextComponent {
pumpkin_macros::translate_cross!(
translation::java::CONTAINER_GRINDSTONE_TITLE,
translation::bedrock::TILE_GRINDSTONE_NAME
)
}
}

View File

@ -892,10 +892,10 @@ impl TrialSpawner {
) {
let mut dropped_any = false;
if let Some(key) = ejecting_loot_table
&& let Some(loot_table) = pumpkin_data::chest_loot_table::get_chest_loot_table(key)
&& let Some(loot_table) = pumpkin_data::loot_table::get_loot_table(key)
{
let seed = rand::random::<i64>();
let items = crate::world::loot::generate_chest_loot(loot_table, seed);
let items = crate::world::loot::generate_loot(loot_table, seed);
for stack in items {
world.drop_stack(&spawner_pos, stack);
dropped_any = true;

View File

@ -7,7 +7,7 @@ use pumpkin_util::random::{RandomGenerator, get_seed, xoroshiro128::Xoroshiro};
use crate::entity::experience_orb::ExperienceOrbEntity;
use crate::entity::player::Player;
use crate::world::World;
use crate::world::loot::{LootContextParameters, LootTableExt};
use crate::world::loot::LootContextParameters;
use std::sync::Arc;
pub mod blocks;
@ -418,10 +418,12 @@ pub fn drop_loot(
block: &Block,
pos: &BlockPos,
experience: bool,
params: LootContextParameters,
params: &LootContextParameters,
) {
if let Some(loot_table) = &block.loot_table {
let items = loot_table.get_loot(params);
let key = format!("minecraft:blocks/{}", block.name);
if let Some(loot_table) = pumpkin_data::loot_table::get_loot_table(&key) {
let seed: i64 = rand::random();
let items = crate::world::loot::generate_loot_with_context(loot_table, seed, params);
if !items.is_empty() {
let mut event = crate::plugin::block::block_drop_item::BlockDropItemEvent {
block_pos: *pos,

View File

@ -6,7 +6,6 @@ use crate::command::context::command_context::CommandContext;
use crate::command::errors::error_types::CommandErrorType;
use crate::command::node::dispatcher::CommandDispatcher;
use crate::command::node::{CommandExecutor, CommandExecutorResult};
use crate::world::loot::LootTableExt;
use pumpkin_data::translation;
use pumpkin_util::PermissionLvl;
use pumpkin_util::permission::{Permission, PermissionDefault, PermissionRegistry};
@ -42,7 +41,10 @@ enum Target {
enum Source {
Loot,
Kill,
Mine { has_tool: bool },
Mine {
#[allow(dead_code)]
has_tool: bool,
},
}
struct LootExecutor {
@ -100,11 +102,10 @@ impl CommandExecutor for LootExecutor {
format!("minecraft:{loot_table_str}")
};
let chest_table =
pumpkin_data::chest_loot_table::get_chest_loot_table(&formatted_key);
if let Some(table) = chest_table {
let loot_table = pumpkin_data::loot_table::get_loot_table(&formatted_key);
if let Some(table) = loot_table {
let seed: i64 = rand::random();
stacks = crate::world::loot::generate_chest_loot(table, seed);
stacks = crate::world::loot::generate_loot(table, seed);
} else {
return Err(ERROR_INVALID_LOOT_TABLE
.create_without_context(TextComponent::text(loot_table_str.to_string())));
@ -114,13 +115,12 @@ impl CommandExecutor for LootExecutor {
let target_entities = EntityArgumentType::get_entities(context, "target_entity")?;
let mut has_loot = false;
for entity in target_entities {
if let Some(loot_table) = &entity.get_entity().entity_type.loot_table {
let resource_name = entity.get_entity().entity_type.resource_name;
let key = format!("minecraft:entities/{resource_name}");
if let Some(loot_table) = pumpkin_data::loot_table::get_loot_table(&key) {
has_loot = true;
let params = crate::world::loot::LootContextParameters {
world_time: context.world().level_info.load().day_time as u64,
..Default::default()
};
stacks.extend(loot_table.get_loot(params));
let seed: i64 = rand::random();
stacks.extend(crate::world::loot::generate_loot(loot_table, seed));
}
}
if !has_loot {
@ -129,32 +129,16 @@ impl CommandExecutor for LootExecutor {
.create_without_context(TextComponent::text(entity_name)));
}
}
Source::Mine { has_tool } => {
Source::Mine { has_tool: _ } => {
let pos = BlockPosArgumentType::get_block_pos(context, "mine_pos")
.or_else(|_| BlockPosArgumentType::get_block_pos(context, "pos"))?;
let world = context.world();
let block = world.get_block(&pos);
let key = format!("minecraft:blocks/{}", block.name);
if let Some(loot_table) = &block.loot_table {
let tool_item = if has_tool {
let tool_str = StringArgumentType::get(context, "tool")?;
let key = tool_str.strip_prefix("minecraft:").unwrap_or(tool_str);
pumpkin_data::item::Item::from_registry_key(key)
} else {
None
};
let tool_stack =
tool_item.map(|item| pumpkin_data::item_stack::ItemStack::new(1, item));
let params = crate::world::loot::LootContextParameters {
block_state: Some(world.get_block_state(&pos)),
tool: tool_stack,
world_time: world.level_info.load().day_time as u64,
..Default::default()
};
stacks.extend(loot_table.get_loot(params));
if let Some(loot_table) = pumpkin_data::loot_table::get_loot_table(&key) {
let seed: i64 = rand::random();
stacks.extend(crate::world::loot::generate_loot(loot_table, seed));
}
}
}

View File

@ -1,6 +1,5 @@
use pumpkin_data::enchantment::LevelBasedValue;
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.AddValue`.
#[derive(Clone, Debug, PartialEq)]
pub struct AddValue {
pub value: LevelBasedValue,

View File

@ -1,6 +1,5 @@
use pumpkin_data::enchantment::EnchantmentEntityEffect;
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.AllOf`.
#[derive(Clone, Debug, PartialEq)]
pub struct AllOf<'a> {
pub effects: &'a [EnchantmentEntityEffect],
@ -12,3 +11,18 @@ impl<'a> AllOf<'a> {
Self { effects }
}
}
impl super::EnchantmentEntityEffectExt for AllOf<'_> {
fn apply(
&self,
world: &std::sync::Arc<crate::world::World>,
enchantment_level: i32,
owner: Option<&std::sync::Arc<crate::entity::player::Player>>,
entity: Option<&crate::entity::Entity>,
position: pumpkin_util::math::vector3::Vector3<f64>,
) {
for effect in self.effects {
effect.apply(world, enchantment_level, owner, entity, position);
}
}
}

View File

@ -0,0 +1,110 @@
use std::sync::Arc;
use std::sync::atomic::Ordering;
use pumpkin_data::enchantment::LevelBasedValue;
use pumpkin_util::math::vector3::Vector3;
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that applies a velocity impulse to an entity.
#[derive(Clone, Debug, PartialEq)]
pub struct ApplyEntityImpulse {
pub direction: Vector3<f64>,
pub coordinate_scale: Vector3<f64>,
pub magnitude: LevelBasedValue,
}
impl ApplyEntityImpulse {
#[must_use]
pub const fn new(
direction: Vector3<f64>,
coordinate_scale: Vector3<f64>,
magnitude: LevelBasedValue,
) -> Self {
Self {
direction,
coordinate_scale,
magnitude,
}
}
/// Computes local coordinate rotation based on entity yaw, pitch, and local offset.
#[must_use]
pub fn compute_local_direction(yaw: f32, pitch: f32, local: Vector3<f64>) -> Vector3<f64> {
let y_rot_rad = (yaw + 90.0).to_radians();
let x_rot_rad = (-pitch).to_radians();
let x_rot_90_rad = (-pitch + 90.0).to_radians();
let f = f64::from(y_rot_rad.cos());
let f1 = f64::from(y_rot_rad.sin());
let f2 = f64::from(x_rot_rad.cos());
let f3 = f64::from(x_rot_rad.sin());
let f4 = f64::from(x_rot_90_rad.cos());
let f5 = f64::from(x_rot_90_rad.sin());
let v1 = Vector3::new(f * f2, f3, f1 * f2);
let v2 = Vector3::new(f * f4, f5, f1 * f4);
let v3 = v1.cross(&v2) * -1.0;
let dx = v3.x * local.x + v2.x * local.y + v1.x * local.z;
let dy = v3.y * local.x + v2.x * local.y + v1.y * local.z;
let dz = v3.z * local.x + v2.x * local.y + v1.z * local.z;
Vector3::new(dx, dy, dz)
}
pub fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
) {
let Some(entity) = entity else {
return;
};
let yaw = entity.yaw.load();
let pitch = entity.pitch.load();
let local_dir = Self::compute_local_direction(yaw, pitch, self.direction);
let scale = self.coordinate_scale;
let mag = f64::from(self.magnitude.calculate(enchantment_level));
let impulse = Vector3::new(
local_dir.x * scale.x * mag,
local_dir.y * scale.y * mag,
local_dir.z * scale.z * mag,
);
let current_velocity = entity.velocity.load();
let new_velocity = current_velocity + impulse;
entity.velocity.store(new_velocity);
entity.velocity_dirty.store(true, Ordering::SeqCst);
entity.send_velocity();
let player = owner
.cloned()
.or_else(|| world.get_player_by_id(entity.entity_id));
if let Some(player) = player {
player.set_velocity(new_velocity);
}
}
}
impl EnchantmentEntityEffectExt for ApplyEntityImpulse {
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
_position: Vector3<f64>,
) {
self.apply(world, enchantment_level, owner, entity);
}
}

View File

@ -0,0 +1,52 @@
use std::sync::Arc;
use pumpkin_data::enchantment::LevelBasedValue;
use pumpkin_util::math::vector3::Vector3;
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that applies food exhaustion to a player.
#[derive(Clone, Debug, PartialEq)]
pub struct ApplyExhaustion {
pub amount: LevelBasedValue,
}
impl ApplyExhaustion {
#[must_use]
pub const fn new(amount: LevelBasedValue) -> Self {
Self { amount }
}
pub fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
) {
let player = owner
.cloned()
.or_else(|| entity.and_then(|e| world.get_player_by_id(e.entity_id)));
if let Some(player) = player {
let exhaustion = self.amount.calculate(enchantment_level);
player.add_exhaustion(exhaustion);
}
}
}
impl EnchantmentEntityEffectExt for ApplyExhaustion {
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
_position: Vector3<f64>,
) {
self.apply(world, enchantment_level, owner, entity);
}
}

View File

@ -0,0 +1,113 @@
use std::sync::Arc;
use pumpkin_data::effect::StatusEffect;
use pumpkin_data::enchantment::LevelBasedValue;
use pumpkin_data::potion::Effect;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::random::{RandomGenerator, RandomImpl, get_seed, xoroshiro128::Xoroshiro};
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that applies a status effect.
#[derive(Clone, Debug, PartialEq)]
pub struct ApplyMobEffect {
pub to_apply: Vec<&'static StatusEffect>,
pub min_duration: LevelBasedValue,
pub max_duration: LevelBasedValue,
pub min_amplifier: LevelBasedValue,
pub max_amplifier: LevelBasedValue,
}
impl ApplyMobEffect {
#[must_use]
pub const fn new(
to_apply: Vec<&'static StatusEffect>,
min_duration: LevelBasedValue,
max_duration: LevelBasedValue,
min_amplifier: LevelBasedValue,
max_amplifier: LevelBasedValue,
) -> Self {
Self {
to_apply,
min_duration,
max_duration,
min_amplifier,
max_amplifier,
}
}
pub fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
_owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
) {
if self.to_apply.is_empty() {
return;
}
let Some(entity) = entity else {
return;
};
let mut rng = RandomGenerator::Xoroshiro(Xoroshiro::from_seed(get_seed()));
let selected_idx = (rng.next_f32() * self.to_apply.len() as f32) as usize;
let selected = self.to_apply[selected_idx.min(self.to_apply.len() - 1)];
let min_dur = self.min_duration.calculate(enchantment_level);
let max_dur = self.max_duration.calculate(enchantment_level);
let dur_secs = if (max_dur - min_dur).abs() < f32::EPSILON || min_dur >= max_dur {
min_dur
} else {
rng.next_f32().mul_add(max_dur - min_dur, min_dur)
};
let ticks = (dur_secs * 20.0).round() as i32;
let min_amp = self.min_amplifier.calculate(enchantment_level);
let max_amp = self.max_amplifier.calculate(enchantment_level);
let amp_f = if (max_amp - min_amp).abs() < f32::EPSILON || min_amp >= max_amp {
min_amp
} else {
rng.next_f32().mul_add(max_amp - min_amp, min_amp)
};
let amplifier = (amp_f.round() as i32).max(0) as u8;
let effect = Effect {
effect_type: selected,
duration: ticks,
amplifier,
ambient: false,
show_particles: true,
show_icon: true,
blend: false,
};
let target_player = world.get_player_by_id(entity.entity_id);
if let Some(target_player) = target_player {
target_player.add_effect(effect);
} else if let Some(living) = world
.get_entity_by_id(entity.entity_id)
.as_deref()
.and_then(crate::entity::EntityBase::get_living_entity)
{
living.add_effect(effect);
}
}
}
impl EnchantmentEntityEffectExt for ApplyMobEffect {
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
_position: Vector3<f64>,
) {
self.apply(world, enchantment_level, owner, entity);
}
}

View File

@ -0,0 +1,52 @@
use std::sync::Arc;
use pumpkin_data::enchantment::LevelBasedValue;
use pumpkin_util::math::vector3::Vector3;
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that alters item damage.
#[derive(Clone, Debug, PartialEq)]
pub struct ChangeItemDamage {
pub amount: LevelBasedValue,
}
impl ChangeItemDamage {
#[must_use]
pub const fn new(amount: LevelBasedValue) -> Self {
Self { amount }
}
pub fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
) {
let player = owner
.cloned()
.or_else(|| entity.and_then(|e| world.get_player_by_id(e.entity_id)));
if let Some(player) = player {
let change = self.amount.calculate(enchantment_level) as i32;
player.damage_held_item(change);
}
}
}
impl EnchantmentEntityEffectExt for ChangeItemDamage {
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
_position: Vector3<f64>,
) {
self.apply(world, enchantment_level, owner, entity);
}
}

View File

@ -1,19 +1,87 @@
use pumpkin_data::enchantment::LevelBasedValue;
use std::sync::Arc;
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.DamageEntity`.
use pumpkin_data::damage::DamageType;
use pumpkin_data::enchantment::LevelBasedValue;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::random::{RandomGenerator, RandomImpl, get_seed, xoroshiro128::Xoroshiro};
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that damages an entity.
#[derive(Clone, Debug, PartialEq)]
pub struct DamageEntity {
pub damage: LevelBasedValue,
pub min_damage: LevelBasedValue,
pub max_damage: LevelBasedValue,
pub damage_type: Option<&'static DamageType>,
}
impl DamageEntity {
#[must_use]
pub const fn new(damage: LevelBasedValue) -> Self {
Self { damage }
pub const fn new(
min_damage: LevelBasedValue,
max_damage: LevelBasedValue,
damage_type: Option<&'static DamageType>,
) -> Self {
Self {
min_damage,
max_damage,
damage_type,
}
}
#[must_use]
pub fn calculate_damage(&self, level: i32) -> f32 {
self.damage.calculate(level)
pub fn calculate_damage(&self, level: i32, rng: &mut impl RandomImpl) -> f32 {
let min = self.min_damage.calculate(level);
let max = self.max_damage.calculate(level);
if (max - min).abs() < f32::EPSILON || min >= max {
min
} else {
rng.next_f32().mul_add(max - min, min)
}
}
pub fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
) {
let Some(entity) = entity else {
return;
};
let mut rng = RandomGenerator::Xoroshiro(Xoroshiro::from_seed(get_seed()));
let damage = self.calculate_damage(enchantment_level, &mut rng);
let damage_type = self.damage_type.copied().unwrap_or(DamageType::GENERIC);
let target_entity = world
.get_player_by_id(entity.entity_id)
.map(|p| p as Arc<dyn crate::entity::EntityBase>)
.or_else(|| world.get_entity_by_id(entity.entity_id));
if let Some(target) = target_entity {
let caller = owner.map_or_else(
|| target.as_ref(),
|o| o.as_ref() as &dyn crate::entity::EntityBase,
);
target.damage(caller, damage, damage_type);
}
}
}
impl EnchantmentEntityEffectExt for DamageEntity {
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
_position: Vector3<f64>,
) {
self.apply(world, enchantment_level, owner, entity);
}
}

View File

@ -0,0 +1,283 @@
use std::sync::Arc;
use pumpkin_data::enchantment::EnchantmentEntityEffect;
use pumpkin_util::math::vector3::Vector3;
use super::{
AllOf, ApplyEntityImpulse, ApplyExhaustion, ApplyMobEffect, ChangeItemDamage, DamageEntity,
ExplodeEffect, Ignite, PlaySound, ReplaceBlock, ReplaceDisk, RunFunction, SetBlockProperties,
SpawnParticlesEffect, SummonEntityEffect,
};
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Extension trait for enchantment entity effects.
pub trait EnchantmentEntityEffectExt {
/// Applies this entity effect at the given position in the world.
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
position: Vector3<f64>,
);
}
impl EnchantmentEntityEffectExt for EnchantmentEntityEffect {
#[allow(clippy::too_many_lines)]
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
position: Vector3<f64>,
) {
match self {
Self::Ignite { duration } => {
EnchantmentEntityEffectExt::apply(
&Ignite::new(duration.clone()),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::DamageEntity {
min_damage,
max_damage,
damage_type,
} => {
EnchantmentEntityEffectExt::apply(
&DamageEntity::new(min_damage.clone(), max_damage.clone(), *damage_type),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::ChangeItemDamage { amount } => {
EnchantmentEntityEffectExt::apply(
&ChangeItemDamage::new(amount.clone()),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::PlaySound { sound } => {
EnchantmentEntityEffectExt::apply(
&PlaySound::new(sound),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::ReplaceBlock {
offset_x,
offset_y,
offset_z,
trigger_game_event,
} => {
let offset = Vector3::new(*offset_x, *offset_y, *offset_z);
EnchantmentEntityEffectExt::apply(
&ReplaceBlock::new(offset, *trigger_game_event),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::SetBlockProperties {
properties,
offset_x,
offset_y,
offset_z,
trigger_game_event,
} => {
let offset = Vector3::new(*offset_x, *offset_y, *offset_z);
let props = properties
.iter()
.map(|(k, v)| ((*k).to_string(), (*v).to_string()))
.collect();
EnchantmentEntityEffectExt::apply(
&SetBlockProperties::new(props, offset, *trigger_game_event),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::ReplaceDisk {
radius,
height,
offset_x,
offset_y,
offset_z,
predicate,
block_state,
trigger_game_event,
} => {
let offset = Vector3::new(*offset_x, *offset_y, *offset_z);
EnchantmentEntityEffectExt::apply(
&ReplaceDisk {
radius: radius.clone(),
height: height.clone(),
offset,
predicate: predicate.clone(),
block_state,
trigger_game_event: *trigger_game_event,
},
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::SummonEntity {
entity_types,
join_team,
} => {
EnchantmentEntityEffectExt::apply(
&SummonEntityEffect::new(entity_types.to_vec(), *join_team),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::SpawnParticles {
particle,
horizontal_position,
vertical_position,
horizontal_velocity,
vertical_velocity,
speed,
} => {
let spawn_particles = SpawnParticlesEffect::new(
*particle,
*horizontal_position,
*vertical_position,
horizontal_velocity.clone(),
vertical_velocity.clone(),
speed.clone(),
);
EnchantmentEntityEffectExt::apply(
&spawn_particles,
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::RunFunction { function } => {
EnchantmentEntityEffectExt::apply(
&RunFunction::new(*function),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::ApplyExhaustion { amount } => {
EnchantmentEntityEffectExt::apply(
&ApplyExhaustion::new(amount.clone()),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::ApplyImpulse {
direction,
coordinate_scale,
magnitude,
} => {
EnchantmentEntityEffectExt::apply(
&ApplyEntityImpulse::new(*direction, *coordinate_scale, magnitude.clone()),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::ApplyMobEffect {
to_apply,
min_duration,
max_duration,
min_amplifier,
max_amplifier,
} => {
EnchantmentEntityEffectExt::apply(
&ApplyMobEffect::new(
to_apply.to_vec(),
min_duration.clone(),
max_duration.clone(),
min_amplifier.clone(),
max_amplifier.clone(),
),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::Explode {
offset_x,
offset_y,
offset_z,
radius,
create_fire,
..
} => {
EnchantmentEntityEffectExt::apply(
&ExplodeEffect::new(
false,
None,
None,
None,
Vector3::new(*offset_x, *offset_y, *offset_z),
radius.clone(),
*create_fire,
crate::world::ExplosionInteraction::None,
None,
None,
None,
),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::AllOf(effects) => {
EnchantmentEntityEffectExt::apply(
&AllOf::new(effects),
world,
enchantment_level,
owner,
entity,
position,
);
}
Self::Other => {}
}
}
}

View File

@ -7,7 +7,6 @@ use pumpkin_util::math::vector3::Vector3;
use crate::world::ExplosionInteraction;
/// Enchantment entity effect that produces an explosion at an offset position.
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.ExplodeEffect`.
#[derive(Clone, Debug, PartialEq)]
pub struct ExplodeEffect {
pub attribute_to_user: bool,
@ -66,3 +65,26 @@ impl ExplodeEffect {
.map(|kb| kb.calculate(level))
}
}
impl super::EnchantmentEntityEffectExt for ExplodeEffect {
fn apply(
&self,
world: &std::sync::Arc<crate::world::World>,
enchantment_level: i32,
_owner: Option<&std::sync::Arc<crate::entity::player::Player>>,
_entity: Option<&crate::entity::Entity>,
position: Vector3<f64>,
) {
let r = self.calculate_radius(enchantment_level);
let center = position + self.offset;
world.explode(
center,
r,
if self.create_fire {
self.block_interaction
} else {
ExplosionInteraction::None
},
);
}
}

View File

@ -1,8 +1,14 @@
use crate::entity::{Entity, EntityBase};
use std::sync::Arc;
use pumpkin_data::enchantment::LevelBasedValue;
use pumpkin_util::math::vector3::Vector3;
use super::EnchantmentEntityEffectExt;
use crate::entity::player::Player;
use crate::entity::{Entity, EntityBase};
use crate::world::World;
/// Enchantment entity effect that sets an entity on fire for a duration calculated from the level.
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.Ignite`.
#[derive(Clone, Debug, PartialEq)]
pub struct Ignite {
pub duration: LevelBasedValue,
@ -15,9 +21,24 @@ impl Ignite {
}
/// Applies the ignite effect to an entity for the given enchantment level.
pub fn apply(&self, level: i32, entity: &Entity) {
pub fn apply_to_entity(&self, level: i32, entity: &Entity) {
let seconds = self.duration.calculate(level);
entity.set_on_fire_for(seconds);
entity.set_on_fire(true);
}
}
impl EnchantmentEntityEffectExt for Ignite {
fn apply(
&self,
_world: &Arc<World>,
enchantment_level: i32,
_owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
_position: Vector3<f64>,
) {
if let Some(entity) = entity {
self.apply_to_entity(enchantment_level, entity);
}
}
}

View File

@ -1,21 +1,41 @@
pub mod add_value;
pub mod all_of;
pub mod apply_entity_impulse;
pub mod apply_exhaustion;
pub mod apply_mob_effect;
pub mod change_item_damage;
pub mod damage_entity;
pub mod entity_effect;
pub mod explode;
pub mod ignite;
pub mod multiply_value;
pub mod play_sound;
pub mod remove_binomial;
pub mod replace_block;
pub mod replace_disk;
pub mod run_function;
pub mod set_block_properties;
pub mod set_value;
pub mod spawn_particles;
pub mod summon_entity;
pub use add_value::AddValue;
pub use all_of::AllOf;
pub use apply_entity_impulse::ApplyEntityImpulse;
pub use apply_exhaustion::ApplyExhaustion;
pub use apply_mob_effect::ApplyMobEffect;
pub use change_item_damage::ChangeItemDamage;
pub use damage_entity::DamageEntity;
pub use entity_effect::EnchantmentEntityEffectExt;
pub use explode::ExplodeEffect;
pub use ignite::Ignite;
pub use multiply_value::MultiplyValue;
pub use play_sound::PlaySound;
pub use remove_binomial::RemoveBinomial;
pub use replace_block::ReplaceBlock;
pub use replace_disk::ReplaceDisk;
pub use run_function::RunFunction;
pub use set_block_properties::SetBlockProperties;
pub use set_value::SetValue;
pub use spawn_particles::SpawnParticlesEffect;
pub use summon_entity::SummonEntityEffect;

View File

@ -1,6 +1,5 @@
use pumpkin_data::enchantment::LevelBasedValue;
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.MultiplyValue`.
#[derive(Clone, Debug, PartialEq)]
pub struct MultiplyValue {
pub factor: LevelBasedValue,

View File

@ -1,4 +1,13 @@
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.PlaySound`.
use std::sync::Arc;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_util::math::vector3::Vector3;
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PlaySound {
pub sound: &'static str,
@ -10,3 +19,18 @@ impl PlaySound {
Self { sound }
}
}
impl EnchantmentEntityEffectExt for PlaySound {
fn apply(
&self,
world: &Arc<World>,
_enchantment_level: i32,
_owner: Option<&Arc<Player>>,
_entity: Option<&Entity>,
position: Vector3<f64>,
) {
if let Some(snd) = Sound::from_name(self.sound) {
world.play_sound_fine(snd, SoundCategory::Players, &position, 1.0, 1.0);
}
}
}

View File

@ -1,6 +1,5 @@
use pumpkin_data::enchantment::LevelBasedValue;
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.RemoveBinomial`.
#[derive(Clone, Debug, PartialEq)]
pub struct RemoveBinomial {
pub chance: LevelBasedValue,

View File

@ -1,9 +1,15 @@
use std::sync::Arc;
use pumpkin_data::game_event::GameEvent;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that replaces a block at an offset position.
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.ReplaceBlock`.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ReplaceBlock {
pub offset: Vector3<i32>,
@ -31,3 +37,19 @@ impl ReplaceBlock {
)
}
}
impl EnchantmentEntityEffectExt for ReplaceBlock {
fn apply(
&self,
world: &Arc<World>,
_enchantment_level: i32,
_owner: Option<&Arc<Player>>,
_entity: Option<&Entity>,
position: Vector3<f64>,
) {
let target = self.target_position(position);
if let Some(event) = self.trigger_game_event {
world.emit_game_event(event.name(), target.to_centered_f64());
}
}
}

View File

@ -0,0 +1,174 @@
use std::sync::Arc;
use pumpkin_data::BlockState;
use pumpkin_data::enchantment::{LevelBasedValue, ReplaceDiskPredicate};
use pumpkin_data::game_event::GameEvent;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::world::BlockFlags;
use crate::world::World;
/// Enchantment entity effect that replaces a disk of blocks around an offset position.
pub struct ReplaceDisk {
pub radius: LevelBasedValue,
pub height: LevelBasedValue,
pub offset: Vector3<i32>,
pub predicate: Option<ReplaceDiskPredicate>,
pub block_state: &'static BlockState,
pub trigger_game_event: Option<GameEvent>,
}
pub trait ReplaceDiskPredicateExt {
fn test_world(&self, world: &World, pos: &BlockPos) -> bool;
}
impl ReplaceDiskPredicateExt for ReplaceDiskPredicate {
fn test_world(&self, world: &World, pos: &BlockPos) -> bool {
match self {
Self::MatchingBlockTag { offset, tag } => {
let test_pos = pos.offset(*offset);
let state_id = world.get_block_state_id(&test_pos);
state_id.to_block_id().has_tag(**tag)
}
Self::MatchingBlocks { offset, blocks } => {
let test_pos = pos.offset(*offset);
let block = world.get_block(&test_pos);
blocks.iter().any(|b| {
let stripped = b.strip_prefix("minecraft:").unwrap_or(b);
stripped == block.name
})
}
Self::MatchingFluids { offset, fluids } => {
let test_pos = pos.offset(*offset);
let (_, fluid) = world.get_block_and_fluid(&test_pos);
fluids.iter().any(|f| {
let stripped = f.strip_prefix("minecraft:").unwrap_or(f);
stripped == fluid.name
})
}
Self::Unobstructed => true,
Self::AllOf(predicates) => predicates.iter().all(|p| p.test_world(world, pos)),
}
}
}
impl ReplaceDisk {
#[must_use]
pub const fn new(
radius: LevelBasedValue,
height: LevelBasedValue,
offset: Vector3<i32>,
predicate: Option<ReplaceDiskPredicate>,
block_state: &'static BlockState,
trigger_game_event: Option<GameEvent>,
) -> Self {
Self {
radius,
height,
offset,
predicate,
block_state,
trigger_game_event,
}
}
#[must_use]
pub const fn simple(
radius: LevelBasedValue,
height: LevelBasedValue,
offset: Vector3<i32>,
block_state: &'static BlockState,
trigger_game_event: Option<GameEvent>,
) -> Self {
Self {
radius,
height,
offset,
predicate: None,
block_state,
trigger_game_event,
}
}
#[must_use]
pub fn calculate_radius(&self, level: i32) -> f32 {
self.radius.calculate(level)
}
#[must_use]
pub fn calculate_height(&self, level: i32) -> f32 {
self.height.calculate(level)
}
#[must_use]
pub fn center_position(&self, origin: Vector3<f64>) -> BlockPos {
BlockPos::containing_vec(origin).offset(self.offset)
}
#[must_use]
pub fn is_in_radius(pos: &BlockPos, position: Vector3<f64>, dist: i32) -> bool {
pos.dist_to_center_sqr(position.x, f64::from(pos.0.y) + 0.5, position.z)
< f64::from(dist * dist)
}
/// Iterates through all candidate block positions within the disk region.
pub fn iterate_blocks(
&self,
level: i32,
position: Vector3<f64>,
) -> impl Iterator<Item = BlockPos> {
let center_block = self.center_position(position);
let dist = self.radius.calculate(level) as i32;
let height = self.height.calculate(level) as i32;
let start = center_block.offset(Vector3::new(-dist, 0, -dist));
let end = center_block.offset(Vector3::new(dist, (height - 1).min(0), dist));
BlockPos::between_closed(start, end)
.filter(move |pos| Self::is_in_radius(pos, position, dist))
}
/// Applies the replace disk effect on the given world and position.
pub fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
_entity: Option<&crate::entity::Entity>,
position: Vector3<f64>,
) {
let mut changed = false;
for pos in self.iterate_blocks(enchantment_level, position) {
let passes_predicate = self
.predicate
.as_ref()
.is_none_or(|p| p.test_world(world.as_ref(), &pos));
if !passes_predicate {
continue;
}
let new_state = self.block_state;
let old_state_id = world.set_block_state(&pos, new_state.id, BlockFlags::NOTIFY_ALL);
if old_state_id != new_state.id {
changed = true;
if let Some(event) = self.trigger_game_event {
world.emit_game_event(event.name(), pos.to_centered_f64());
}
}
}
if changed {
world.flush_block_updates();
}
}
}
impl super::EnchantmentEntityEffectExt for ReplaceDisk {
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
_owner: Option<&Arc<crate::entity::player::Player>>,
entity: Option<&crate::entity::Entity>,
position: Vector3<f64>,
) {
self.apply(world, enchantment_level, entity, position);
}
}

View File

@ -0,0 +1,90 @@
use std::sync::Arc;
use pumpkin_util::math::vector2::Vector2;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::text::TextComponent;
use super::EnchantmentEntityEffectExt;
use crate::command::CommandSender;
use crate::command::context::command_source::CommandSource;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that executes a datapack function.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RunFunction {
pub function: String,
}
impl RunFunction {
#[must_use]
pub fn new(function: impl Into<String>) -> Self {
Self {
function: function.into(),
}
}
pub fn apply(
&self,
world: &Arc<World>,
position: Vector3<f64>,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
) {
let Some(server) = world.server.upgrade() else {
return;
};
let rotation = entity.map_or_else(Vector2::default, |e| {
Vector2::new(e.yaw.load(), e.pitch.load())
});
let source = owner.map_or_else(
|| {
let mut src = CommandSource::new(
CommandSender::Console,
world.clone(),
None,
position,
rotation,
"Enchantment".to_string(),
TextComponent::text("Enchantment"),
server.clone(),
);
src.silent = true;
src
},
|player| {
let mut src = player.get_command_source(&server);
src.position = position;
src.rotation = rotation;
src.silent = true;
src
},
);
if let Err(err) = server
.datapack_manager
.execute_function(&server, &source, &self.function)
{
tracing::error!(
"Enchantment run_function effect failed for non-existent function {}: {err}",
self.function
);
}
}
}
impl EnchantmentEntityEffectExt for RunFunction {
fn apply(
&self,
world: &Arc<World>,
_enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
position: Vector3<f64>,
) {
self.apply(world, position, owner, entity);
}
}

View File

@ -0,0 +1,72 @@
use std::sync::Arc;
use pumpkin_data::game_event::GameEvent;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that sets block properties at an offset position.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SetBlockProperties {
pub properties: Vec<(String, String)>,
pub offset: Vector3<i32>,
pub trigger_game_event: Option<GameEvent>,
}
impl SetBlockProperties {
#[must_use]
pub const fn new(
properties: Vec<(String, String)>,
offset: Vector3<i32>,
trigger_game_event: Option<GameEvent>,
) -> Self {
Self {
properties,
offset,
trigger_game_event,
}
}
#[must_use]
pub const fn target_position(&self, origin: Vector3<f64>) -> BlockPos {
let base_x = origin.x.floor() as i32;
let base_y = origin.y.floor() as i32;
let base_z = origin.z.floor() as i32;
BlockPos::new(
base_x + self.offset.x,
base_y + self.offset.y,
base_z + self.offset.z,
)
}
pub fn apply(
&self,
world: &Arc<World>,
_enchantment_level: i32,
_owner: Option<&Arc<Player>>,
_entity: Option<&Entity>,
position: Vector3<f64>,
) {
let target = self.target_position(position);
if let Some(event) = self.trigger_game_event {
world.emit_game_event(event.name(), target.to_centered_f64());
}
}
}
impl EnchantmentEntityEffectExt for SetBlockProperties {
fn apply(
&self,
world: &Arc<World>,
enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
position: Vector3<f64>,
) {
self.apply(world, enchantment_level, owner, entity, position);
}
}

View File

@ -1,6 +1,5 @@
use pumpkin_data::enchantment::LevelBasedValue;
/// Matches vanilla `net.minecraft.world.item.enchantment.effects.SetValue`.
#[derive(Clone, Debug, PartialEq)]
pub struct SetValue {
pub value: LevelBasedValue,

View File

@ -0,0 +1,110 @@
use std::sync::Arc;
pub use pumpkin_data::enchantment::{PositionSource, PositionSourceType, VelocitySource};
use pumpkin_data::particle::Particle;
use pumpkin_util::math::float_provider::FloatProvider;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::random::{RandomGenerator, get_seed, xoroshiro128::Xoroshiro};
use super::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::player::Player;
use crate::world::World;
/// Enchantment entity effect that spawns particles.
#[derive(Clone, Debug, PartialEq)]
pub struct SpawnParticlesEffect {
pub particle: Particle,
pub horizontal_position: PositionSource,
pub vertical_position: PositionSource,
pub horizontal_velocity: VelocitySource,
pub vertical_velocity: VelocitySource,
pub speed: FloatProvider,
}
impl SpawnParticlesEffect {
#[must_use]
pub const fn new(
particle: Particle,
horizontal_position: PositionSource,
vertical_position: PositionSource,
horizontal_velocity: VelocitySource,
vertical_velocity: VelocitySource,
speed: FloatProvider,
) -> Self {
Self {
particle,
horizontal_position,
vertical_position,
horizontal_velocity,
vertical_velocity,
speed,
}
}
pub fn apply(&self, world: &Arc<World>, position: Vector3<f64>, entity: Option<&Entity>) {
let (bb_width, bb_height, movement) = entity.map_or_else(
|| (0.6f32, 1.8f32, Vector3::new(0.0, 0.0, 0.0)),
|entity| {
let bb = entity.bounding_box.load();
let width = (bb.max.x - bb.min.x) as f32;
let height = (bb.max.y - bb.min.y) as f32;
let vel = entity.velocity.load();
(width, height, vel)
},
);
let mut random_gen = RandomGenerator::Xoroshiro(Xoroshiro::from_seed(get_seed()));
let x = self.horizontal_position.get_coordinate(
position.x,
position.x,
bb_width,
&mut random_gen,
);
let y = self.vertical_position.get_coordinate(
position.y,
position.y + f64::from(bb_height) / 2.0,
bb_height,
&mut random_gen,
);
let z = self.horizontal_position.get_coordinate(
position.z,
position.z,
bb_width,
&mut random_gen,
);
let vx = self
.horizontal_velocity
.get_velocity(movement.x, &mut random_gen);
let vy = self
.vertical_velocity
.get_velocity(movement.y, &mut random_gen);
let vz = self
.horizontal_velocity
.get_velocity(movement.z, &mut random_gen);
let speed = self.speed.get(&mut random_gen);
world.spawn_particle(
Vector3::new(x, y, z),
Vector3::new(vx as f32, vy as f32, vz as f32),
speed,
0,
self.particle,
);
}
}
impl EnchantmentEntityEffectExt for SpawnParticlesEffect {
fn apply(
&self,
world: &Arc<World>,
_enchantment_level: i32,
_owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
position: Vector3<f64>,
) {
self.apply(world, position, entity);
}
}

View File

@ -0,0 +1,75 @@
use std::sync::Arc;
use pumpkin_data::entity::EntityType;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use rand::seq::IndexedRandom;
use uuid::Uuid;
use crate::entity::lightning::LightningBoltEntity;
use crate::entity::player::Player;
use crate::entity::{Entity, EntityBase};
use crate::world::World;
/// Enchantment entity effect that summons an entity (such as lightning) at a given position.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SummonEntityEffect {
pub entity_types: Vec<&'static EntityType>,
pub join_team: bool,
}
impl SummonEntityEffect {
#[must_use]
pub const fn new(entity_types: Vec<&'static EntityType>, join_team: bool) -> Self {
Self {
entity_types,
join_team,
}
}
#[must_use]
pub fn select_random_entity_type(&self) -> Option<&'static EntityType> {
let mut rng = rand::rng();
self.entity_types.choose(&mut rng).copied()
}
/// Applies the summon entity effect at the given position in the world.
pub fn apply(
&self,
world: &Arc<World>,
position: Vector3<f64>,
owner: Option<&Arc<Player>>,
_entity: Option<&Entity>,
) -> Option<Arc<dyn EntityBase>> {
let block_pos = BlockPos::floored_v(position);
if !world.is_in_build_limit(block_pos) {
return None;
}
let entity_type = self.select_random_entity_type()?;
let spawned =
crate::entity::r#type::from_type(entity_type, position, world, Uuid::new_v4());
if let Some(bolt) = spawned.cast_any().downcast_ref::<LightningBoltEntity>()
&& let Some(player) = owner
{
bolt.set_cause(Some(player.clone()));
}
world.spawn_entity(spawned.clone());
Some(spawned)
}
}
impl super::EnchantmentEntityEffectExt for SummonEntityEffect {
fn apply(
&self,
world: &Arc<World>,
_enchantment_level: i32,
owner: Option<&Arc<Player>>,
entity: Option<&Entity>,
position: Vector3<f64>,
) {
let _ = self.apply(world, position, owner, entity);
}
}

View File

@ -1,4 +1,4 @@
use crate::enchantment::effects::Ignite;
use crate::enchantment::effects::EnchantmentEntityEffectExt;
use crate::entity::Entity;
use crate::entity::projectile::arrow::ArrowEntity;
use pumpkin_data::data_component_impl::EnchantmentsImpl;
@ -28,29 +28,39 @@ impl EnchantmentHelper {
projectile_entity: &Entity,
arrow: Option<&ArrowEntity>,
) {
let world = projectile_entity.world.load_full();
Self::run_iteration_on_item(weapon, |enchantment, level| {
for conditional_effect in enchantment.effects.projectile_spawned {
if let EnchantmentEntityEffect::Ignite { duration } = &conditional_effect.effect {
let ignite = Ignite::new(duration.clone());
ignite.apply(level, projectile_entity);
if let Some(arrow) = arrow {
arrow.set_flame(true);
}
conditional_effect.effect.apply(
&world,
level,
None,
Some(projectile_entity),
projectile_entity.pos.load(),
);
if let EnchantmentEntityEffect::Ignite { .. } = &conditional_effect.effect
&& let Some(arrow) = arrow
{
arrow.set_flame(true);
}
}
});
}
/// Applies post-attack enchantment effects (e.g. Fire Aspect ignites victim).
pub fn on_post_attack(_attacker: &Entity, victim: &Entity, weapon: &ItemStack) {
pub fn on_post_attack(attacker: &Entity, victim: &Entity, weapon: &ItemStack) {
Self::run_iteration_on_item(weapon, |enchantment, level| {
for targeted_effect in enchantment.effects.post_attack {
if targeted_effect.affected == Some(EnchantmentTarget::Victim)
&& let EnchantmentEntityEffect::Ignite { duration } = &targeted_effect.effect
{
let ignite = Ignite::new(duration.clone());
ignite.apply(level, victim);
}
let target = match targeted_effect.affected {
Some(EnchantmentTarget::Attacker | EnchantmentTarget::DamagingEntity) => {
attacker
}
Some(EnchantmentTarget::Victim) | None => victim,
};
let world = target.world.load_full();
targeted_effect
.effect
.apply(&world, level, None, Some(target), target.pos.load());
}
});
}
@ -166,4 +176,157 @@ impl EnchantmentHelper {
}
(charge_time as i32).max(0)
}
/// Modifies durability change using data-driven item damage effects (e.g. Unbreaking).
#[must_use]
pub fn modify_durability_change(item: &ItemStack, base_change: f32) -> f32 {
let mut change = base_change;
if let Some(enchantments) = item.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
for effect in enchantment.effects.item_damage {
change = effect.effect.process(*level, change);
}
}
}
change
}
/// Modifies block experience using data-driven block experience effects (e.g. Fortune).
#[must_use]
pub fn modify_block_experience(tool: &ItemStack, base_xp: i32) -> i32 {
let mut xp = base_xp as f32;
if let Some(enchantments) = tool.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
enchantment.modify_block_experience(*level, &mut xp);
}
}
(xp as i32).max(0)
}
/// Modifies mob experience using data-driven mob experience effects (e.g. Looting).
#[must_use]
pub fn modify_mob_experience(weapon: &ItemStack, base_xp: i32) -> i32 {
let mut xp = base_xp as f32;
if let Some(enchantments) = weapon.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
enchantment.modify_mob_experience(*level, &mut xp);
}
}
(xp as i32).max(0)
}
/// Modifies durability to repair from experience using data-driven effects (e.g. Mending).
#[must_use]
pub fn modify_durability_to_repair_from_xp(item: &ItemStack, base_repair: f32) -> f32 {
let mut repair = base_repair;
if let Some(enchantments) = item.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
enchantment.modify_durability_to_repair_from_xp(*level, &mut repair);
}
}
repair
}
/// Modifies trident return acceleration using data-driven effects (e.g. Loyalty).
#[must_use]
pub fn modify_trident_return_acceleration(trident: &ItemStack, base_accel: f32) -> f32 {
let mut accel = base_accel;
if let Some(enchantments) = trident.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
enchantment.modify_trident_return_to_owner_acceleration(*level, &mut accel);
}
}
accel
}
/// Modifies trident spin attack strength using data-driven effects (e.g. Riptide).
#[must_use]
pub fn modify_trident_spin_attack_strength(trident: &ItemStack, base_strength: f32) -> f32 {
let mut strength = base_strength;
if let Some(enchantments) = trident.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
enchantment.modify_trident_spin_attack_strength(*level, &mut strength);
}
}
strength
}
/// Modifies fishing time reduction using data-driven effects (e.g. Lure).
#[must_use]
pub fn modify_fishing_time_reduction(rod: &ItemStack, base_reduction: f32) -> f32 {
let mut reduction = base_reduction;
if let Some(enchantments) = rod.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
enchantment.modify_fishing_time_reduction(*level, &mut reduction);
}
}
reduction
}
/// Modifies fishing luck bonus using data-driven effects (e.g. Luck of the Sea).
#[must_use]
pub fn modify_fishing_luck_bonus(rod: &ItemStack, base_luck: f32) -> f32 {
let mut luck = base_luck;
if let Some(enchantments) = rod.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
enchantment.modify_fishing_luck_bonus(*level, &mut luck);
}
}
luck
}
/// Modifies damage protection across equipped armor items.
#[must_use]
pub fn modify_damage_protection<'a>(
armor_items: impl IntoIterator<Item = &'a ItemStack>,
base_protection: f32,
) -> f32 {
let mut protection = base_protection;
for item in armor_items {
if let Some(enchantments) = item.get_data_component::<EnchantmentsImpl>() {
for (enchantment, level) in enchantments.enchantment.iter() {
for effect in enchantment.effects.damage_protection {
protection = effect.effect.process(*level, protection);
}
}
}
}
protection
}
/// Applies location-changed enchantment effects (e.g. Frost Walker replacing water with frosted ice).
pub fn on_location_changed(
entity: &Entity,
item: &ItemStack,
position: pumpkin_util::math::vector3::Vector3<f64>,
) {
let world = entity.world.load_full();
Self::run_iteration_on_item(item, |enchantment, level| {
for conditional_effect in enchantment.effects.location_changed {
conditional_effect
.effect
.apply(&world, level, None, Some(entity), position);
}
});
}
/// Applies hit-block enchantment effects.
pub fn on_hit_block(
weapon: &ItemStack,
projectile_entity: &Entity,
position: pumpkin_util::math::vector3::Vector3<f64>,
) {
let world = projectile_entity.world.load_full();
Self::run_iteration_on_item(weapon, |enchantment, level| {
for conditional_effect in enchantment.effects.hit_block {
conditional_effect.effect.apply(
&world,
level,
None,
Some(projectile_entity),
position,
);
}
});
}
}

View File

@ -34,7 +34,7 @@ use crate::entity::mob::equipment::DEFAULT_EQUIPMENT_DROP_CHANCE;
use crate::entity::mob::slime::SlimeEntity;
use crate::entity::player::statistics::{CustomStatistic, StatisticCategory};
use crate::server::Server;
use crate::world::loot::{LootContextParameters, LootTableExt};
use crate::world::loot::LootContextParameters;
use crossbeam::atomic::AtomicCell;
use pumpkin_data::attributes::Attributes;
use pumpkin_data::data_component_impl::Operation;
@ -121,6 +121,9 @@ pub struct LivingEntity {
water_movement_speed_multiplier: f32,
livings_flags: AtomicU8,
/// The last block position the entity occupied, used to trigger location changed effects.
pub last_block_pos: AtomicCell<Option<BlockPos>>,
/// The attributes of the entity
pub attributes: RwLock<FxHashMap<u8, AttributeInstance>>,
}
@ -226,6 +229,35 @@ impl LivingEntity {
combat_tracker: std::sync::Mutex::new(CombatTracker::new()),
movement_input: AtomicCell::new(Vector3::default()),
water_movement_speed_multiplier,
last_block_pos: AtomicCell::new(None),
}
}
/// Triggers location-based enchantment effects (e.g. Frost Walker) when the entity's block position changes.
pub fn on_changed_block(&self, caller: &dyn EntityBase, _pos: BlockPos) {
let pos_f64 = self.entity.pos.load();
if let Some(player) = caller.get_player() {
let boots = player.inventory.get_slot(36);
if !boots.is_empty() {
crate::enchantment::EnchantmentHelper::on_location_changed(
&self.entity,
&boots,
pos_f64,
);
}
} else {
let boots = self
.entity_equipment
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.get(&EquipmentSlot::FEET);
if !boots.is_empty() {
crate::enchantment::EnchantmentHelper::on_location_changed(
&self.entity,
&boots,
pos_f64,
);
}
}
}
@ -233,6 +265,23 @@ impl LivingEntity {
if equipment.is_empty() {
return;
}
if equipment
.iter()
.any(|(slot, _)| *slot == EquipmentSlot::FEET)
{
let pos_f64 = self.entity.pos.load();
for (slot, stack) in equipment {
if *slot == EquipmentSlot::FEET && !stack.is_empty() {
crate::enchantment::EnchantmentHelper::on_location_changed(
&self.entity,
stack,
pos_f64,
);
}
}
}
let equipment_java: Vec<(i8, ItemStackSerializer)> = equipment
.iter()
.map(|(slot, stack)| {
@ -1408,6 +1457,9 @@ impl LivingEntity {
) {
if ground {
let fall_distance = self.fall_distance.swap(0.0);
if fall_distance > 0.0 {
self.on_changed_block(caller, self.entity.block_pos.load());
}
if fall_distance <= 0.0
|| dont_damage
|| self.should_prevent_fall_damage()
@ -1589,7 +1641,7 @@ impl LivingEntity {
};
// Drop loot
self.drop_loot(params.clone());
self.drop_loot(&params);
// Award experience
if params.killed_by_player.unwrap_or(false)
@ -1770,10 +1822,13 @@ impl LivingEntity {
}
}
fn drop_loot(&self, params: LootContextParameters) {
if let Some(loot_table) = &self.get_entity().entity_type.loot_table {
fn drop_loot(&self, params: &LootContextParameters) {
let resource_name = self.get_entity().entity_type.resource_name;
let key = format!("minecraft:entities/{resource_name}");
if let Some(loot_table) = pumpkin_data::loot_table::get_loot_table(&key) {
let seed: i64 = rand::random();
let pos = self.entity.block_pos.load();
for stack in loot_table.get_loot(params) {
for stack in crate::world::loot::generate_loot_with_context(loot_table, seed, params) {
self.entity.world.load().drop_stack(&pos, stack);
}
}
@ -2757,6 +2812,12 @@ impl EntityBase for LivingEntity {
}
}
let current_block_pos = self.entity.block_pos.load();
if is_alive && self.last_block_pos.load() != Some(current_block_pos) {
self.last_block_pos.store(Some(current_block_pos));
self.on_changed_block(caller, current_block_pos);
}
self.tick_effects();
// Current active item

View File

@ -1527,6 +1527,20 @@ impl Player {
false
}
/// Checks and triggers location-based enchantments (e.g. Frost Walker) on the player's equipped armor.
pub fn check_location_enchantments(&self, pos: Vector3<f64>, on_ground: bool) {
if on_ground {
let boots = self.inventory.get_slot(36);
if !boots.is_empty() {
crate::enchantment::EnchantmentHelper::on_location_changed(
self.get_entity(),
&boots,
pos,
);
}
}
}
/// Convenience wrapper – damages the currently held (main-hand) item.
pub fn damage_held_item(&self, amount: i32) -> bool {
self.damage_item_in_slot(&EquipmentSlot::MAIN_HAND, amount)
@ -7457,6 +7471,20 @@ impl InventoryPlayer for Player {
}
}
}
fn use_grindstone(&self, xp_amount: i32) {
if let Some(pos) = self.open_container_pos.load() {
let world = self.world();
if xp_amount > 0 {
crate::entity::experience_orb::ExperienceOrbEntity::spawn(
&world,
pos.to_centered_f64(),
xp_amount as u32,
);
}
world.sync_world_event(pumpkin_data::world::WorldEvent::SoundGrindstoneUsed, pos, 0);
}
}
}
#[cfg(test)]

View File

@ -16,7 +16,7 @@ use pumpkin_world::inventory::{Clearable, Inventory};
use crate::entity::{Entity, player::Player};
use crate::world::loot::fill_chest_inventory;
use pumpkin_data::chest_loot_table::get_chest_loot_table;
use pumpkin_data::loot_table::get_loot_table;
pub(super) struct MinecartInventory {
items: RwLock<Vec<ItemStack>>,
@ -98,7 +98,7 @@ impl MinecartInventory {
let Some((loot_table, seed)) = loot_table else {
return;
};
let Some(table) = get_chest_loot_table(&loot_table) else {
let Some(table) = get_loot_table(&loot_table) else {
*self
.loot_table
.lock()

View File

@ -5,7 +5,6 @@ use crate::entity::Entity;
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::EntityBase;
use crate::world::loot::{LootContextParameters, LootTableExt};
use pumpkin_protocol::codec::var_int::VarInt;
use pumpkin_util::GameMode;
@ -161,18 +160,15 @@ impl VehicleEntity {
let world = self.entity.world.load();
let entity_drops = world.level_info.load().game_rules.entity_drops;
if entity_drops && let Some(loot_table) = &self.entity.entity_type.loot_table {
let pos = self.entity.block_pos.load();
let is_raining = world.is_raining();
let is_thundering = world.is_thundering();
let params = LootContextParameters {
is_raining: Some(is_raining),
is_thundering: Some(is_thundering),
world_time: world.level_info.load().day_time as u64,
..Default::default()
};
for stack in loot_table.get_loot(params) {
world.drop_stack(&pos, stack);
if entity_drops {
let resource_name = self.entity.entity_type.resource_name;
let key = format!("minecraft:entities/{resource_name}");
if let Some(loot_table) = pumpkin_data::loot_table::get_loot_table(&key) {
let pos = self.entity.block_pos.load();
let seed: i64 = rand::random();
for stack in crate::world::loot::generate_loot(loot_table, seed) {
world.drop_stack(&pos, stack);
}
}
}

View File

@ -54,35 +54,34 @@ fn set_dusted_stage(block: &Block, state_id: BlockStateId, stage: u8) -> BlockSt
block.from_properties(&updated_props).to_state_id(block)
}
fn get_random_archaeology_loot() -> &'static Item {
let loot_table = [
&Item::SNORT_POTTERY_SHERD,
&Item::FLOW_POTTERY_SHERD,
&Item::GUSTER_POTTERY_SHERD,
&Item::SCRAPE_POTTERY_SHERD,
&Item::ANGLER_POTTERY_SHERD,
&Item::ARCHER_POTTERY_SHERD,
&Item::ARMS_UP_POTTERY_SHERD,
&Item::BLADE_POTTERY_SHERD,
&Item::BREWER_POTTERY_SHERD,
&Item::BURN_POTTERY_SHERD,
&Item::DANGER_POTTERY_SHERD,
&Item::EXPLORER_POTTERY_SHERD,
&Item::FRIEND_POTTERY_SHERD,
&Item::HEART_POTTERY_SHERD,
&Item::HEARTBREAK_POTTERY_SHERD,
&Item::HOWL_POTTERY_SHERD,
&Item::MINER_POTTERY_SHERD,
&Item::MOURNER_POTTERY_SHERD,
&Item::PLENTY_POTTERY_SHERD,
&Item::PRIZE_POTTERY_SHERD,
&Item::SHEAF_POTTERY_SHERD,
&Item::SHELTER_POTTERY_SHERD,
&Item::SKULL_POTTERY_SHERD,
];
use crate::block::entities::brushable_block::BrushableBlockBlockEntity;
use crate::world::World;
let idx = (rand::random::<u32>() as usize) % loot_table.len();
loot_table[idx]
fn get_archaeology_loot(is_sand: bool, location: BlockPos, world: &World) -> ItemStack {
if let Some(block_entity) = world.get_block_entity(&location)
&& let Some(brushable) = block_entity
.as_any()
.downcast_ref::<BrushableBlockBlockEntity>()
&& let Ok(mut item_guard) = brushable.item.lock()
&& let Some(item) = item_guard.take()
{
return item;
}
let loot_key = if is_sand {
"minecraft:archaeology/desert_pyramid"
} else {
"minecraft:archaeology/trail_ruins_common"
};
if let Some(table) = pumpkin_data::loot_table::get_loot_table(loot_key) {
let items = crate::world::loot::generate_loot(table, rand::random());
if let Some(first) = items.into_iter().next() {
return first;
}
}
ItemStack::new(1, &Item::SNORT_POTTERY_SHERD)
}
impl ItemBehaviour for BrushItem {
@ -153,7 +152,7 @@ impl ItemBehaviour for BrushItem {
&block_center,
);
let loot_item = get_random_archaeology_loot();
let loot_stack = get_archaeology_loot(is_sand, location, &world);
let spawn_pos = Vector3::new(
f64::from(location.0.x) + 0.5,
f64::from(location.0.y) + 1.0,
@ -161,7 +160,7 @@ impl ItemBehaviour for BrushItem {
);
let item_entity = Arc::new(ItemEntity::new(
Entity::new(world.clone(), spawn_pos, &EntityType::ITEM),
ItemStack::new(1, loot_item),
loot_stack,
));
world.spawn_entity(item_entity);
}

View File

@ -1,18 +1,15 @@
use crate::entity::Entity;
use crate::entity::item::ItemEntity;
use crate::entity::player::Player;
use crate::item::{ItemBehaviour, ItemMetadata};
use crate::server::Server;
use pumpkin_data::BlockDirection;
use pumpkin_data::entity::EntityType;
use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::{Block, tag};
use pumpkin_util::GameMode;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::world::BlockFlags;
use std::sync::Arc;
pub struct HoeItem;
@ -33,70 +30,50 @@ impl ItemBehaviour for HoeItem {
block: &Block,
_server: &Server,
) {
// Yes, Minecraft does hardcode these
if block == &Block::GRASS_BLOCK
let world = player.world();
let only_if_air_above =
|| face != BlockDirection::Down && world.get_block_state(&location.up()).is_air();
let (future_block, drop_item) = if block == &Block::GRASS_BLOCK
|| block == &Block::DIRT_PATH
|| block == &Block::DIRT
|| block == &Block::COARSE_DIRT
|| block == &Block::ROOTED_DIRT
{
let mut future_block = block;
let world = player.world();
let mut changed = false;
//Only rooted can be right-clicked on the bottom of the block
if face == BlockDirection::Down {
if block == &Block::ROOTED_DIRT {
future_block = &Block::DIRT;
changed = true;
}
if only_if_air_above() {
(Some(&Block::FARMLAND), None)
} else {
// grass, dirt && dirt path become farmland
if (block == &Block::GRASS_BLOCK
|| block == &Block::DIRT_PATH
|| block == &Block::DIRT)
&& world.get_block_state(&location.up()).is_air()
{
future_block = &Block::FARMLAND;
changed = true;
}
//Coarse dirt and rooted dirt become dirt
else if block == &Block::COARSE_DIRT || block == &Block::ROOTED_DIRT {
future_block = &Block::DIRT;
changed = true;
}
(None, None)
}
} else if block == &Block::COARSE_DIRT {
if only_if_air_above() {
(Some(&Block::DIRT), None)
} else {
(None, None)
}
} else if block == &Block::ROOTED_DIRT {
(Some(&Block::DIRT), Some(&Item::HANGING_ROOTS))
} else {
(None, None)
};
if let Some(target_block) = future_block {
world.play_sound(
Sound::ItemHoeTill,
SoundCategory::Blocks,
&location.to_f64(),
);
world.set_block_state(
&location,
target_block.default_state.id,
BlockFlags::NOTIFY_ALL,
);
if let Some(drop_item) = drop_item {
world.drop_stack_from_face(&location, face, ItemStack::new(1, drop_item));
}
// Vanilla returns PASS without touching the block when nothing is tilled,
// otherwise the rewrite would reset properties such as `snowy` on grass blocks.
if changed {
world.set_block_state(
&location,
future_block.default_state.id,
BlockFlags::NOTIFY_ALL,
);
}
//Also rooted_dirt drop a hanging_root
if block == &Block::ROOTED_DIRT {
let location = match face {
BlockDirection::Up => location.up().to_f64(),
BlockDirection::Down => location.down().to_f64(),
BlockDirection::North => location.up().to_f64().add_raw(0.0, -0.4, -1.0),
BlockDirection::South => location.up().to_f64().add_raw(0.0, -0.4, 1.0),
BlockDirection::West => location.up().to_f64().add_raw(-1.0, -0.4, 0.0),
BlockDirection::East => location.up().to_f64().add_raw(1.0, -0.4, 0.0),
};
let entity = Entity::new(world.clone(), location, &EntityType::ITEM);
// TODO: Merge stacks together
let item_entity = Arc::new(ItemEntity::new(
entity,
ItemStack::new(1, &Item::HANGING_ROOTS),
));
world.spawn_entity(item_entity);
}
if changed && player.gamemode.load() != GameMode::Creative {
if player.gamemode.load() != GameMode::Creative {
// TODO: Handle DamageResult::Broken to broadcast item break and update player slot.
let _ = item.damage_item(1);
}

View File

@ -145,6 +145,7 @@ impl BedrockClient {
if pos_changed {
chunker::update_position(player);
player.check_location_enchantments(new_pos, on_ground);
player.progress_motion(delta);
}
}

View File

@ -169,6 +169,7 @@ impl JavaClient {
// Only update idle timeout if there's actual movement (vanilla threshold)
if delta.length_squared() > 1.0E-5 {
player.update_last_action_time();
player.check_location_enchantments(pos, packet.collision & FLAG_ON_GROUND != 0);
}
player.progress_motion(delta);
}
@ -331,6 +332,7 @@ impl JavaClient {
// Only update idle timeout if there's actual movement (vanilla threshold)
if delta.length_squared() > 1.0E-5 {
player.update_last_action_time();
player.check_location_enchantments(pos, (packet.collision & FLAG_ON_GROUND) != 0);
}
player.progress_motion(delta);
}

View File

@ -562,7 +562,7 @@ impl Explosion {
is_thundering: Some(is_thundering),
..Default::default()
};
drop_loot(world, block, pos, false, params);
drop_loot(world, block, pos, false, &params);
}
if let Some(pumpkin_block) = pumpkin_block {
pumpkin_block.explode(ExplodeArgs {

File diff suppressed because it is too large Load Diff

View File

@ -5323,7 +5323,7 @@ impl World {
killed_by_player: Some(cause.is_some()),
..Default::default()
};
crate::block::drop_loot(self, broken_block, position, true, params);
crate::block::drop_loot(self, broken_block, position, true, &params);
}
let new_state_id = if broken_block
@ -5442,12 +5442,16 @@ impl World {
}
pub fn drop_stack(self: &Arc<Self>, pos: &BlockPos, stack: ItemStack) {
let height = EntityType::ITEM.dimension[1] / 2.0;
if stack.is_empty() {
return;
}
let half_height = f64::from(EntityType::ITEM.dimension[1]) / 2.0;
let spawn_pos = {
let mut r = rand::rng();
Vector3::new(
f64::from(pos.0.x) + 0.5 + r.random_range(-0.25..0.25),
f64::from(pos.0.y) + 0.5 + r.random_range(-0.25..0.25) - f64::from(height),
f64::from(pos.0.y) + 0.5 + r.random_range(-0.25..0.25) - half_height,
f64::from(pos.0.z) + 0.5 + r.random_range(-0.25..0.25),
)
};
@ -5471,6 +5475,90 @@ impl World {
self.spawn_entity(item_entity);
}
pub fn drop_stack_from_face(
self: &Arc<Self>,
pos: &BlockPos,
face: BlockDirection,
stack: ItemStack,
) {
if stack.is_empty() {
return;
}
let offset = face.to_offset();
let step_x = offset.x;
let step_y = offset.y;
let step_z = offset.z;
let half_width = f64::from(EntityType::ITEM.dimension[0]) / 2.0;
let half_height = f64::from(EntityType::ITEM.dimension[1]) / 2.0;
let (spawn_pos, velocity) = {
let mut r = rand::rng();
let x = f64::from(pos.0.x)
+ 0.5
+ if step_x == 0 {
r.random_range(-0.25..0.25)
} else {
f64::from(step_x) * (0.5 + half_width)
};
let y = f64::from(pos.0.y)
+ 0.5
+ if step_y == 0 {
r.random_range(-0.25..0.25)
} else {
f64::from(step_y) * (0.5 + half_height)
}
- half_height;
let z = f64::from(pos.0.z)
+ 0.5
+ if step_z == 0 {
r.random_range(-0.25..0.25)
} else {
f64::from(step_z) * (0.5 + half_width)
};
let delta_x = if step_x == 0 {
r.random_range(-0.1..0.1)
} else {
f64::from(step_x) * 0.1
};
let delta_y = if step_y == 0 {
r.random_range(0.0..0.1)
} else {
f64::from(step_y) * 0.1 + 0.1
};
let delta_z = if step_z == 0 {
r.random_range(-0.1..0.1)
} else {
f64::from(step_z) * 0.1
};
(
Vector3::new(x, y, z),
Vector3::new(delta_x, delta_y, delta_z),
)
};
let entity = Entity::new(self.clone(), spawn_pos, &EntityType::ITEM);
let mut item_event = crate::plugin::api::events::entity::item_spawn::ItemSpawnEvent::new(
entity.entity_id,
spawn_pos,
stack.item.registry_key.to_string(),
);
if let Some(server) = self.server.upgrade() {
server
.plugin_manager
.fire_blocking(&server, &mut item_event);
}
if item_event.cancelled {
return;
}
let item_entity = Arc::new(ItemEntity::new_with_velocity(entity, stack, velocity, 10));
self.spawn_entity(item_entity);
}
pub fn strike_lightning(self: &Arc<Self>, pos: Vector3<f64>, effect_only: bool) {
use pumpkin_data::entity::EntityType;
use uuid::Uuid;

View File

@ -12,10 +12,7 @@ use std::{
};
use syn::{Ident, LitInt, LitStr};
use crate::{
bitsets::{Bitset, gen_u16_bitset},
loot::LootTableStruct,
};
use crate::bitsets::{Bitset, gen_u16_bitset};
/// Converts a sparse index-value list into a dense array, filling gaps with `None` tokens.
///
@ -662,8 +659,6 @@ pub struct Block {
pub item_id: u16,
/// Flammability data, present only if the block can catch fire.
pub flammable: Option<FlammableStruct>,
/// Loot table used when the block is broken, if any.
pub loot_table: Option<LootTableStruct>,
/// Friction applied to entities walking on this block.
pub slipperiness: f32,
/// Horizontal velocity multiplier for entities inside this block.
@ -703,12 +698,6 @@ impl ToTokens for Block {
};
// Generate state tokens
let states = self.states.iter().map(BlockState::to_tokens);
let loot_table = if let Some(table) = &self.loot_table {
let table_tokens = table.to_token_stream();
quote! { Some(#table_tokens) }
} else {
quote! { None }
};
let default_state_ref: &BlockState = self
.states
@ -738,7 +727,6 @@ impl ToTokens for Block {
default_state: &#default_state,
states: &[#(#states),*],
flammable: #flammable,
loot_table: #loot_table,
experience: #experience,
}
});
@ -1148,7 +1136,6 @@ pub fn build() -> TokenStream {
};
use crate::block_state::PistonBehavior;
use pumpkin_util::math::int_provider::{UniformIntProvider, IntProvider, NormalIntProvider};
use pumpkin_util::loot_table::*;
use pumpkin_util::math::experience::Experience;
use pumpkin_util::math::vector3::Vector3;
use std::collections::BTreeMap;

View File

@ -1,281 +0,0 @@
use std::{fs, path::Path};
use heck::ToShoutySnakeCase;
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use serde::Deserialize;
use syn::LitStr;
/// `rolls` can be a bare float or an object with `type/min/max`.
#[derive(Deserialize, Clone, Debug)]
#[serde(untagged)]
enum RollsStruct {
Constant(f32),
Provider {
#[allow(dead_code)]
#[serde(rename = "type")]
provider_type: String,
#[allow(dead_code)]
#[serde(default)]
min: f32,
#[serde(default)]
max: f32,
},
}
impl RollsStruct {
fn min(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { min, .. } => min.round() as i32,
}
}
fn max(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { max, .. } => max.round() as i32,
}
}
}
/// A `set_count` count provider (uniform or constant).
#[derive(Deserialize, Clone, Debug)]
#[serde(untagged)]
enum CountStruct {
Constant(f32),
Provider {
#[serde(rename = "type")]
#[allow(dead_code)]
provider_type: String,
#[serde(default)]
min: f32,
#[serde(default)]
max: f32,
},
}
impl CountStruct {
fn min(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { min, .. } => min.round() as i32,
}
}
fn max(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { max, .. } => max.round() as i32,
}
}
}
#[derive(Deserialize, Clone, Debug)]
struct EntryFunctionStruct {
function: String,
count: Option<CountStruct>,
}
/// A single entry inside a pool.
#[derive(Deserialize, Clone, Debug)]
struct PoolEntryStruct {
#[serde(rename = "type")]
entry_type: String,
/// Item name (only for `minecraft:item`).
name: Option<String>,
/// Weight (default 1 if absent).
#[serde(default = "default_weight")]
weight: i32,
/// Optional list of functions.
#[serde(default)]
functions: Vec<EntryFunctionStruct>,
}
fn default_weight() -> i32 {
1
}
#[derive(Deserialize, Clone, Debug)]
struct PoolStruct {
entries: Vec<PoolEntryStruct>,
rolls: RollsStruct,
}
/// Top-level chest loot table JSON.
#[derive(Deserialize, Clone, Debug)]
struct ChestLootTableJson {
pools: Vec<PoolStruct>,
}
/// Convert a relative path (e.g. `"trial_chambers/entrance"`) to a Minecraft
/// namespaced key (e.g. `"minecraft:chests/trial_chambers/entrance"`).
fn path_to_key(relative: &str) -> String {
format!("minecraft:chests/{relative}")
}
/// Convert a file stem path to a valid Rust SCREAMING_SNAKE_CASE identifier prefix.
/// e.g. `"trial_chambers/entrance"` -> `"TRIAL_CHAMBERS_ENTRANCE"`
fn path_to_ident(relative: &str) -> String {
relative.replace('/', "_").to_shouty_snake_case()
}
/// Read every chest loot JSON from `../assets/loot_table/chests/` (recursively)
/// and emit a `pumpkin-data/src/generated/chest_loot.rs` with static constants
/// and a `get_chest_loot_table(key) -> Option<&'static ChestLootTable>` function.
pub fn build() -> TokenStream {
let base = Path::new("../../assets/datapacks/26_2/data/minecraft/loot_table/chests");
// Collect all JSON files recursively, sorted for deterministic output.
let mut files: Vec<(String, ChestLootTableJson)> = collect_json_files(base, base);
files.sort_by(|a, b| a.0.cmp(&b.0));
let mut all_tokens = TokenStream::new();
// Emit one set of statics per file
let mut table_idents = Vec::new();
let mut table_keys = Vec::new();
for (relative_path, table) in &files {
let prefix = path_to_ident(relative_path);
let key = path_to_key(relative_path);
let table_ident = format_ident!("{}", prefix);
let pool_tokens = emit_table(&prefix, table, &mut all_tokens);
let pools_ident = format_ident!("{}_POOLS", prefix);
all_tokens.extend(quote! {
static #pools_ident: &[ChestLootPool] = &[#(#pool_tokens),*];
pub static #table_ident: ChestLootTable = ChestLootTable { pools: #pools_ident };
});
table_idents.push(table_ident);
table_keys.push(LitStr::new(&key, Span::call_site()));
}
// Emit get_chest_loot_table
all_tokens.extend(quote! {
#[must_use]
pub fn get_chest_loot_table(key: &str) -> Option<&'static ChestLootTable> {
match key {
#(#table_keys => Some(&#table_idents),)*
_ => None,
}
}
});
quote! {
pub use pumpkin_util::chest_loot_table::*;
#all_tokens
}
}
/// Emit static entry arrays and pool literals for one table.
/// Returns the list of `ChestLootPool` literals (one per pool).
fn emit_table(
prefix: &str,
table: &ChestLootTableJson,
tokens: &mut TokenStream,
) -> Vec<TokenStream> {
let mut pool_literals = Vec::new();
for (pool_idx, pool) in table.pools.iter().enumerate() {
let min_rolls = pool.rolls.min();
let max_rolls = pool.rolls.max();
let mut entry_literals = Vec::new();
let mut empty_weight: i32 = 0;
for entry in &pool.entries {
match entry.entry_type.as_str() {
"minecraft:empty" => {
empty_weight += entry.weight;
}
"minecraft:item" => {
let name = match &entry.name {
Some(n) => n.clone(),
None => continue, // malformed, skip
};
let weight = entry.weight;
// Extract min/max count from the first `set_count` function.
let (min_count, max_count) = entry
.functions
.iter()
.find(|f| f.function == "minecraft:set_count")
.and_then(|f| f.count.as_ref())
.map(|c| (c.min(), c.max()))
.unwrap_or((1, 1));
let name_lit = LitStr::new(&name, Span::call_site());
entry_literals.push(quote! {
ChestLootEntry {
item: #name_lit,
weight: #weight,
min_count: #min_count,
max_count: #max_count,
}
});
}
_ => {} // skip loot_table refs, dynamic, etc.
}
}
// Emit the entries static array.
let entries_ident = format_ident!("{}_POOL{}_ENTRIES", prefix, pool_idx);
tokens.extend(quote! {
static #entries_ident: &[ChestLootEntry] = &[#(#entry_literals),*];
});
pool_literals.push(quote! {
ChestLootPool {
entries: #entries_ident,
min_rolls: #min_rolls,
max_rolls: #max_rolls,
empty_weight: #empty_weight,
}
});
}
pool_literals
}
/// Recursively collect all `*.json` files under `dir`, returning a vec of
/// `(relative_stem_path, parsed_table)`.
fn collect_json_files(base: &Path, dir: &Path) -> Vec<(String, ChestLootTableJson)> {
let mut result = Vec::new();
let entries = match fs::read_dir(dir) {
Ok(e) => e,
Err(_) => return result,
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
result.extend(collect_json_files(base, &path));
} else if path.extension().and_then(|s| s.to_str()) == Some("json") {
// Build relative stem: e.g. "trial_chambers/entrance"
let rel = path.strip_prefix(base).unwrap();
let stem = rel.with_extension("");
// Use forward slashes on all platforms.
let relative = stem
.components()
.map(|c| c.as_os_str().to_string_lossy().into_owned())
.collect::<Vec<_>>()
.join("/");
let raw = match fs::read_to_string(&path) {
Ok(s) => s,
Err(e) => {
eprintln!("Warning: could not read {}: {e}", path.display());
continue;
}
};
match serde_json::from_str::<ChestLootTableJson>(&raw) {
Ok(table) => result.push((relative, table)),
Err(e) => eprintln!("Warning: could not parse {}: {e}", path.display()),
}
}
}
result
}

View File

@ -160,6 +160,133 @@ fn parse_level_based_value(val: &serde_json::Value) -> TokenStream {
}
}
fn parse_particle(v: &serde_json::Value) -> TokenStream {
let type_str = if let Some(s) = v.as_str() {
s
} else {
v.get("type").and_then(|s| s.as_str()).unwrap_or("")
};
let raw = type_str.strip_prefix("minecraft:").unwrap_or(type_str);
let ident = format_ident!("{}", raw.to_pascal_case());
quote! { crate::particle::Particle::#ident }
}
fn parse_position_source(v: Option<&serde_json::Value>) -> (TokenStream, f32, f32) {
let obj = v.and_then(|val| val.as_object());
let type_str = obj
.and_then(|o| o.get("type"))
.and_then(|s| s.as_str())
.unwrap_or("entity_position");
let offset = obj
.and_then(|o| o.get("offset"))
.and_then(|n| n.as_f64())
.unwrap_or(0.0) as f32;
let scale = obj
.and_then(|o| o.get("scale"))
.and_then(|n| n.as_f64())
.unwrap_or(1.0) as f32;
let type_token = match type_str {
"in_bounding_box" => quote! { PositionSourceType::InBoundingBox },
_ => quote! { PositionSourceType::EntityPosition },
};
(type_token, offset, scale)
}
fn parse_float_provider(v: &serde_json::Value) -> TokenStream {
if let Some(f) = v.as_f64() {
let f = f as f32;
quote! { pumpkin_util::math::float_provider::FloatProvider::Constant(#f) }
} else if let Some(type_str) = v.get("type").and_then(|s| s.as_str()) {
match type_str {
"minecraft:constant" => {
let val = v.get("value").and_then(|n| n.as_f64()).unwrap_or(0.0) as f32;
quote! { pumpkin_util::math::float_provider::FloatProvider::Constant(#val) }
}
"minecraft:uniform" => {
let min = v
.get("min_inclusive")
.and_then(|n| n.as_f64())
.unwrap_or(0.0) as f32;
let max = v
.get("max_exclusive")
.and_then(|n| n.as_f64())
.unwrap_or(0.0) as f32;
quote! {
pumpkin_util::math::float_provider::FloatProvider::Object(
pumpkin_util::math::float_provider::NormalFloatProvider::Uniform(
pumpkin_util::math::float_provider::UniformFloatProvider::new(#min, #max)
)
)
}
}
"minecraft:trapezoid" => {
let min = v.get("min").and_then(|n| n.as_f64()).unwrap_or(0.0) as f32;
let max = v.get("max").and_then(|n| n.as_f64()).unwrap_or(0.0) as f32;
let plateau = v.get("plateau").and_then(|n| n.as_f64()).unwrap_or(0.0) as f32;
quote! {
pumpkin_util::math::float_provider::FloatProvider::Object(
pumpkin_util::math::float_provider::NormalFloatProvider::Trapezoid(
pumpkin_util::math::float_provider::TrapezoidFloatProvider::new(#min, #max, #plateau)
)
)
}
}
_ => quote! { pumpkin_util::math::float_provider::FloatProvider::Constant(0.0) },
}
} else {
quote! { pumpkin_util::math::float_provider::FloatProvider::Constant(0.0) }
}
}
fn parse_velocity_source(v: Option<&serde_json::Value>) -> (f32, TokenStream) {
let obj = v.and_then(|val| val.as_object());
let movement_scale = obj
.and_then(|o| o.get("movement_scale"))
.and_then(|n| n.as_f64())
.unwrap_or(0.0) as f32;
let base = obj.and_then(|o| o.get("base"));
let base_token = match base {
Some(b) => parse_float_provider(b),
None => quote! { pumpkin_util::math::float_provider::FloatProvider::Constant(0.0) },
};
(movement_scale, base_token)
}
fn parse_vec3(v: Option<&serde_json::Value>) -> (f64, f64, f64) {
let arr = v.and_then(|val| val.as_array());
if let Some(a) = arr {
let x = a.first().and_then(|n| n.as_f64()).unwrap_or(0.0);
let y = a.get(1).and_then(|n| n.as_f64()).unwrap_or(0.0);
let z = a.get(2).and_then(|n| n.as_f64()).unwrap_or(0.0);
(x, y, z)
} else {
(0.0, 0.0, 0.0)
}
}
fn parse_status_effect_list(v: Option<&serde_json::Value>) -> TokenStream {
match v {
Some(serde_json::Value::String(s)) => {
let raw = s.strip_prefix("minecraft:").unwrap_or(s);
let ident = format_ident!("{}", raw.to_shouty_snake_case());
quote! { &[&crate::effect::StatusEffect::#ident] }
}
Some(serde_json::Value::Array(arr)) => {
let idents: Vec<_> = arr
.iter()
.filter_map(|x| x.as_str())
.map(|s| {
let raw = s.strip_prefix("minecraft:").unwrap_or(s);
let ident = format_ident!("{}", raw.to_shouty_snake_case());
quote! { &crate::effect::StatusEffect::#ident }
})
.collect();
quote! { &[#(#idents),*] }
}
_ => quote! { &[] },
}
}
fn parse_entity_effect(val: &serde_json::Value) -> TokenStream {
if let Some(obj) = val.as_object() {
let eff_type = obj.get("type").and_then(|t| t.as_str()).unwrap_or("");
@ -171,12 +298,41 @@ fn parse_entity_effect(val: &serde_json::Value) -> TokenStream {
quote! { EnchantmentEntityEffect::Ignite { duration: #dur } }
}
"minecraft:damage_entity" => {
let dmg = parse_level_based_value(
obj.get("damage")
.or_else(|| obj.get("min_damage"))
let min_damage = parse_level_based_value(
obj.get("min_damage")
.or_else(|| obj.get("damage"))
.unwrap_or(&serde_json::Value::Null),
);
quote! { EnchantmentEntityEffect::DamageEntity { damage: #dmg } }
let max_damage = parse_level_based_value(
obj.get("max_damage")
.or_else(|| obj.get("damage"))
.unwrap_or(&serde_json::Value::Null),
);
let damage_type = obj.get("damage_type").and_then(|s| s.as_str());
let damage_type_token = match damage_type {
Some(dt) => {
let dt_raw = dt.strip_prefix("minecraft:").unwrap_or(dt);
let dt_ident = format_ident!("{}", dt_raw.to_shouty_snake_case());
quote! { Some(&crate::damage::DamageType::#dt_ident) }
}
None => quote! { None },
};
quote! {
EnchantmentEntityEffect::DamageEntity {
min_damage: #min_damage,
max_damage: #max_damage,
damage_type: #damage_type_token,
}
}
}
"minecraft:change_item_damage" => {
let amount =
parse_level_based_value(obj.get("amount").unwrap_or(&serde_json::Value::Null));
quote! {
EnchantmentEntityEffect::ChangeItemDamage {
amount: #amount,
}
}
}
"minecraft:play_sound" => {
let sound = obj.get("sound").and_then(|s| s.as_str()).unwrap_or("");
@ -216,6 +372,227 @@ fn parse_entity_effect(val: &serde_json::Value) -> TokenStream {
}
}
}
"minecraft:set_block_properties" => {
let offset_x = obj
.get("offset")
.and_then(|v| v.get(0))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_y = obj
.get("offset")
.and_then(|v| v.get(1))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_z = obj
.get("offset")
.and_then(|v| v.get(2))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let event = obj.get("trigger_game_event").and_then(|s| s.as_str());
let event_token = match event {
Some(ev) => {
let ev_raw = ev.strip_prefix("minecraft:").unwrap_or(ev);
let ev_ident = format_ident!("{}", ev_raw.to_pascal_case());
quote! { Some(crate::game_event::GameEvent::#ev_ident) }
}
None => quote! { None },
};
let properties_obj = obj.get("properties").and_then(|p| p.as_object());
let properties_tokens: Vec<_> = properties_obj
.map(|o| {
o.iter()
.map(|(k, v)| {
let val_str = v.as_str().unwrap_or("");
quote! { (#k, #val_str) }
})
.collect()
})
.unwrap_or_default();
quote! {
EnchantmentEntityEffect::SetBlockProperties {
properties: &[#(#properties_tokens),*],
offset_x: #offset_x,
offset_y: #offset_y,
offset_z: #offset_z,
trigger_game_event: #event_token,
}
}
}
"minecraft:replace_disk" => {
let radius =
parse_level_based_value(obj.get("radius").unwrap_or(&serde_json::Value::Null));
let height =
parse_level_based_value(obj.get("height").unwrap_or(&serde_json::Value::Null));
let offset_x = obj
.get("offset")
.and_then(|v| v.get(0))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_y = obj
.get("offset")
.and_then(|v| v.get(1))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_z = obj
.get("offset")
.and_then(|v| v.get(2))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let event = obj.get("trigger_game_event").and_then(|s| s.as_str());
let event_token = match event {
Some(ev) => {
let ev_raw = ev.strip_prefix("minecraft:").unwrap_or(ev);
let ev_ident = format_ident!("{}", ev_raw.to_pascal_case());
quote! { Some(crate::game_event::GameEvent::#ev_ident) }
}
None => quote! { None },
};
let block_state_token = obj.get("block_state").map_or_else(
|| quote! { crate::block::Block::FROSTED_ICE.default_state },
parse_block_state,
);
let predicate_token = obj
.get("predicate")
.map_or_else(|| quote! { None }, parse_replace_disk_predicate);
quote! {
EnchantmentEntityEffect::ReplaceDisk {
radius: #radius,
height: #height,
offset_x: #offset_x,
offset_y: #offset_y,
offset_z: #offset_z,
predicate: #predicate_token,
block_state: #block_state_token,
trigger_game_event: #event_token,
}
}
}
"minecraft:summon_entity" => {
let entity_val = obj.get("entity");
let entity_token = match entity_val {
Some(serde_json::Value::String(s)) => {
let raw = s.strip_prefix("minecraft:").unwrap_or(s);
let ident = format_ident!("{}", raw.to_shouty_snake_case());
quote! { &[&crate::entity::EntityType::#ident] }
}
Some(serde_json::Value::Array(arr)) => {
let idents: Vec<TokenStream> = arr
.iter()
.filter_map(|v| v.as_str())
.map(|s| {
let raw = s.strip_prefix("minecraft:").unwrap_or(s);
let ident = format_ident!("{}", raw.to_shouty_snake_case());
quote! { &crate::entity::EntityType::#ident }
})
.collect();
quote! { &[#(#idents),*] }
}
_ => quote! { &[] },
};
let join_team = obj
.get("join_team")
.and_then(|b| b.as_bool())
.unwrap_or(false);
quote! {
EnchantmentEntityEffect::SummonEntity {
entity_types: #entity_token,
join_team: #join_team,
}
}
}
"minecraft:spawn_particles" => {
let particle_val = obj.get("particle").unwrap_or(&serde_json::Value::Null);
let particle_token = parse_particle(particle_val);
let (h_pos_type, h_pos_off, h_pos_scale) =
parse_position_source(obj.get("horizontal_position"));
let (v_pos_type, v_pos_off, v_pos_scale) =
parse_position_source(obj.get("vertical_position"));
let (h_vel_scale, h_vel_base) =
parse_velocity_source(obj.get("horizontal_velocity"));
let (v_vel_scale, v_vel_base) = parse_velocity_source(obj.get("vertical_velocity"));
let speed_token =
parse_float_provider(obj.get("speed").unwrap_or(&serde_json::Value::Null));
quote! {
EnchantmentEntityEffect::SpawnParticles {
particle: #particle_token,
horizontal_position: PositionSource {
source_type: #h_pos_type,
offset: #h_pos_off,
scale: #h_pos_scale,
},
vertical_position: PositionSource {
source_type: #v_pos_type,
offset: #v_pos_off,
scale: #v_pos_scale,
},
horizontal_velocity: VelocitySource {
movement_scale: #h_vel_scale,
base: #h_vel_base,
},
vertical_velocity: VelocitySource {
movement_scale: #v_vel_scale,
base: #v_vel_base,
},
speed: #speed_token,
}
}
}
"minecraft:run_function" => {
let function = obj.get("function").and_then(|s| s.as_str()).unwrap_or("");
quote! {
EnchantmentEntityEffect::RunFunction {
function: #function,
}
}
}
"minecraft:apply_exhaustion" => {
let amount =
parse_level_based_value(obj.get("amount").unwrap_or(&serde_json::Value::Null));
quote! {
EnchantmentEntityEffect::ApplyExhaustion {
amount: #amount,
}
}
}
"minecraft:apply_impulse" => {
let (dir_x, dir_y, dir_z) = parse_vec3(obj.get("direction"));
let (scale_x, scale_y, scale_z) = parse_vec3(obj.get("coordinate_scale"));
let mag = parse_level_based_value(
obj.get("magnitude").unwrap_or(&serde_json::Value::Null),
);
quote! {
EnchantmentEntityEffect::ApplyImpulse {
direction: pumpkin_util::math::vector3::Vector3::new(#dir_x, #dir_y, #dir_z),
coordinate_scale: pumpkin_util::math::vector3::Vector3::new(#scale_x, #scale_y, #scale_z),
magnitude: #mag,
}
}
}
"minecraft:apply_mob_effect" => {
let to_apply = parse_status_effect_list(obj.get("to_apply"));
let min_duration = parse_level_based_value(
obj.get("min_duration").unwrap_or(&serde_json::Value::Null),
);
let max_duration = parse_level_based_value(
obj.get("max_duration").unwrap_or(&serde_json::Value::Null),
);
let min_amplifier = parse_level_based_value(
obj.get("min_amplifier").unwrap_or(&serde_json::Value::Null),
);
let max_amplifier = parse_level_based_value(
obj.get("max_amplifier").unwrap_or(&serde_json::Value::Null),
);
quote! {
EnchantmentEntityEffect::ApplyMobEffect {
to_apply: #to_apply,
min_duration: #min_duration,
max_duration: #max_duration,
min_amplifier: #min_amplifier,
max_amplifier: #max_amplifier,
}
}
}
"minecraft:explode" => {
let attribute_to_user = obj
.get("attribute_to_user")
@ -477,6 +854,146 @@ fn parse_targeted_conditional_value_effects(val: Option<&serde_json::Value>) ->
quote! { &[#(#effects),*] }
}
fn parse_block_state(v: &serde_json::Value) -> TokenStream {
let state_val = if let Some(state) = v.get("state") {
state
} else {
v
};
let name = state_val
.get("Name")
.and_then(|n| n.as_str())
.unwrap_or("minecraft:air");
let name_stripped = name.strip_prefix("minecraft:").unwrap_or(name);
let block_ident = format_ident!("{}", name_stripped.to_shouty_snake_case());
quote! {
crate::Block::#block_ident.default_state
}
}
fn parse_replace_disk_predicate(v: &serde_json::Value) -> TokenStream {
if v.is_null() {
return quote! { None };
}
let pred_token = parse_single_replace_disk_predicate(v);
quote! { Some(#pred_token) }
}
fn parse_single_replace_disk_predicate(v: &serde_json::Value) -> TokenStream {
let type_str = v.get("type").and_then(|s| s.as_str()).unwrap_or("");
match type_str {
"minecraft:matching_block_tag" => {
let offset_x = v
.get("offset")
.and_then(|a| a.get(0))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_y = v
.get("offset")
.and_then(|a| a.get(1))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_z = v
.get("offset")
.and_then(|a| a.get(2))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let tag = v.get("tag").and_then(|s| s.as_str()).unwrap_or("");
let tag_ident = format_ident!("{}", tag.to_uppercase().replace([':', '-'], "_"));
quote! {
ReplaceDiskPredicate::MatchingBlockTag {
offset: pumpkin_util::math::vector3::Vector3::new(#offset_x, #offset_y, #offset_z),
tag: &crate::tag::Block::#tag_ident,
}
}
}
"minecraft:matching_blocks" => {
let offset_x = v
.get("offset")
.and_then(|a| a.get(0))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_y = v
.get("offset")
.and_then(|a| a.get(1))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_z = v
.get("offset")
.and_then(|a| a.get(2))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let blocks_token = match v.get("blocks") {
Some(serde_json::Value::String(s)) => quote! { &[#s] },
Some(serde_json::Value::Array(arr)) => {
let items: Vec<&str> = arr.iter().filter_map(|x| x.as_str()).collect();
quote! { &[#(#items),*] }
}
_ => quote! { &[] },
};
quote! {
ReplaceDiskPredicate::MatchingBlocks {
offset: pumpkin_util::math::vector3::Vector3::new(#offset_x, #offset_y, #offset_z),
blocks: #blocks_token,
}
}
}
"minecraft:matching_fluids" => {
let offset_x = v
.get("offset")
.and_then(|a| a.get(0))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_y = v
.get("offset")
.and_then(|a| a.get(1))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let offset_z = v
.get("offset")
.and_then(|a| a.get(2))
.and_then(|n| n.as_i64())
.unwrap_or(0) as i32;
let fluids_token = match v.get("fluids") {
Some(serde_json::Value::String(s)) => quote! { &[#s] },
Some(serde_json::Value::Array(arr)) => {
let items: Vec<&str> = arr.iter().filter_map(|x| x.as_str()).collect();
quote! { &[#(#items),*] }
}
_ => quote! { &[] },
};
quote! {
ReplaceDiskPredicate::MatchingFluids {
offset: pumpkin_util::math::vector3::Vector3::new(#offset_x, #offset_y, #offset_z),
fluids: #fluids_token,
}
}
}
"minecraft:unobstructed" => {
quote! {
ReplaceDiskPredicate::Unobstructed
}
}
"minecraft:all_of" => {
let preds: Vec<TokenStream> = v
.get("predicates")
.and_then(|arr| arr.as_array())
.map(|arr| {
arr.iter()
.map(parse_single_replace_disk_predicate)
.collect()
})
.unwrap_or_default();
quote! {
ReplaceDiskPredicate::AllOf(&[#(#preds),*])
}
}
_ => quote! {
ReplaceDiskPredicate::AllOf(&[])
},
}
}
fn parse_optional_value_effect(val: Option<&serde_json::Value>) -> TokenStream {
if let Some(v) = val {
let eff = v.get("effect").unwrap_or(v);
@ -595,6 +1112,8 @@ pub fn build() -> TokenStream {
parse_optional_value_effect(effects_map.get("minecraft:trident_spin_attack_strength"));
let crossbow_charge_time =
parse_optional_value_effect(effects_map.get("minecraft:crossbow_charge_time"));
let location_changed =
parse_conditional_entity_effects(effects_map.get("minecraft:location_changed"));
let prevent_armor_change = effects_map.contains_key("minecraft:prevent_armor_change");
let prevent_equipment_drop = effects_map.contains_key("minecraft:prevent_equipment_drop");
@ -622,6 +1141,7 @@ pub fn build() -> TokenStream {
trident_return_acceleration: #trident_return_acceleration,
trident_spin_attack_strength: #trident_spin_attack_strength,
crossbow_charge_time: #crossbow_charge_time,
location_changed: #location_changed,
prevent_armor_change: #prevent_armor_change,
prevent_equipment_drop: #prevent_equipment_drop,
}
@ -777,13 +1297,36 @@ pub fn build() -> TokenStream {
pub effect: T,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ReplaceDiskPredicate {
MatchingBlockTag {
offset: pumpkin_util::math::vector3::Vector3<i32>,
tag: &'static crate::tag::Tag,
},
MatchingBlocks {
offset: pumpkin_util::math::vector3::Vector3<i32>,
blocks: &'static [&'static str],
},
MatchingFluids {
offset: pumpkin_util::math::vector3::Vector3<i32>,
fluids: &'static [&'static str],
},
Unobstructed,
AllOf(&'static [ReplaceDiskPredicate]),
}
#[derive(Clone, Debug, PartialEq)]
pub enum EnchantmentEntityEffect {
Ignite {
duration: LevelBasedValue,
},
DamageEntity {
damage: LevelBasedValue,
min_damage: LevelBasedValue,
max_damage: LevelBasedValue,
damage_type: Option<&'static crate::damage::DamageType>,
},
ChangeItemDamage {
amount: LevelBasedValue,
},
PlaySound {
sound: &'static str,
@ -794,6 +1337,53 @@ pub fn build() -> TokenStream {
offset_z: i32,
trigger_game_event: Option<crate::game_event::GameEvent>,
},
SetBlockProperties {
properties: &'static [(&'static str, &'static str)],
offset_x: i32,
offset_y: i32,
offset_z: i32,
trigger_game_event: Option<crate::game_event::GameEvent>,
},
ReplaceDisk {
radius: LevelBasedValue,
height: LevelBasedValue,
offset_x: i32,
offset_y: i32,
offset_z: i32,
predicate: Option<ReplaceDiskPredicate>,
block_state: &'static crate::block_state::BlockState,
trigger_game_event: Option<crate::game_event::GameEvent>,
},
SummonEntity {
entity_types: &'static [&'static crate::entity::EntityType],
join_team: bool,
},
SpawnParticles {
particle: crate::particle::Particle,
horizontal_position: PositionSource,
vertical_position: PositionSource,
horizontal_velocity: VelocitySource,
vertical_velocity: VelocitySource,
speed: pumpkin_util::math::float_provider::FloatProvider,
},
RunFunction {
function: &'static str,
},
ApplyExhaustion {
amount: LevelBasedValue,
},
ApplyImpulse {
direction: pumpkin_util::math::vector3::Vector3<f64>,
coordinate_scale: pumpkin_util::math::vector3::Vector3<f64>,
magnitude: LevelBasedValue,
},
ApplyMobEffect {
to_apply: &'static [&'static crate::effect::StatusEffect],
min_duration: LevelBasedValue,
max_duration: LevelBasedValue,
min_amplifier: LevelBasedValue,
max_amplifier: LevelBasedValue,
},
Explode {
attribute_to_user: bool,
damage_type: Option<&'static crate::damage::DamageType>,
@ -813,6 +1403,129 @@ pub fn build() -> TokenStream {
Other,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub enum PositionSourceType {
#[default]
EntityPosition,
InBoundingBox,
}
impl PositionSourceType {
#[must_use]
pub fn get_coordinate(
self,
position: f64,
center: f64,
bounding_box_span: f32,
random: &mut impl pumpkin_util::random::RandomImpl,
) -> f64 {
match self {
Self::EntityPosition => position,
Self::InBoundingBox => {
let random_offset = f64::from(random.next_f32()) - 0.5;
center + random_offset * f64::from(bounding_box_span)
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct PositionSource {
pub source_type: PositionSourceType,
pub offset: f32,
pub scale: f32,
}
impl PositionSource {
#[must_use]
pub const fn new(source_type: PositionSourceType, offset: f32, scale: f32) -> Self {
Self {
source_type,
offset,
scale,
}
}
#[must_use]
pub const fn offset_from_entity_position(offset: f32) -> Self {
Self {
source_type: PositionSourceType::EntityPosition,
offset,
scale: 1.0,
}
}
#[must_use]
pub const fn in_bounding_box() -> Self {
Self {
source_type: PositionSourceType::InBoundingBox,
offset: 0.0,
scale: 1.0,
}
}
#[must_use]
pub fn get_coordinate(
&self,
position: f64,
center: f64,
bounding_box_span: f32,
random: &mut impl pumpkin_util::random::RandomImpl,
) -> f64 {
self.source_type.get_coordinate(
position,
center,
bounding_box_span * self.scale,
random,
) + f64::from(self.offset)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct VelocitySource {
pub movement_scale: f32,
pub base: pumpkin_util::math::float_provider::FloatProvider,
}
impl VelocitySource {
#[must_use]
pub const fn new(
movement_scale: f32,
base: pumpkin_util::math::float_provider::FloatProvider,
) -> Self {
Self {
movement_scale,
base,
}
}
#[must_use]
pub const fn movement_scaled(scale: f32) -> Self {
Self {
movement_scale: scale,
base: pumpkin_util::math::float_provider::FloatProvider::Constant(0.0),
}
}
#[must_use]
pub const fn fixed_velocity(
provider: pumpkin_util::math::float_provider::FloatProvider,
) -> Self {
Self {
movement_scale: 0.0,
base: provider,
}
}
pub fn get_velocity(
&self,
movement: f64,
random: &mut impl pumpkin_util::random::RandomImpl,
) -> f64 {
f64::from(self.movement_scale).mul_add(movement, f64::from(self.base.get(random)))
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum EnchantmentValueEffect {
Add(LevelBasedValue),
@ -866,6 +1579,7 @@ pub fn build() -> TokenStream {
pub trident_return_acceleration: &'static [ConditionalEffect<EnchantmentValueEffect>],
pub trident_spin_attack_strength: Option<EnchantmentValueEffect>,
pub crossbow_charge_time: Option<EnchantmentValueEffect>,
pub location_changed: &'static [ConditionalEffect<EnchantmentEntityEffect>],
pub prevent_armor_change: bool,
pub prevent_equipment_drop: bool,
}
@ -1109,6 +1823,10 @@ pub fn build() -> TokenStream {
pub fn get_projectile_spawned_effects(&self) -> &'static [ConditionalEffect<EnchantmentEntityEffect>] {
self.effects.projectile_spawned
}
pub fn get_location_changed_effects(&self) -> &'static [ConditionalEffect<EnchantmentEntityEffect>] {
self.effects.location_changed
}
}
}
}

View File

@ -7,8 +7,6 @@ use quote::{ToTokens, format_ident, quote};
use serde::Deserialize;
use syn::LitInt;
use crate::loot::LootTableStruct;
/// Raw deserialization shape for a single entity type entry from `entities.json`.
#[derive(Deserialize)]
pub struct EntityType {
@ -24,8 +22,6 @@ pub struct EntityType {
pub mob: Option<bool>,
/// Maximum number of this entity type allowed per chunk, if capped.
pub limit_per_chunk: Option<i32>,
/// Loot table dropped by this entity on death, if any.
pub loot_table: Option<LootTableStruct>,
/// Whether this entity can be summoned by the `/summon` command.
pub summonable: bool,
/// Whether this entity is immune to fire damage.
@ -182,14 +178,6 @@ impl ToTokens for NamedEntityType<'_> {
let dimension0 = entity.dimension[0];
let dimension1 = entity.dimension[1];
let spawn_dimensions_scale = entity.spawn_dimensions_scale;
let loot_table = if let Some(table) = &entity.loot_table {
let table_tokens = table.to_token_stream();
quote! { Some(#table_tokens) }
} else {
quote! { None }
};
let experience_reward = entity.experience_reward.unwrap_or(0);
let client_tracking_range = entity.client_tracking_range;
let update_interval = entity.update_interval;
@ -212,7 +200,6 @@ impl ToTokens for NamedEntityType<'_> {
client_tracking_range: #client_tracking_range,
update_interval: #update_interval,
track_deltas: #track_deltas,
loot_table: #loot_table,
dimension: [#dimension0, #dimension1], // Correctly construct the array
eye_height: #eye_height,
spawn_dimensions_scale: #spawn_dimensions_scale,
@ -264,7 +251,6 @@ pub fn build() -> TokenStream {
use crate::tag::RegistryKey;
use crate::attributes::Attributes;
use crate::sound::Sound;
use pumpkin_util::loot_table::*;
use pumpkin_util::HeightMap;
use pumpkin_util::math::boundingbox::BoundingBox;
use pumpkin_util::math::vector3::Vector3;
@ -287,7 +273,6 @@ pub fn build() -> TokenStream {
pub client_tracking_range: u32,
pub update_interval: u32,
pub track_deltas: bool,
pub loot_table: Option<LootTable>,
pub dimension: [f32; 2],
pub eye_height: f32,
pub spawn_dimensions_scale: f32,

View File

@ -12,6 +12,7 @@ pub fn build() -> TokenStream {
let mut variants = TokenStream::new();
let mut from_name_match = TokenStream::new();
let mut to_name_match = TokenStream::new();
for event in &game_events {
let ident = format_ident!("{}", event.to_pascal_case());
@ -22,6 +23,9 @@ pub fn build() -> TokenStream {
from_name_match.extend(quote! {
#event | #namespaced => Some(Self::#ident),
});
to_name_match.extend(quote! {
Self::#ident => #event,
});
}
quote! {
@ -31,6 +35,13 @@ pub fn build() -> TokenStream {
}
impl GameEvent {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
#to_name_match
}
}
#[must_use]
pub fn from_name(name: &str) -> Option<Self> {
match name {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,567 @@
use std::{fs, path::Path};
use heck::ToShoutySnakeCase;
use proc_macro2::{Span, TokenStream};
use pumpkin_util::loot_table::{LootBonusFormula, LootCondition};
use quote::{format_ident, quote};
use serde::Deserialize;
use syn::LitStr;
/// `rolls` can be a bare float or an object with `type/min/max`.
#[derive(Deserialize, Clone, Debug)]
#[serde(untagged)]
enum RollsStruct {
Constant(f32),
Provider {
#[allow(dead_code)]
#[serde(rename = "type")]
provider_type: String,
#[allow(dead_code)]
#[serde(default)]
min: f32,
#[serde(default)]
max: f32,
},
}
impl RollsStruct {
fn min(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { min, .. } => min.round() as i32,
}
}
fn max(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { max, .. } => max.round() as i32,
}
}
}
/// A `set_count` count provider (uniform or constant).
#[derive(Deserialize, Clone, Debug)]
#[serde(untagged)]
enum CountStruct {
Constant(f32),
Provider {
#[serde(rename = "type")]
#[allow(dead_code)]
provider_type: String,
#[serde(default)]
min: f32,
#[serde(default)]
max: f32,
},
}
impl CountStruct {
fn min(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { min, .. } => min.round() as i32,
}
}
fn max(&self) -> i32 {
match self {
Self::Constant(v) => v.round() as i32,
Self::Provider { max, .. } => max.round() as i32,
}
}
}
#[derive(Deserialize, Clone, Debug)]
struct PredicateStruct {
#[serde(default)]
items: Option<serde_json::Value>,
#[serde(default)]
predicates: Option<serde_json::Value>,
}
#[derive(Deserialize, Clone, Debug)]
struct ConditionStruct {
#[serde(default)]
condition: String,
#[allow(dead_code)]
#[serde(default)]
enchantment: Option<String>,
#[allow(dead_code)]
#[serde(default)]
chances: Option<Vec<f32>>,
#[serde(default)]
predicate: Option<PredicateStruct>,
#[serde(default)]
term: Option<Box<ConditionStruct>>,
#[serde(default)]
terms: Option<Vec<ConditionStruct>>,
}
fn parse_condition(cond: &ConditionStruct) -> LootCondition {
match cond.condition.as_str() {
"minecraft:survives_explosion" => LootCondition::SurvivesExplosion,
"minecraft:killed_by_player" => LootCondition::KilledByPlayer,
"minecraft:match_tool" => {
if let Some(pred) = &cond.predicate {
if let Some(items_val) = &pred.items {
let is_shears = match items_val {
serde_json::Value::String(s) => s.contains("shears"),
serde_json::Value::Array(arr) => arr
.iter()
.any(|v| v.as_str().is_some_and(|s| s.contains("shears"))),
_ => false,
};
if is_shears {
return LootCondition::Shears;
}
}
if let Some(pred_val) = &pred.predicates {
let s = pred_val.to_string();
if s.contains("silk_touch") {
return LootCondition::SilkTouch;
}
}
}
LootCondition::None
}
"minecraft:any_of" => {
if let Some(terms) = &cond.terms {
let has_silk = terms
.iter()
.any(|t| parse_condition(t) == LootCondition::SilkTouch);
let has_shears = terms
.iter()
.any(|t| parse_condition(t) == LootCondition::Shears);
if has_silk && has_shears {
return LootCondition::SilkTouchOrShears;
} else if has_silk {
return LootCondition::SilkTouch;
} else if has_shears {
return LootCondition::Shears;
}
}
LootCondition::None
}
"minecraft:inverted" => {
if let Some(term) = &cond.term {
match parse_condition(term) {
LootCondition::SilkTouch => LootCondition::NoSilkTouch,
LootCondition::Shears => LootCondition::NoSilkTouchOrShears,
LootCondition::SilkTouchOrShears => LootCondition::NoSilkTouchOrShears,
_ => LootCondition::None,
}
} else {
LootCondition::None
}
}
_ => LootCondition::None,
}
}
#[derive(Deserialize, Clone, Debug)]
struct BonusParameterStruct {
#[serde(rename = "bonusMultiplier", default)]
bonus_multiplier: Option<i32>,
#[serde(default)]
extra: Option<i32>,
#[serde(default)]
probability: Option<f32>,
}
#[derive(Deserialize, Clone, Debug)]
struct EntryFunctionStruct {
function: String,
#[serde(default)]
formula: Option<String>,
#[serde(default)]
parameters: Option<BonusParameterStruct>,
count: Option<CountStruct>,
}
/// A single entry inside a pool.
#[derive(Deserialize, Clone, Debug)]
struct PoolEntryStruct {
#[serde(rename = "type")]
entry_type: String,
/// Item name (only for `minecraft:item`).
name: Option<String>,
/// Weight (default 1 if absent).
#[serde(default = "default_weight")]
weight: i32,
/// Optional list of functions.
#[serde(default)]
functions: Vec<EntryFunctionStruct>,
/// Optional list of conditions.
#[serde(default)]
conditions: Vec<ConditionStruct>,
/// Optional list of child entries.
#[serde(default)]
children: Vec<PoolEntryStruct>,
}
fn default_weight() -> i32 {
1
}
#[derive(Deserialize, Clone, Debug)]
struct PoolStruct {
#[serde(default)]
entries: Vec<PoolEntryStruct>,
#[serde(default = "default_rolls")]
rolls: RollsStruct,
#[serde(default)]
conditions: Vec<ConditionStruct>,
}
fn default_rolls() -> RollsStruct {
RollsStruct::Constant(1.0)
}
/// Top-level chest loot table JSON.
#[derive(Deserialize, Clone, Debug)]
struct ChestLootTableJson {
#[serde(default)]
pools: Vec<PoolStruct>,
}
/// Convert a relative path (e.g. `"chests/trial_chambers/entrance"` or `"archaeology/desert_pyramid"`)
/// to a Minecraft namespaced key (e.g. `"minecraft:chests/trial_chambers/entrance"`).
fn path_to_key(relative: &str) -> String {
format!("minecraft:{relative}")
}
/// Convert a file stem path to a valid Rust SCREAMING_SNAKE_CASE identifier prefix.
/// e.g. `"chests/trial_chambers/entrance"` -> `"CHESTS_TRIAL_CHAMBERS_ENTRANCE"`
fn path_to_ident(relative: &str) -> String {
relative.replace('/', "_").to_shouty_snake_case()
}
struct ParsedEntry {
item: String,
weight: i32,
min_count: i32,
max_count: i32,
condition: LootCondition,
bonus_formula: Option<LootBonusFormula>,
}
fn extract_entries(
entry: &PoolEntryStruct,
inherited_condition: LootCondition,
out: &mut Vec<ParsedEntry>,
empty_weight: &mut i32,
) {
let mut entry_cond = inherited_condition;
for c in &entry.conditions {
let parsed = parse_condition(c);
if parsed != LootCondition::None {
if entry_cond == LootCondition::NoSilkTouch
|| entry_cond == LootCondition::NoSilkTouchOrShears
{
// Preserve the NoSilkTouch constraint
} else {
entry_cond = parsed;
}
}
}
match entry.entry_type.as_str() {
"minecraft:empty" => {
*empty_weight += entry.weight;
}
"minecraft:item" => {
if let Some(name) = &entry.name {
let (min_count, max_count) = entry
.functions
.iter()
.find(|f| f.function == "minecraft:set_count")
.and_then(|f| f.count.as_ref())
.map(|c| (c.min(), c.max()))
.unwrap_or((1, 1));
let bonus_formula = entry.functions.iter().find_map(|f| {
if f.function == "minecraft:apply_bonus" {
match f.formula.as_deref() {
Some("minecraft:ore_drops") => Some(LootBonusFormula::OreDrops),
Some("minecraft:uniform_bonus_count") => {
let mult = f
.parameters
.as_ref()
.and_then(|p| p.bonus_multiplier)
.unwrap_or(1);
Some(LootBonusFormula::UniformBonusCount(mult))
}
Some("minecraft:binomial_with_bonus_count") => {
let extra =
f.parameters.as_ref().and_then(|p| p.extra).unwrap_or(0);
let prob = f
.parameters
.as_ref()
.and_then(|p| p.probability)
.unwrap_or(0.0);
Some(LootBonusFormula::BinomialWithBonusCount {
extra,
probability: prob,
})
}
_ => None,
}
} else {
None
}
});
out.push(ParsedEntry {
item: name.clone(),
weight: entry.weight,
min_count,
max_count,
condition: entry_cond,
bonus_formula,
});
}
}
"minecraft:alternatives" => {
let mut saw_silk = false;
let mut saw_shears = false;
for child in &entry.children {
let mut child_cond = LootCondition::None;
for c in &child.conditions {
let parsed = parse_condition(c);
if parsed != LootCondition::None {
child_cond = parsed;
}
}
let effective_cond = if child_cond == LootCondition::SilkTouch {
saw_silk = true;
LootCondition::SilkTouch
} else if child_cond == LootCondition::Shears {
saw_shears = true;
LootCondition::Shears
} else if child_cond == LootCondition::SilkTouchOrShears {
saw_silk = true;
saw_shears = true;
LootCondition::SilkTouchOrShears
} else if saw_silk && saw_shears {
LootCondition::NoSilkTouchOrShears
} else if saw_silk {
LootCondition::NoSilkTouch
} else if saw_shears {
LootCondition::NoSilkTouchOrShears
} else {
entry_cond
};
extract_entries(child, effective_cond, out, empty_weight);
}
}
"minecraft:sequence" | "minecraft:group" => {
for child in &entry.children {
extract_entries(child, entry_cond, out, empty_weight);
}
}
_ => {}
}
}
fn condition_to_tokens(cond: LootCondition) -> TokenStream {
match cond {
LootCondition::None => quote! { LootCondition::None },
LootCondition::SilkTouch => quote! { LootCondition::SilkTouch },
LootCondition::NoSilkTouch => quote! { LootCondition::NoSilkTouch },
LootCondition::Shears => quote! { LootCondition::Shears },
LootCondition::SilkTouchOrShears => quote! { LootCondition::SilkTouchOrShears },
LootCondition::NoSilkTouchOrShears => quote! { LootCondition::NoSilkTouchOrShears },
LootCondition::SurvivesExplosion => quote! { LootCondition::SurvivesExplosion },
LootCondition::KilledByPlayer => quote! { LootCondition::KilledByPlayer },
}
}
fn bonus_to_tokens(bonus: Option<LootBonusFormula>) -> TokenStream {
match bonus {
None => quote! { None },
Some(LootBonusFormula::OreDrops) => {
quote! { Some(LootBonusFormula::OreDrops) }
}
Some(LootBonusFormula::UniformBonusCount(mult)) => {
quote! { Some(LootBonusFormula::UniformBonusCount(#mult)) }
}
Some(LootBonusFormula::BinomialWithBonusCount { extra, probability }) => {
quote! { Some(LootBonusFormula::BinomialWithBonusCount { extra: #extra, probability: #probability }) }
}
}
}
/// Emit static entry arrays and pool literals for one table.
/// Returns the list of `LootPool` literals (one per pool).
fn emit_table(
prefix: &str,
table: &ChestLootTableJson,
tokens: &mut TokenStream,
) -> Vec<TokenStream> {
let mut pool_literals = Vec::new();
for (pool_idx, pool) in table.pools.iter().enumerate() {
let min_rolls = pool.rolls.min();
let max_rolls = pool.rolls.max();
let mut pool_cond = LootCondition::None;
for c in &pool.conditions {
let parsed = parse_condition(c);
if parsed != LootCondition::None {
pool_cond = parsed;
}
}
let mut parsed_entries = Vec::new();
let mut empty_weight: i32 = 0;
for entry in &pool.entries {
extract_entries(
entry,
LootCondition::None,
&mut parsed_entries,
&mut empty_weight,
);
}
let entry_literals: Vec<TokenStream> = parsed_entries
.iter()
.map(|e| {
let name_lit = LitStr::new(&e.item, Span::call_site());
let weight = e.weight;
let min_count = e.min_count;
let max_count = e.max_count;
let cond_tokens = condition_to_tokens(e.condition);
let bonus_tokens = bonus_to_tokens(e.bonus_formula);
quote! {
LootEntry {
item: #name_lit,
weight: #weight,
min_count: #min_count,
max_count: #max_count,
condition: #cond_tokens,
bonus_formula: #bonus_tokens,
}
}
})
.collect();
// Emit the entries static array.
let entries_ident = format_ident!("{}_POOL{}_ENTRIES", prefix, pool_idx);
tokens.extend(quote! {
static #entries_ident: &[LootEntry] = &[#(#entry_literals),*];
});
let pool_cond_tokens = condition_to_tokens(pool_cond);
pool_literals.push(quote! {
LootPool {
entries: #entries_ident,
min_rolls: #min_rolls,
max_rolls: #max_rolls,
empty_weight: #empty_weight,
condition: #pool_cond_tokens,
}
});
}
pool_literals
}
/// Recursively collect all `*.json` files under `dir`, returning a vec of
/// `(relative_stem_path, parsed_table)`.
fn collect_json_files(base: &Path, dir: &Path) -> Vec<(String, ChestLootTableJson)> {
let mut result = Vec::new();
let entries = match fs::read_dir(dir) {
Ok(e) => e,
Err(e) => panic!("failed to read directory {}: {e}", dir.display()),
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
result.extend(collect_json_files(base, &path));
} else if path.extension().is_some_and(|ext| ext == "json") {
let relative = path
.strip_prefix(base)
.unwrap()
.with_extension("")
.to_string_lossy()
.to_string();
let content = match fs::read_to_string(&path) {
Ok(c) => c,
Err(e) => panic!("failed to read {}: {e}", path.display()),
};
let table: ChestLootTableJson = match serde_json::from_str(&content) {
Ok(t) => t,
Err(e) => panic!("failed to parse {}: {e}", path.display()),
};
result.push((relative, table));
}
}
result
}
/// Read every loot JSON from `../../assets/datapacks/26_2/data/minecraft/loot_table/` (recursively)
/// and emit a `pumpkin-data/src/generated/chest_loot.rs` with static constants
/// and a `get_chest_loot_table(key) -> Option<&'static ChestLootTable>` function.
pub fn build() -> TokenStream {
let base = Path::new("../../assets/datapacks/26_2/data/minecraft/loot_table");
// Collect all JSON files recursively, sorted for deterministic output.
let mut files: Vec<(String, ChestLootTableJson)> = collect_json_files(base, base);
files.sort_by(|a, b| a.0.cmp(&b.0));
let mut all_tokens = TokenStream::new();
// Emit one set of statics per file
let mut table_idents = Vec::new();
let mut table_keys = Vec::new();
let mut short_table_keys = Vec::new();
for (relative_path, table) in &files {
let prefix = path_to_ident(relative_path);
let key = path_to_key(relative_path);
let table_ident = format_ident!("{}", prefix);
let pool_tokens = emit_table(&prefix, table, &mut all_tokens);
let pools_ident = format_ident!("{}_POOLS", prefix);
all_tokens.extend(quote! {
static #pools_ident: &[LootPool] = &[#(#pool_tokens),*];
pub static #table_ident: LootTable = LootTable { pools: #pools_ident };
});
table_idents.push(table_ident.clone());
table_keys.push(LitStr::new(&key, Span::call_site()));
short_table_keys.push(LitStr::new(relative_path, Span::call_site()));
}
// Emit get_loot_table and get_chest_loot_table
all_tokens.extend(quote! {
#[must_use]
pub fn get_loot_table(key: &str) -> Option<&'static LootTable> {
match key {
#(#table_keys | #short_table_keys => Some(&#table_idents),)*
_ => None,
}
}
#[must_use]
pub fn get_chest_loot_table(key: &str) -> Option<&'static LootTable> {
get_loot_table(key)
}
});
quote! {
pub use pumpkin_util::loot_table::*;
#all_tokens
}
}

View File

@ -33,7 +33,6 @@ mod biome;
mod bitsets;
mod block;
mod carver;
pub mod chest_loot;
mod chunk_gen_settings;
mod chunk_status;
mod chunk_view_lut;
@ -55,7 +54,7 @@ mod game_event;
mod game_rules;
mod item;
mod jukebox_song;
pub mod loot;
pub mod loot_table;
mod map_color;
mod map_decoration;
mod message_type;
@ -163,7 +162,7 @@ pub fn main() {
"configured_features_generated.rs",
),
(carver::build, "carver.rs"),
(chest_loot::build, "chest_loot.rs"),
(loot_table::build, "loot_table.rs"),
(map_color::build, "map_color.rs"),
(map_decoration::build, "map_decoration.rs"),
(dye_color::build, "dye_color.rs"),