chore: next round of fixes

This commit is contained in:
Alexander Medvedev 2026-08-28 22:32:50 +02:00
parent 9e9f1b5784
commit d439d5e22e
61 changed files with 3745 additions and 1007 deletions

1
Cargo.lock generated
View File

@ -3518,6 +3518,7 @@ dependencies = [
"async-compression",
"bitflags 2.13.1",
"bytes",
"cesu8",
"cfb8",
"flate2",
"hybrid-array",

File diff suppressed because one or more lines are too long

View File

@ -123,6 +123,16 @@ impl FromResourceLocation for &'static Block {
}
impl Block {
#[must_use]
pub const fn get_speed_factor(&self) -> f32 {
self.velocity_multiplier
}
#[must_use]
pub const fn get_jump_velocity_multiplier(&self) -> f32 {
self.jump_velocity_multiplier
}
pub(crate) fn shape_offset_delta(&self, pos: &BlockPos) -> Vector3<f64> {
let Some(shape_offset) = self.shape_offset() else {
return Vector3::new(0.0, 0.0, 0.0);

View File

@ -1541,13 +1541,21 @@ fn build_configured_features()
map.insert(
pumpkin_data::configured_feature::ConfiguredFeature::EndGatewayDelayed,
ConfiguredFeature::EndGateway(
crate::generation::feature::features::end_gateway::EndGatewayFeature {},
crate::generation::feature::features::end_gateway::EndGatewayFeature {
exit: None,
exact: false,
},
),
);
map.insert(
pumpkin_data::configured_feature::ConfiguredFeature::EndGatewayReturn,
ConfiguredFeature::EndGateway(
crate::generation::feature::features::end_gateway::EndGatewayFeature {},
crate::generation::feature::features::end_gateway::EndGatewayFeature {
exit: Some(pumpkin_util::math::position::BlockPos::new(
100i32, 50i32, 0i32,
)),
exact: true,
},
),
);
map.insert(

View File

@ -6550,7 +6550,44 @@ impl EntityType {
};
pub const PLAYER: EntityType = EntityType {
id: 156,
attributes: &[],
attributes: &[
(Attributes::AIR_DRAG_MODIFIER, 1f64),
(Attributes::ARMOR, 0f64),
(Attributes::ARMOR_TOUGHNESS, 0f64),
(Attributes::ATTACK_DAMAGE, 1f64),
(Attributes::ATTACK_KNOCKBACK, 0f64),
(Attributes::ATTACK_SPEED, 4f64),
(Attributes::BELOW_NAME_DISTANCE, 10f64),
(Attributes::BLOCK_BREAK_SPEED, 1f64),
(Attributes::BLOCK_INTERACTION_RANGE, 4.5f64),
(Attributes::BOUNCINESS, 0f64),
(Attributes::BURNING_TIME, 1f64),
(Attributes::CAMERA_DISTANCE, 4f64),
(Attributes::EXPLOSION_KNOCKBACK_RESISTANCE, 0f64),
(Attributes::ENTITY_INTERACTION_RANGE, 3f64),
(Attributes::FALL_DAMAGE_MULTIPLIER, 1f64),
(Attributes::FRICTION_MODIFIER, 1f64),
(Attributes::GRAVITY, 0.08f64),
(Attributes::JUMP_STRENGTH, 0.41999998688697815f64),
(Attributes::KNOCKBACK_RESISTANCE, 0f64),
(Attributes::LUCK, 0f64),
(Attributes::MAX_ABSORPTION, 0f64),
(Attributes::MAX_HEALTH, 20f64),
(Attributes::MINING_EFFICIENCY, 0f64),
(Attributes::MOVEMENT_EFFICIENCY, 0f64),
(Attributes::MOVEMENT_SPEED, 0.1f64),
(Attributes::NAME_TAG_DISTANCE, 64f64),
(Attributes::OXYGEN_BONUS, 0f64),
(Attributes::SAFE_FALL_DISTANCE, 3f64),
(Attributes::SCALE, 1f64),
(Attributes::SNEAKING_SPEED, 0.3f64),
(Attributes::STEP_HEIGHT, 0.6f64),
(Attributes::SUBMERGED_MINING_SPEED, 0.2f64),
(Attributes::SWEEPING_DAMAGE_RATIO, 0f64),
(Attributes::WATER_MOVEMENT_EFFICIENCY, 0f64),
(Attributes::WAYPOINT_TRANSMIT_RANGE, 0f64),
(Attributes::WAYPOINT_RECEIVE_RANGE, 0f64),
],
experience_reward: 0u32,
hurt_sound: None,
attackable: None,

View File

@ -67641,7 +67641,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\t\titem_tags\x08\x02\x11minecraft:is_food\n\x0Eminecraft:tags\t\x04tags\x08\x02\x11minecraft:is_food\0\n\x0Fitem_properties\x08\x0Ecreative_group\0\x03\x11enchantable_value\0\x01\x0Fstacked_by_data\0\x03\x06damage\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x04none\x03\x11creative_category\x04\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\x03\ruse_animation\x02\x03\x0Emax_stack_size\x80\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x05apple\0\0\x01\x17can_destroy_in_creative\x01\x01\x04foil\0\x01\rhand_equipped\0\x01\x0Eshould_despawn\x01\x03\x0Cuse_duration@\0\n\x17minecraft:use_animation\x08\x05value\x03eat\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\x01\x05\x11movement_modifier33\xB3>\x05\x0Cuse_duration\xCD\xCC\xCC?\x08\x0Bstart_using\x06always\0\n\x0Eminecraft:food\x03\tnutrition\x08\x05\x13saturation_modifier\x9A\x99\x99>\n\x11using_converts_to\0\x01\x0Ecan_always_eat\0\0\n\x16minecraft:display_name\x08\x05value\x0Fitem.apple.name\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\t\titem_tags\x08\x02\x11minecraft:is_food\n\x17minecraft:use_modifiers\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\x01\x05\x11movement_modifier33\xB3>\x05\x0Cuse_duration\xCD\xCC\xCC?\0\n\x0Eminecraft:tags\t\x04tags\x08\x02\x11minecraft:is_food\0\n\x17minecraft:use_animation\x08\x05value\x03eat\0\n\x0Fitem_properties\x03\x0Emax_stack_size\x80\x01\x01\x0Fstacked_by_data\0\x01\x17can_destroy_in_creative\x01\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\x08\x0Ecreative_group\0\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration@\x03\x0Bframe_count\x02\x08\x10enchantable_slot\x04none\x03\x11creative_category\x04\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x03\x06damage\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x05apple\0\0\x01\rhand_equipped\0\x01\x12hidden_in_commands\x02\x01\x04foil\0\x03\ruse_animation\x02\0\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\tnutrition\x08\n\x11using_converts_to\0\0\n\x16minecraft:display_name\x08\x05value\x0Fitem.apple.name\0\0\0" } ;
pub const ARCHER_POTTERY_SHERD: Self = Self {
id: 671,
registry_key: "minecraft:archer_pottery_sherd",
@ -67726,7 +67726,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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x08\rcooldown_type\0\x03\ron_use_action\x01\x03\tnutrition\n\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\x01\x0Ecan_always_eat\0\0\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\ron_use_action\x01\x08\rcooldown_type\0\x03\rcooldown_time\0\x03\tnutrition\n\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\x19?\x01\x0Ecan_always_eat\0\0\0\0" } ;
pub const BALLOON: Self = Self {
id: 612,
registry_key: "minecraft:balloon",
@ -67979,7 +67979,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\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x03\ron_use_action\x01\x08\rcooldown_type\0\x03\tnutrition\x06\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\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\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x06\x03\rcooldown_time\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x99>\0\0\0" } ;
pub const BEEHIVE: Self = Self {
id: -219,
registry_key: "minecraft:beehive",
@ -67987,9 +67987,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\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x03\tnutrition\x02\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\0\x08\rcooldown_type\0\0\x03\x16minecraft:use_duration@\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\x03\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\x04bowl\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\x0C\x01\x0Ecan_always_eat\0\0\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\x05\x13saturation_modifier\x9A\x99\x19?\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\tnutrition\x02\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\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\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\x0Bcrop_result\x12minecraft:beetroot\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\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\x04bowl\x03\rcooldown_time\0\x08\rcooldown_type\0\x03\tnutrition\x0C\0\x03\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\0\0" } ;
pub const BELL: Self = Self {
id: -206,
registry_key: "minecraft:bell",
@ -68151,7 +68151,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\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\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\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\0\0\n\x0Fitem_properties\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\0\x01\rhand_equipped\0\x03\x06damage\0\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Cbundle_black\x08\x11bundle_open_front\x17bundle_black_open_front\x08\x10bundle_open_back\x16bundle_black_open_back\0\0\x03\ruse_animation\0\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x03\x0Bframe_count\x02\x01\x04foil\0\x01\x0Eliquid_clipped\0\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\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x08\x10enchantable_slot\x04none\x01\x0Eallow_off_hand\0\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x03\x0Cuse_duration\0\x03\x0Emax_stack_size\x02\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x08\x0Ecreative_group\0\x03\x06damage\0\x03\ruse_animation\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x17bundle_black_open_front\x08\x07default\x0Cbundle_black\x08\x10bundle_open_back\x16bundle_black_open_back\0\0\x03\x11enchantable_value\0\x01\rhand_equipped\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\t\rallowed_items\0\0\x03\tmax_slots\x80\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\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\0\0\0\0" } ;
pub const BLACK_CANDLE: Self = Self {
id: -428,
registry_key: "minecraft:black_candle",
@ -68327,7 +68327,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\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\x01\x04foil\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bbundle_blue\x08\x10bundle_open_back\x15bundle_blue_open_back\x08\x11bundle_open_front\x16bundle_blue_open_front\0\0\x01\x0Fstacked_by_data\0\x03\x0Bframe_count\x02\x03\x0Cuse_duration\0\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x02\x01\x12hidden_in_commands\x02\x08\x10enchantable_slot\x04none\x03\x06damage\0\x03\x11enchantable_value\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x08\x0Ecreative_group\0\x01\x17can_destroy_in_creative\x01\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\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 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\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\x18minecraft:max_stack_size\x01\x05value\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\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x0Fitem_properties\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x03\x06damage\0\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\x12hidden_in_commands\x02\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x03\x0Bframe_count\x02\x03\x0Emax_stack_size\x02\x03\ruse_animation\0\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x08\x0Ecreative_group\0\x03\x0Cuse_duration\0\x01\rhand_equipped\0\x03\x11enchantable_value\0\x03\x11creative_category\x06\x01\x0Fstacked_by_data\0\0\0\0" } ;
pub const BLUE_CANDLE: Self = Self {
id: -424,
registry_key: "minecraft:blue_candle",
@ -68566,8 +68566,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\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\n\x08\rcooldown_type\0\x03\ron_use_action\x01\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x19?\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\t\titem_tags\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x0Fitem_properties\x03\x0Cuse_duration\0\x03\x0Bframe_count\x02\x03\ruse_animation\0\x01\x0Eallow_off_hand\0\x01\x12hidden_in_commands\x02\x01\x17can_destroy_in_creative\x01\x05\x0Cmining_speed\0\0\x80?\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nbreeze_rod\0\0\x08\x10enchantable_slot\x04none\x01\x04foil\0\x01\x0Eshould_despawn\x01\x03\x06damage\0\x03\x0Emax_stack_size\x80\x01\x08\x0Ecreative_group\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x08\x01\rhand_equipped\x01\x03\x11enchantable_value\0\x01\x0Fstacked_by_data\0\0\n\x16minecraft:display_name\x08\x05value\x14item.breeze_rod.name\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\x03\tnutrition\n\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x19?\x01\x0Ecan_always_eat\0\x03\rcooldown_time\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\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\t\titem_tags\0\0\n\x16minecraft:display_name\x08\x05value\x14item.breeze_rod.name\0\n\x0Fitem_properties\x08\x10enchantable_slot\x04none\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\x03\x0Emax_stack_size\x80\x01\x01\x0Fstacked_by_data\0\x08\x0Ecreative_group\0\x03\x11creative_category\x08\x01\x17can_destroy_in_creative\x01\x01\rhand_equipped\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nbreeze_rod\0\0\x01\x04foil\0\x03\x06damage\0\x03\x0Bframe_count\x02\x01\x0Eliquid_clipped\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\0\0" } ;
pub const BREEZE_SPAWN_EGG: Self = Self {
id: 506,
registry_key: "minecraft:breeze_spawn_egg",
@ -68631,7 +68631,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\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\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\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!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x0Fitem_properties\x03\x0Bframe_count\x02\x01\rhand_equipped\0\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\x01\x0Fstacked_by_data\0\x01\x17can_destroy_in_creative\x01\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x16bundle_brown_open_back\x08\x07default\x0Cbundle_brown\x08\x11bundle_open_front\x17bundle_brown_open_front\0\0\x03\ruse_animation\0\x01\x0Eallow_off_hand\0\x03\x0Cuse_duration\0\x01\x04foil\0\x03\x06damage\0\x01\x12hidden_in_commands\x02\x03\x11enchantable_value\0\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\t\titem_tags\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x08\x10enchantable_slot\x04none\x01\x0Eallow_off_hand\0\x01\x04foil\0\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x03\x06damage\0\x03\x11enchantable_value\0\x01\rhand_equipped\0\x01\x12hidden_in_commands\x02\x03\x0Cuse_duration\0\x08\x0Ecreative_group\0\x01\x17can_destroy_in_creative\x01\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x03\x0Emax_stack_size\x02\x03\ruse_animation\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x17bundle_brown_open_front\x08\x10bundle_open_back\x16bundle_brown_open_back\x08\x07default\x0Cbundle_brown\0\0\x03\x11creative_category\x06\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\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\0\0" } ;
pub const BROWN_CANDLE: Self = Self {
id: -425,
registry_key: "minecraft:brown_candle",
@ -68807,7 +68807,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\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x03\x0Cuse_duration\0\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x11bundle_open_front\x08\x10bundle_open_back\x10bundle_open_back\x08\x07default\x06bundle\0\0\x01\x0Eshould_despawn\x01\x01\x0Eliquid_clipped\0\x08\x0Ecreative_group\0\x01\rhand_equipped\0\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x03\x11creative_category\x06\x03\x06damage\0\x03\x11enchantable_value\0\x03\ruse_animation\0\x01\x04foil\0\x08\x10enchantable_slot\x04none\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\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\t\titem_tags\0\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\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\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\n\x0Fitem_properties\x03\x11enchantable_value\0\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x06bundle\x08\x10bundle_open_back\x10bundle_open_back\x08\x11bundle_open_front\x11bundle_open_front\0\0\x08\x0Ecreative_group\0\x01\x04foil\0\x01\x0Eliquid_clipped\0\x03\x06damage\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x08\x10enchantable_slot\x04none\x01\rhand_equipped\0\0\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\t\titem_tags\0\0\0\0" } ;
pub const BURN_POTTERY_SHERD: Self = Self {
id: 675,
registry_key: "minecraft:burn_pottery_sherd",
@ -68871,7 +68871,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\x08\x0Fminecraft:block\x10minecraft:camera\n\x10minecraft:camera\x05\x13slide_away_duration\xCD\xCCL>\x05\x14shutter_screen_ratio\0\0\0?\x05\x17black_bars_screen_ratio\n\xD7\xA3=\x05\x13black_bars_duration\xCD\xCCL>\x05\x10picture_duration\0\0\x80?\x05\x10shutter_duration\xCD\xCCL>\0\x03\x16minecraft:use_duration\xC0\x9A\x0C\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\x17black_bars_screen_ratio\n\xD7\xA3=\x05\x10picture_duration\0\0\x80?\x05\x13slide_away_duration\xCD\xCCL>\x05\x13black_bars_duration\xCD\xCCL>\x05\x10shutter_duration\xCD\xCCL>\0\x03\x16minecraft:use_duration\xC0\x9A\x0C\0\0" } ;
pub const CAMPFIRE: Self = Self {
id: 601,
registry_key: "minecraft:campfire",
@ -68900,7 +68900,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\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\0\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\x08\rcooldown_type\0\x03\tnutrition\x06\x03\ron_use_action\x01\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?\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x19?\x03\tnutrition\x06\x08\rcooldown_type\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\x01\x0Ecan_always_eat\0\0\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\x11minecraft:carrots\0\0\0" } ;
pub const CARROT_ON_A_STICK: Self = Self {
id: 527,
registry_key: "minecraft:carrot_on_a_stick",
@ -69202,7 +69202,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\t\x07effects\n\x02\x03\x08duration<\x03\tamplifier\0\x05\x06chance\x9A\x99\x99>\x08\rdescriptionId\rpotion.hunger\x03\x02id\"\x08\x04name\x06hunger\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\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\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x99>\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\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x99>\x03\ron_use_action\x01\x03\tnutrition\x04\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x08\x11using_converts_to\0\t\x07effects\n\x02\x08\rdescriptionId\rpotion.hunger\x03\tamplifier\0\x08\x04name\x06hunger\x03\x08duration<\x03\x02id\"\x05\x06chance\x9A\x99\x99>\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const CHICKEN_SPAWN_EGG: Self = Self {
id: 439,
registry_key: "minecraft:chicken_spawn_egg",
@ -69322,7 +69322,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\tnutrition\x08\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\0\x08\rcooldown_type\x0Bchorusfruit\x01\x0Ecan_always_eat\x01\x08\x11using_converts_to\0\x03\rcooldown_time(\x05\x13saturation_modifier\x9A\x99\x99>\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time(\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\ron_use_action\0\x03\tnutrition\x08\x05\x13saturation_modifier\x9A\x99\x99>\x08\rcooldown_type\x0Bchorusfruit\x01\x0Ecan_always_eat\x01\0\0\0" } ;
pub const CHORUS_PLANT: Self = Self {
id: 240,
registry_key: "minecraft:chorus_plant",
@ -69547,7 +69547,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\n\x0Eminecraft:food\x03\tnutrition\x04\x08\x11using_converts_to\0\x05\x13saturation_modifier\xCD\xCC\xCC=\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\ron_use_action\x01\x03\rcooldown_time\0\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\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\n\x0Eminecraft:food\x03\ron_use_action\x01\x08\x11using_converts_to\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\x03\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\tnutrition\x04\0\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\0\0" } ;
pub const COD_BUCKET: Self = Self {
id: 367,
registry_key: "minecraft:cod_bucket",
@ -69674,14 +69674,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\rcooldown_time\0\x03\tnutrition\x10\x03\ron_use_action\x01\x05\x13saturation_modifier\xCD\xCCL?\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\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x08\rcooldown_type\0\x03\tnutrition\x0C\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\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x19?\0\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\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x19?\x01\x0Ecan_always_eat\0\x03\tnutrition\n\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x08\rcooldown_type\0\x03\ron_use_action\x01\0\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\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\x08\rcooldown_type\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x03\tnutrition\x0C\x03\rcooldown_time\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\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\rcooldown_type\0\x03\tnutrition\x10\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\xCD\xCCL?\x08\x11using_converts_to\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\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\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\x9A\x99\x19?\x03\tnutrition\n\x03\rcooldown_time\0\x08\x11using_converts_to\0\0\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\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCCL?\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\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\tnutrition\x04\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\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\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x03\tnutrition\x10\x08\x11using_converts_to\0\x03\rcooldown_time\0\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCCL?\x03\ron_use_action\x01\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x19?\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x03\rcooldown_time\0\x08\x11using_converts_to\0\x03\tnutrition\x0C\0\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\n\x0Eminecraft:food\x03\tnutrition\n\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x19?\x03\ron_use_action\x01\x08\x11using_converts_to\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\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\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x03\tnutrition\x0C\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\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCCL?\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCCL?\x08\x11using_converts_to\0\x03\tnutrition\x10\x03\ron_use_action\x01\0\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\x05\x13saturation_modifier\x9A\x99\x19?\x03\rcooldown_time\0\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\n\x03\ron_use_action\x01\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\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\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\x03\ron_use_action\x01\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCCL?\x03\rcooldown_time\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\ron_use_action\x01\x05\x13saturation_modifier\xCD\xCC\xCC=\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x04\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x08\rcooldown_type\0\0\0\0" } ;
pub const COPPER_AXE: Self = Self {
id: 750,
registry_key: "minecraft:copper_axe",
@ -69843,7 +69843,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\x14minecraft:durability\x03\x0Emax_durability\xFC\x02\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\0\n\x18minecraft:swing_duration\x05\x05value\x9A\x99Y?\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x08\x08category\x05spear\x05\x08duration\x9A\x99Y?\0\n\x17minecraft:use_modifiers\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x15item.copper_spear.use\x01\x0Femit_vibrations\0\x08\x0Bstart_using\x06always\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\x0Fdamage_modifier\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\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x14knockback_conditions\x02\x0Cmax_duration\xA5\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x13dismount_conditions\x02\x0Cmax_durationP\0\x05\tmin_speed\0\0@A\x05\x12min_relative_speed\0\0\0\0\0\x05\x11damage_multiplier\x85\xEBQ?\x05\rhitbox_margin\0\0\x80>\0\0\n\x16minecraft:display_name\x08\x05value\x16item.copper_spear.name\0\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\r\0\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\x10minecraft:damage\x02\x05value\x02\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\0\t\titem_tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Ccopper_spear\0\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x05\x0Cmining_speed\0\0\x80?\x01\rhand_equipped\x01\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x03\x11enchantable_value\x1A\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x01\x0Eallow_off_hand\0\x03\x06damage\x04\x01\x04foil\0\x08\x0Ecreative_group\0\x03\x11creative_category\x06\x08\x10enchantable_slot\x0Bmelee_spear\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Ditem.copper_spear.attack_miss\x08\nattack_hit\x1Citem.copper_spear.attack_hit\0\n\x18minecraft:max_stack_size\x01\x05value\x01\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\x10minecraft:damage\x02\x05value\x02\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\0\n\x16minecraft:display_name\x08\x05value\x16item.copper_spear.name\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\rhitbox_margin\0\0\x80>\n\x11damage_conditions\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\xFA\0\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\xA5\0\x05\tmin_speed33\xA3@\0\x05\x0Fdamage_modifier\0\0\0\0\n\x13dismount_conditions\x02\x0Cmax_durationP\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0@A\0\x05\x11damage_multiplier\x85\xEBQ?\x02\x05delay\r\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\x03\x0Emax_durability\xFC\x02\0\t\titem_tags\x08\x04\x15minecraft:copper_tier\x12minecraft:is_spear\n\x17minecraft:use_modifiers\x08\x0Bstart_sound\x15item.copper_spear.use\x08\x0Bstart_using\x06always\x05\x11movement_modifier\0\0\x80?\x01\x0Femit_vibrations\0\x05\x0Cuse_duration\0\xA0\x8CG\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\x08duration\x9A\x99Y?\x08\x04type\x06attack\x08\x08category\x05spear\0\n\x0Fitem_properties\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Ccopper_spear\0\0\x01\x12hidden_in_commands\x02\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x0Eallow_off_hand\0\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x0Bmelee_spear\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x03\x11creative_category\x06\x03\x06damage\x04\x03\x11enchantable_value\x1A\x01\x04foil\0\x05\x0Cmining_speed\0\0\x80?\x01\rhand_equipped\x01\0\n\x18minecraft:swing_duration\x05\x05value\x9A\x99Y?\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\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\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\r\0\0\0" } ;
pub const COPPER_SWORD: Self = Self {
id: 747,
registry_key: "minecraft:copper_sword",
@ -70208,7 +70208,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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x08\x0Ecreative_group\0\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x01\x12hidden_in_commands\x02\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\x04foil\0\x01\rhand_equipped\0\x03\x06damage\0\x01\x0Eshould_despawn\x01\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\x03\x11enchantable_value\0\x03\x0Emax_stack_size\x02\x03\x0Bframe_count\x02\x01\x17can_destroy_in_creative\x01\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x15bundle_cyan_open_back\x08\x11bundle_open_front\x16bundle_cyan_open_front\x08\x07default\x0Bbundle_cyan\0\0\x08\x10enchantable_slot\x04none\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\x0Cbanned_items\n\x04\x08\x04name\x15minecraft:shulker_box\0\x08\x04name\x1Cminecraft:undyed_shulker_box\0\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 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\x16minecraft:storage_item\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\t\rallowed_items\0\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\0\0\n\x0Fitem_properties\x05\x0Cmining_speed\0\0\x80?\x03\x06damage\0\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x02\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x01\x0Eliquid_clipped\0\x08\x10enchantable_slot\x04none\x03\x0Cuse_duration\0\x01\rhand_equipped\0\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\x01\x12hidden_in_commands\x02\x03\x11creative_category\x06\x03\x11enchantable_value\0\x01\x04foil\0\x03\ruse_animation\0\x01\x0Eallow_off_hand\0\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\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 CYAN_CANDLE: Self = Self {
id: -422,
registry_key: "minecraft:cyan_candle",
@ -70930,7 +70930,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\x12minecraft:cooldown\x08\x04type\x06attack\x08\x08category\x05spear\x05\x08durationff\x86?\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\x0Battack_miss\x1Eitem.diamond_spear.attack_miss\x08\nattack_hit\x1Ditem.diamond_spear.attack_hit\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\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x11minecraft:diamond\0\0\0\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\n\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_duration\x82\0\0\n\x13dismount_conditions\x02\x0Cmax_duration<\0\x05\tmin_speed\0\0 A\x05\x12min_relative_speed\0\0\0\0\0\x05\x0Fdamage_modifier\0\0\0\0\x05\x11damage_multiplier\x9A\x99\x89?\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\x02\x05delay\n\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\x02\x0Cmax_duration\xC8\0\0\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x18minecraft:swing_duration\x05\x05valueff\x86?\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xB0\x18\0\n\x10minecraft:damage\x02\x05value\x04\0\0\n\x0Fitem_properties\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x0Bmelee_spear\x03\x06damage\x08\n\x0Eminecraft:icon\n\x08textures\x08\x07default\rdiamond_spear\0\0\x03\x0Bframe_count\x02\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x03\x11enchantable_value\x14\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x04foil\0\x03\x0Emax_stack_size\x02\x01\x12hidden_in_commands\x02\x01\rhand_equipped\x01\x03\x11creative_category\x06\x01\x0Eliquid_clipped\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\n\x16minecraft:display_name\x08\x05value\x17item.diamond_spear.name\0\n\x0Eminecraft:tags\t\x04tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_sound\x16item.diamond_spear.use\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_using\x06always\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\x01\x05value\n\x08\x04slot\x0Bmelee_spear\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x08\x04type\x06attack\x05\x08durationff\x86?\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xB0\x18\0\n\x10minecraft:damage\x02\x05value\x04\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x05\rhitbox_margin\0\0\x80>\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\rhitbox_margin\0\0\x80>\x05\x0Fdamage_modifier\0\0\0\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x13dismount_conditions\x05\tmin_speed\0\0 A\x02\x0Cmax_duration<\0\x05\x12min_relative_speed\0\0\0\0\0\n\x11damage_conditions\x02\x0Cmax_duration\xC8\0\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\0\x02\x05delay\n\0\x05\x11damage_multiplier\x9A\x99\x89?\n\x14knockback_conditions\x02\x0Cmax_duration\x82\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\0\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\x08\x06\x16minecraft:diamond_tier\x1Dminecraft:transformable_items\x12minecraft:is_spear\n\x0Fitem_properties\x01\x0Eshould_despawn\x01\x03\x11creative_category\x06\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\x03\x0Emax_stack_size\x02\x08\x10enchantable_slot\x0Bmelee_spear\x01\x17can_destroy_in_creative\x01\x08\x0Ecreative_group\0\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\x14\x01\x04foil\0\x01\rhand_equipped\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\rdiamond_spear\0\0\x03\x06damage\x08\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Eitem.diamond_spear.attack_miss\x08\nattack_hit\x1Ditem.diamond_spear.attack_hit\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\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x11minecraft:diamond\0\0\0\n\x18minecraft:swing_duration\x05\x05valueff\x86?\0\n\x17minecraft:use_modifiers\x08\x0Bstart_using\x06always\x08\x0Bstart_sound\x16item.diamond_spear.use\x05\x0Cuse_duration\0\xA0\x8CG\x05\x11movement_modifier\0\0\x80?\x01\x0Femit_vibrations\0\0\n\x16minecraft:display_name\x08\x05value\x17item.diamond_spear.name\0\0\0" } ;
pub const DIAMOND_SWORD: Self = Self {
id: 318,
registry_key: "minecraft:diamond_sword",
@ -71085,7 +71085,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\n\x0Eminecraft:food\x08\x11using_converts_to\0\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\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\tnutrition\x02\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration \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\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\xCD\xCC\xCC=\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x03\tnutrition\x02\0\x03\x16minecraft:use_duration \0\0" } ;
pub const DRIED_KELP_BLOCK: Self = Self {
id: -139,
registry_key: "minecraft:dried_kelp_block",
@ -72031,7 +72031,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\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x03\rcooldown_time\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\t\x07effects\n\x08\x03\x08duration<\x08\x04name\x0Cregeneration\x03\tamplifier\x02\x05\x06chance\0\0\x80?\x03\x02id\x14\x08\rdescriptionId\x13potion.regeneration\0\x05\x06chance\0\0\x80?\x08\rdescriptionId\x11potion.absorption\x03\x08duration\xF0\x01\x03\tamplifier\x06\x03\x02id,\x08\x04name\nabsorption\0\x05\x06chance\0\0\x80?\x08\rdescriptionId\x11potion.resistance\x03\tamplifier\0\x08\x04name\nresistance\x03\x02id\x16\x03\x08duration\xD8\x04\0\x08\x04name\x0Ffire_resistance\x03\x02id\x18\x03\x08duration\xD8\x04\x03\tamplifier\0\x08\rdescriptionId\x15potion.fireResistance\x05\x06chance\0\0\x80?\0\x03\tnutrition\x08\x05\x13saturation_modifier\x9A\x99\x99?\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\x01\0\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\n\x0Eminecraft:food\x01\x0Ecan_always_eat\x01\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99?\x08\x11using_converts_to\0\x03\tnutrition\x08\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\t\x07effects\n\x08\x08\rdescriptionId\x13potion.regeneration\x05\x06chance\0\0\x80?\x03\tamplifier\x02\x03\x08duration<\x03\x02id\x14\x08\x04name\x0Cregeneration\0\x03\tamplifier\x06\x03\x02id,\x05\x06chance\0\0\x80?\x08\x04name\nabsorption\x08\rdescriptionId\x11potion.absorption\x03\x08duration\xF0\x01\0\x05\x06chance\0\0\x80?\x08\rdescriptionId\x11potion.resistance\x08\x04name\nresistance\x03\x08duration\xD8\x04\x03\x02id\x16\x03\tamplifier\0\0\x08\rdescriptionId\x15potion.fireResistance\x03\x08duration\xD8\x04\x03\tamplifier\0\x08\x04name\x0Ffire_resistance\x05\x06chance\0\0\x80?\x03\x02id\x18\0\x03\rcooldown_time\0\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\x01\x0Eminecraft:foil\x01\0\0" } ;
pub const ENCHANTING_TABLE: Self = Self {
id: 116,
registry_key: "minecraft:enchanting_table",
@ -72606,7 +72606,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:seed\x01\x1Aplant_at_any_solid_surface\x01\x08\rplant_at_face\x04down\x08\x0Bcrop_result\x14minecraft:cave_vines\t\x08plant_at\x08\x04\ncave_vines\x1Ccave_vines_head_with_berries\0\n\x0Eminecraft:food\x08\rcooldown_type\0\x03\ron_use_action\x01\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\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\tnutrition\x04\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:seed\x08\rplant_at_face\x04down\x08\x0Bcrop_result\x14minecraft:cave_vines\x01\x1Aplant_at_any_solid_surface\x01\t\x08plant_at\x08\x04\ncave_vines\x1Ccave_vines_head_with_berries\0\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\ron_use_action\x01\x03\tnutrition\x04\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\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x99>\x08\rcooldown_type\0\0\0\0" } ;
pub const GLOW_FRAME: Self = Self {
id: 636,
registry_key: "minecraft:glow_frame",
@ -72705,7 +72705,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\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x08\x11using_converts_to\0\x03\rcooldown_time\0\t\x07effects\n\x04\x08\rdescriptionId\x13potion.regeneration\x03\x08duration\n\x03\tamplifier\x02\x03\x02id\x14\x05\x06chance\0\0\x80?\x08\x04name\x0Cregeneration\0\x03\tamplifier\0\x05\x06chance\0\0\x80?\x08\x04name\nabsorption\x08\rdescriptionId\x11potion.absorption\x03\x08duration\xF0\x01\x03\x02id,\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\x01\x03\tnutrition\x08\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x99?\x08\rcooldown_type\0\0\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\x01\x19minecraft:stacked_by_data\x01\n\x0Eminecraft:food\x01\x0Ecan_always_eat\x01\x08\rcooldown_type\0\x03\tnutrition\x08\x03\rcooldown_time\0\x03\ron_use_action\x01\t\x07effects\n\x04\x05\x06chance\0\0\x80?\x03\x08duration\n\x03\tamplifier\x02\x03\x02id\x14\x08\rdescriptionId\x13potion.regeneration\x08\x04name\x0Cregeneration\0\x08\rdescriptionId\x11potion.absorption\x03\x02id,\x08\x04name\nabsorption\x05\x06chance\0\0\x80?\x03\tamplifier\0\x03\x08duration\xF0\x01\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x99?\x08\x11using_converts_to\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const GOLDEN_AXE: Self = Self {
id: 328,
registry_key: "minecraft:golden_axe",
@ -72720,7 +72720,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\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\x03\tnutrition\x0C\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x99?\x03\rcooldown_time\0\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\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x99?\x03\rcooldown_time\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\x01\x0Ecan_always_eat\0\x03\tnutrition\x0C\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const GOLDEN_CHESTPLATE: Self = Self {
id: 355,
registry_key: "minecraft:golden_chestplate",
@ -72791,7 +72791,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\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x16minecraft:golden_spear\0\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x14minecraft:gold_ingot\0\0\0\n\x14minecraft:durability\x03\x0Emax_durability<\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\0\n\x16minecraft:display_name\x08\x05value\x16item.golden_spear.name\0\n\x18minecraft:swing_duration\x05\x05value33s?\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Citem.golden_spear.attack_hit\x08\x0Battack_miss\x1Ditem.golden_spear.attack_miss\0\t\titem_tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x08\x0Bstart_sound\x15item.golden_spear.use\x08\x0Bstart_using\x06always\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\0\n\x0Fitem_properties\x03\x0Emax_stack_size\x02\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\rhand_equipped\x01\x01\x17can_destroy_in_creative\x01\x01\x0Eliquid_clipped\0\x01\x04foil\0\x08\x10enchantable_slot\x0Bmelee_spear\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ngold_spear\0\0\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x03\x11enchantable_value,\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x03\x06damage\x02\x01\x12hidden_in_commands\x02\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x02\x05delay\x0E\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\xAA\0\x05\tmin_speed33\xA3@\0\n\x13dismount_conditions\x02\x0Cmax_durationF\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0PA\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\x13\x01\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\x0Fdamage_modifier\0\0\0\0\x05\x11damage_multiplier333?\x05\rhitbox_margin\0\0\x80>\0\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\0\n\x10minecraft:damage\x02\x05value\x01\0\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x05\x08duration33s?\x08\x04type\x06attack\0\n\x15minecraft:enchantable\x01\x05value\x16\x08\x04slot\x0Bmelee_spear\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\x10minecraft:damage\x02\x05value\x01\0\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\x13\x01\x05\x12min_relative_speed33\x93@\0\x05\x11damage_multiplier333?\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x05\x0Fdamage_modifier\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\0PA\x02\x0Cmax_durationF\0\0\n\x14knockback_conditions\x02\x0Cmax_duration\xAA\0\x05\tmin_speed33\xA3@\x05\x12min_relative_speed\0\0\0\0\0\x02\x05delay\x0E\0\0\0\n\x15minecraft:enchantable\x01\x05value\x16\x08\x04slot\x0Bmelee_spear\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Ditem.golden_spear.attack_miss\x08\nattack_hit\x1Citem.golden_spear.attack_hit\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\x18minecraft:swing_duration\x05\x05value33s?\0\n\x17minecraft:use_modifiers\x01\x0Femit_vibrations\0\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_sound\x15item.golden_spear.use\x08\x0Bstart_using\x06always\0\n\x0Fitem_properties\x03\x11enchantable_value,\x08\x10enchantable_slot\x0Bmelee_spear\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\x01\rhand_equipped\x01\x01\x17can_destroy_in_creative\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ngold_spear\0\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x06damage\x02\x03\ruse_animation\0\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x01\x0Fstacked_by_data\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x01\x12hidden_in_commands\x02\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability<\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\n\x12minecraft:cooldown\x08\x04type\x06attack\x05\x08duration33s?\x08\x08category\x05spear\0\n\x16minecraft:display_name\x08\x05value\x16item.golden_spear.name\0\n\x17minecraft:hand_equipped\x01\x05value\x01\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\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:golden_tier\x12minecraft:is_spear\0\0\0" } ;
pub const GOLDEN_SWORD: Self = Self {
id: 325,
registry_key: "minecraft:golden_sword",
@ -72855,7 +72855,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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x01\x0Fstacked_by_data\0\x01\x04foil\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x15bundle_gray_open_back\x08\x11bundle_open_front\x16bundle_gray_open_front\x08\x07default\x0Bbundle_gray\0\0\x03\x06damage\0\x01\rhand_equipped\0\x01\x0Eallow_off_hand\0\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x03\x11enchantable_value\0\x05\x0Cmining_speed\0\0\x80?\x03\x0Bframe_count\x02\x03\x0Emax_stack_size\x02\x03\x0Cuse_duration\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x03\ruse_animation\0\x08\x0Ecreative_group\0\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\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!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\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\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\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\x0Fitem_properties\x01\rhand_equipped\0\x01\x12hidden_in_commands\x02\x01\x17can_destroy_in_creative\x01\x03\x06damage\0\x01\x04foil\0\x03\x0Bframe_count\x02\x03\x0Emax_stack_size\x02\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x03\x0Cuse_duration\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x15bundle_gray_open_back\x08\x11bundle_open_front\x16bundle_gray_open_front\x08\x07default\x0Bbundle_gray\0\0\x08\x0Ecreative_group\0\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x03\x11enchantable_value\0\x01\x0Eallow_off_hand\0\x08\x10enchantable_slot\x04none\0\0\0" } ;
pub const GRAY_CANDLE: Self = Self {
id: -420,
registry_key: "minecraft:gray_candle",
@ -72954,7 +72954,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\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\t\rallowed_items\0\0\x03\tmax_slots\x80\x01\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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x0Fitem_properties\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\0\x01\x0Eshould_despawn\x01\x03\x11creative_category\x06\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\0\x01\x04foil\0\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\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\x03\x06damage\0\x01\x12hidden_in_commands\x02\x01\x0Eallow_off_hand\0\x03\x0Bframe_count\x02\x01\x17can_destroy_in_creative\x01\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\rhand_equipped\0\0\t\titem_tags\0\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\x18minecraft:max_stack_size\x01\x05value\x01\0\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\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\t\titem_tags\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x0Fitem_properties\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\0\x03\x11enchantable_value\0\x01\rhand_equipped\0\x01\x0Eshould_despawn\x01\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x03\x11creative_category\x06\x01\x0Eallow_off_hand\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\x08\x10enchantable_slot\x04none\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x03\ruse_animation\0\x03\x06damage\0\x01\x04foil\0\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\0\0\0" } ;
pub const GREEN_CANDLE: Self = Self {
id: -426,
registry_key: "minecraft:green_candle",
@ -73417,7 +73417,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\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\x01\x03\rcooldown_time\0\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x08\x11using_converts_to\x0Cglass_bottle\x03\tnutrition\x0C\x03\ron_use_action\x01\t\x0Eremove_effects\x03\x02&\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\x01\x0Ecan_always_eat\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x03\rcooldown_time\0\x03\ron_use_action\x01\t\x0Eremove_effects\x03\x02&\x03\tnutrition\x0C\x08\x11using_converts_to\x0Cglass_bottle\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",
@ -73719,7 +73719,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\x16minecraft:display_name\x08\x05value\x14item.iron_spear.name\0\t\titem_tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Bitem.iron_spear.attack_miss\x08\nattack_hit\x1Aitem.iron_spear.attack_hit\0\n\x17minecraft:use_modifiers\x08\x0Bstart_using\x06always\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_sound\x13item.iron_spear.use\x01\x0Femit_vibrations\0\x05\x0Cuse_duration\0\xA0\x8CG\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\x0Fdamage_modifier\0\0\0\0\x05\rhitbox_margin\0\0\x80>\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\xE1\0\x05\x12min_relative_speed33\x93@\0\n\x13dismount_conditions\x05\tmin_speed\0\x000A\x02\x0Cmax_duration2\0\x05\x12min_relative_speed\0\0\0\0\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\x87\0\x05\tmin_speed33\xA3@\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\x11damage_multiplier33s?\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x02\x05delay\x0C\0\0\0\n\x0Fitem_properties\x08\x10enchantable_slot\x0Bmelee_spear\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x0Bframe_count\x02\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\x05\x0Cmining_speed\0\0\x80?\x01\rhand_equipped\x01\x03\x06damage\x06\x08\x0Ecreative_group\0\x03\x11enchantable_value\x1C\x03\ruse_animation\0\x01\x04foil\0\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\niron_spear\0\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xF4\x03\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x15minecraft:enchantable\x01\x05value\x0E\x08\x04slot\x0Bmelee_spear\0\n\x18minecraft:swing_duration\x05\x05value33s?\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\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04name\x14minecraft:iron_ingot\0\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\x08duration33s?\x08\x04type\x06attack\x08\x08category\x05spear\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\0\n\x10minecraft:damage\x02\x05value\x03\0\0\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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x18minecraft:swing_duration\x05\x05value33s?\0\n\x10minecraft:damage\x02\x05value\x03\0\0\n\x16minecraft:display_name\x08\x05value\x14item.iron_spear.name\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\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Bitem.iron_spear.attack_miss\x08\nattack_hit\x1Aitem.iron_spear.attack_hit\0\t\titem_tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x15minecraft:enchantable\x01\x05value\x0E\x08\x04slot\x0Bmelee_spear\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\x03\x0Emax_durability\xF4\x03\0\n\x0Fitem_properties\x01\x0Eallow_off_hand\0\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x05\x0Cmining_speed\0\0\x80?\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\x03\x0Cuse_duration\x80\xE4\xAF\x01\x03\x11creative_category\x06\x08\x0Ecreative_group\0\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x01\rhand_equipped\x01\x03\x06damage\x06\x08\x10enchantable_slot\x0Bmelee_spear\x03\x11enchantable_value\x1C\x01\x04foil\0\x03\x0Bframe_count\x02\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\niron_spear\0\0\0\n\x12minecraft:cooldown\x05\x08duration33s?\x08\x08category\x05spear\x08\x04type\x06attack\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x11damage_conditions\x02\x0Cmax_duration\xE1\0\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\0\x05\x0Fdamage_modifier\0\0\0\0\x05\x11damage_multiplier33s?\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x05\rhitbox_margin\0\0\x80>\x02\x05delay\x0C\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration2\0\x05\tmin_speed\0\x000A\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x14knockback_conditions\x02\x0Cmax_duration\x87\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\0\0\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\n\x0Eminecraft:tags\t\x04tags\x08\x04\x13minecraft:iron_tier\x12minecraft:is_spear\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\0\0" } ;
pub const IRON_SWORD: Self = Self {
id: 309,
registry_key: "minecraft:iron_sword",
@ -74301,7 +74301,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\n\x0Fitem_properties\x03\x06damage\0\x01\x0Eshould_despawn\x01\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x1Cbundle_light_blue_open_front\x08\x07default\x11bundle_light_blue\x08\x10bundle_open_back\x1Bbundle_light_blue_open_back\0\0\x03\x0Cuse_duration\0\x03\x0Bframe_count\x02\x01\x04foil\0\x03\ruse_animation\0\x08\x0Ecreative_group\0\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\x01\x0Eallow_off_hand\0\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x01\x17can_destroy_in_creative\x01\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x01\x0Fstacked_by_data\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!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\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\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\x0Fitem_properties\x08\x0Ecreative_group\0\x03\ruse_animation\0\x03\x0Cuse_duration\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\x01\rhand_equipped\0\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x03\x06damage\0\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x01\x04foil\0\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\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\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\0\0\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\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\0\0" } ;
pub const LIGHT_BLUE_CANDLE: Self = Self {
id: -416,
registry_key: "minecraft:light_blue_candle",
@ -74400,7 +74400,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\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\t\titem_tags\0\0\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x1Cbundle_light_gray_open_front\x08\x10bundle_open_back\x1Bbundle_light_gray_open_back\x08\x07default\x11bundle_light_gray\0\0\x08\x0Ecreative_group\0\x03\x11enchantable_value\0\x03\x0Bframe_count\x02\x03\x11creative_category\x06\x01\x12hidden_in_commands\x02\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x08\x10enchantable_slot\x04none\x01\rhand_equipped\0\x01\x04foil\0\x01\x0Eliquid_clipped\0\x03\x06damage\0\x01\x0Eallow_off_hand\0\x01\x0Fstacked_by_data\0\x03\x0Emax_stack_size\x02\x03\x0Cuse_duration\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\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\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\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\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\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\n\x0Fitem_properties\x01\x0Eallow_off_hand\0\x01\x17can_destroy_in_creative\x01\x03\x06damage\0\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\0\x01\x04foil\0\x03\x0Cuse_duration\0\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x03\x0Bframe_count\x02\x01\x0Eshould_despawn\x01\x03\x11creative_category\x06\x01\rhand_equipped\0\x03\x0Emax_stack_size\x02\x01\x0Eliquid_clipped\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\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const LIGHT_GRAY_CANDLE: Self = Self {
id: -421,
registry_key: "minecraft:light_gray_candle",
@ -74520,7 +74520,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\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!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\x0Fitem_properties\x03\x0Emax_stack_size\x02\x08\x10enchantable_slot\x04none\x01\x17can_destroy_in_creative\x01\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bbundle_lime\x08\x11bundle_open_front\x16bundle_lime_open_front\x08\x10bundle_open_back\x15bundle_lime_open_back\0\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x01\rhand_equipped\0\x03\x11creative_category\x06\x01\x04foil\0\x01\x0Eallow_off_hand\0\x03\x0Bframe_count\x02\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x03\x0Cuse_duration\0\x03\x06damage\0\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\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x01\x0Eshould_despawn\x01\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\x03\x0Emax_stack_size\x02\x01\x0Eallow_off_hand\0\x01\x12hidden_in_commands\x02\x03\x11creative_category\x06\x03\ruse_animation\0\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x16bundle_lime_open_front\x08\x07default\x0Bbundle_lime\x08\x10bundle_open_back\x15bundle_lime_open_back\0\0\x03\x06damage\0\x08\x10enchantable_slot\x04none\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x08\x0Ecreative_group\0\x01\rhand_equipped\0\x01\x17can_destroy_in_creative\x01\x01\x04foil\0\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\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\0\0\0" } ;
pub const LIME_CANDLE: Self = Self {
id: -418,
registry_key: "minecraft:lime_candle",
@ -74724,7 +74724,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\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\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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x03\x06damage\0\x01\x04foil\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x01\x0Eallow_off_hand\0\x01\rhand_equipped\0\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\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x08\x10enchantable_slot\x04none\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\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\t\titem_tags\0\0\n\x0Fitem_properties\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Ebundle_magenta\x08\x10bundle_open_back\x18bundle_magenta_open_back\x08\x11bundle_open_front\x19bundle_magenta_open_front\0\0\x03\x11creative_category\x06\x03\x11enchantable_value\0\x01\x17can_destroy_in_creative\x01\x01\x04foil\0\x03\x0Emax_stack_size\x02\x08\x10enchantable_slot\x04none\x08\x0Ecreative_group\0\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\0\x01\x0Fstacked_by_data\0\x01\x12hidden_in_commands\x02\x03\ruse_animation\0\x01\rhand_equipped\0\x01\x0Eallow_off_hand\0\x03\x06damage\0\x03\x0Bframe_count\x02\x01\x0Eliquid_clipped\0\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\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\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 MAGENTA_CANDLE: Self = Self {
id: -415,
registry_key: "minecraft:magenta_candle",
@ -75026,8 +75026,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\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x14minecraft:melon_stem\t\x08plant_at\x08\x02\x12minecraft:farmland\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x99>\x01\x0Ecan_always_eat\0\x03\tnutrition\x04\x03\rcooldown_time\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\x08\x11using_converts_to\0\0\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\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x14minecraft:melon_stem\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x08\rcooldown_type\0\x03\tnutrition\x04\x03\ron_use_action\x01\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\x9A\x99\x99>\x08\x11using_converts_to\0\0\0\0" } ;
pub const MELON_STEM: Self = Self {
id: 105,
registry_key: "minecraft:melon_stem",
@ -75245,7 +75245,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\rcooldown_type\0\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\x03\tnutrition\x0C\x08\x11using_converts_to\x04bowl\x05\x13saturation_modifier\x9A\x99\x19?\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\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\tnutrition\x0C\x03\rcooldown_time\0\x08\rcooldown_type\0\x03\ron_use_action\x01\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\x04bowl\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\0\0\0" } ;
pub const MUSIC_DISC_11: Self = Self {
id: 554,
registry_key: "minecraft:music_disc_11",
@ -75400,7 +75400,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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\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\x03\ron_use_action\x01\x03\tnutrition\x04\x08\x11using_converts_to\0\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\0\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\x03\rcooldown_time\0\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\tnutrition\x04\x08\rcooldown_type\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const MYCELIUM: Self = Self {
id: 110,
registry_key: "minecraft:mycelium",
@ -75492,7 +75492,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\x08\rplant_at_face\x02up\t\x08plant_at\x08\x02\tsoul_sand\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x15minecraft:nether_wart\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\t\x08plant_at\x08\x02\tsoul_sand\x08\x0Bcrop_result\x15minecraft:nether_wart\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\0\0\0" } ;
pub const NETHER_WART_BLOCK: Self = Self {
id: 214,
registry_key: "minecraft:nether_wart_block",
@ -75598,7 +75598,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: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\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\x0F\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x18minecraft:netherite_tier\x12minecraft:is_spear\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xDC\x1F\0\n\x18minecraft:swing_duration\x05\x05value33\x93?\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x13dismount_conditions\x02\x0Cmax_duration2\0\x05\tmin_speed\0\0\x10A\x05\x12min_relative_speed\0\0\0\0\0\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\x02\x0Cmax_duration\xAF\0\0\x02\x05delay\x08\0\x05\x11damage_multiplier\x9A\x99\x99?\x05\rhitbox_margin\0\0\x80>\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed33\xA3@\x02\x0Cmax_durationn\0\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x05\x0Fdamage_modifier\0\0\0\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\0\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x08\x08category\x05spear\x05\x08duration33\x93?\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss item.netherite_spear.attack_miss\x08\nattack_hit\x1Fitem.netherite_spear.attack_hit\0\t\titem_tags\x08\x04\x18minecraft:netherite_tier\x12minecraft:is_spear\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\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\x01\x0Eallow_off_hand\0\x03\x06damage\n\x08\x10enchantable_slot\x0Bmelee_spear\x03\x0Bframe_count\x02\x01\x04foil\0\x05\x0Cmining_speed\0\0\x80?\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Fnetherite_spear\0\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x03\x11enchantable_value\x1E\x01\x0Fstacked_by_data\0\x03\x0Emax_stack_size\x02\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x03\ruse_animation\0\x01\rhand_equipped\x01\0\n\x10minecraft:damage\x02\x05value\x05\0\0\n\x16minecraft:display_name\x08\x05value\x19item.netherite_spear.name\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\0\n\x18minecraft:fire_resistant\x01\x05value\x01\0\n\x18minecraft:max_stack_size\x01\x05value\x01\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\x14minecraft:durability\n\rdamage_chance\x03\x03min\0\x03\x03max\xC8\x01\0\x03\x0Emax_durability\xDC\x1F\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x05\x08duration33\x93?\x08\x08category\x05spear\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\n\x14knockback_conditions\x05\tmin_speed33\xA3@\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_durationn\0\0\x02\x05delay\x08\0\x05\rhitbox_margin\0\0\x80>\n\x11damage_conditions\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration\xAF\0\x05\x12min_relative_speed33\x93@\0\x05\x11damage_multiplier\x9A\x99\x99?\x05\x0Fdamage_modifier\0\0\0\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0\x10A\x02\x0Cmax_duration2\0\0\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x18minecraft:netherite_tier\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\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\x18minecraft:fire_resistant\x01\x05value\x01\0\n\x18minecraft:swing_duration\x05\x05value33\x93?\0\n\x16minecraft:display_name\x08\x05value\x19item.netherite_spear.name\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\x18minecraft:max_stack_size\x01\x05value\x01\0\t\titem_tags\x08\x04\x18minecraft:netherite_tier\x12minecraft:is_spear\n\x15minecraft:enchantable\x01\x05value\x0F\x08\x04slot\x0Bmelee_spear\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss item.netherite_spear.attack_miss\x08\nattack_hit\x1Fitem.netherite_spear.attack_hit\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\x0Fitem_properties\x01\rhand_equipped\x01\x03\x0Bframe_count\x02\x03\x0Emax_stack_size\x02\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Fnetherite_spear\0\0\x03\x11enchantable_value\x1E\x03\ruse_animation\0\x08\x10enchantable_slot\x0Bmelee_spear\x08\x0Ecreative_group\0\x01\x0Eallow_off_hand\0\x03\x06damage\n\x01\x04foil\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Fstacked_by_data\0\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\0\n\x10minecraft:damage\x02\x05value\x05\0\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\0\0" } ;
pub const NETHERITE_SWORD: Self = Self {
id: 617,
registry_key: "minecraft:netherite_sword",
@ -75795,7 +75795,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\x16minecraft:display_name\x08\x05value\x1Bitem.ominous_trial_key.name\0\n\x0Fitem_properties\x01\x04foil\0\x08\x10enchantable_slot\x04none\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x11ominous_trial_key\0\0\x01\x17can_destroy_in_creative\x01\x01\x12hidden_in_commands\x02\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x80\x01\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\0\x03\x11creative_category\x08\x03\x11enchantable_value\0\x01\x0Fstacked_by_data\0\x03\x06damage\0\x03\ruse_animation\0\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\0\t\titem_tags\0\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\x16minecraft:display_name\x08\x05value\x1Bitem.ominous_trial_key.name\0\n\x0Fitem_properties\x01\x12hidden_in_commands\x02\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x11ominous_trial_key\0\0\x01\x0Eallow_off_hand\0\x08\x10enchantable_slot\x04none\x01\x04foil\0\x01\x0Eliquid_clipped\0\x03\x11creative_category\x08\x03\x0Emax_stack_size\x80\x01\x03\ruse_animation\0\x03\x0Cuse_duration\0\x08\x0Ecreative_group\0\x01\x0Eshould_despawn\x01\x01\rhand_equipped\0\x05\x0Cmining_speed\0\0\x80?\x03\x06damage\0\x03\x0Bframe_count\x02\x01\x17can_destroy_in_creative\x01\x01\x0Fstacked_by_data\0\0\t\titem_tags\0\0\0\0" } ;
pub const OPEN_EYEBLOSSOM: Self = Self {
id: -1018,
registry_key: "minecraft:open_eyeblossom",
@ -75803,7 +75803,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\n\x0Fitem_properties\x03\x11enchantable_value\0\x03\x0Cuse_duration\0\x03\x06damage\0\x03\x11creative_category\x06\x03\x0Emax_stack_size\x02\x01\x12hidden_in_commands\x02\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x04none\x05\x0Cmining_speed\0\0\x80?\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x18bundle_orange_open_front\x08\x10bundle_open_back\x17bundle_orange_open_back\x08\x07default\rbundle_orange\0\0\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\x0Eallow_off_hand\0\x01\x0Eliquid_clipped\0\x01\x04foil\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\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\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\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\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\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\n\x0Fitem_properties\x03\x0Cuse_duration\0\x03\x11enchantable_value\0\x05\x0Cmining_speed\0\0\x80?\x08\x10enchantable_slot\x04none\x01\x0Eallow_off_hand\0\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\x03\x06damage\0\x01\x04foil\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x17bundle_orange_open_back\x08\x11bundle_open_front\x18bundle_orange_open_front\x08\x07default\rbundle_orange\0\0\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\0\0" } ;
pub const ORANGE_CANDLE: Self = Self {
id: -414,
registry_key: "minecraft:orange_candle",
@ -76336,7 +76336,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\x01\x17can_destroy_in_creative\x01\x03\x11enchantable_value\0\x03\x11creative_category\x06\x01\x12hidden_in_commands\x02\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x01\rhand_equipped\0\x01\x0Eallow_off_hand\0\x01\x04foil\0\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\x03\x06damage\0\x03\x0Cuse_duration\0\x01\x0Eshould_despawn\x01\x08\x0Ecreative_group\0\n\x0Eminecraft:icon\n\x08textures\x08\x11bundle_open_front\x16bundle_pink_open_front\x08\x10bundle_open_back\x15bundle_pink_open_back\x08\x07default\x0Bbundle_pink\0\0\x05\x0Cmining_speed\0\0\x80?\0\n\x18minecraft:max_stack_size\x01\x05value\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\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\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\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\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\x11enchantable_value\0\x01\rhand_equipped\0\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x03\x0Cuse_duration\0\x01\x12hidden_in_commands\x02\x01\x0Fstacked_by_data\0\x01\x04foil\0\x01\x0Eliquid_clipped\0\x03\x06damage\0\x08\x10enchantable_slot\x04none\x03\x0Emax_stack_size\x02\x01\x0Eshould_despawn\x01\x05\x0Cmining_speed\0\0\x80?\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x15bundle_pink_open_back\x08\x11bundle_open_front\x16bundle_pink_open_front\x08\x07default\x0Bbundle_pink\0\0\x03\x11creative_category\x06\x08\x0Ecreative_group\0\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",
@ -76477,7 +76477,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\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x16minecraft:pitcher_crop\t\x08plant_at\x08\x02\x12minecraft:farmland\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\rplant_at_face\x02up\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\x0Bcrop_result\x16minecraft:pitcher_crop\x01\x1Aplant_at_any_solid_surface\0\0\0\0" } ;
pub const PLANKS: Self = Self {
id: 814,
registry_key: "minecraft:planks",
@ -76513,7 +76513,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\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\t\x07effects\n\x02\x03\tamplifier\0\x05\x06chance\x9A\x99\x19?\x03\x02id&\x08\x04name\x06poison\x08\rdescriptionId\rpotion.poison\x03\x08duration\n\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\ron_use_action\x01\x08\x11using_converts_to\0\x08\rcooldown_type\0\x03\rcooldown_time\0\x03\tnutrition\x04\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x03\tnutrition\x04\x03\ron_use_action\x01\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x01\x0Ecan_always_eat\0\t\x07effects\n\x02\x08\rdescriptionId\rpotion.poison\x03\x08duration\n\x03\tamplifier\0\x05\x06chance\x9A\x99\x19?\x08\x04name\x06poison\x03\x02id&\0\0\0\0" } ;
pub const POLAR_BEAR_SPAWN_EGG: Self = Self {
id: 477,
registry_key: "minecraft:polar_bear_spawn_egg",
@ -76990,7 +76990,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\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x99>\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\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\n\x0Eminecraft:food\x08\x11using_converts_to\0\x08\rcooldown_type\0\x03\ron_use_action\x01\x03\tnutrition\x06\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x99>\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const PORTAL: Self = Self {
id: 90,
registry_key: "minecraft:portal",
@ -76998,7 +76998,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\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x12minecraft:potatoes\0\x03\x16minecraft:use_duration@\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\x03\rcooldown_time\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\tnutrition\x02\x08\x11using_converts_to\0\0\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\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\x03\tnutrition\x02\x03\rcooldown_time\0\x08\x11using_converts_to\0\x05\x13saturation_modifier\x9A\x99\x99>\0\x03\x16minecraft:use_duration@\n\x0Eminecraft:seed\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x12minecraft:potatoes\t\x08plant_at\x08\x02\x12minecraft:farmland\0\0\0" } ;
pub const POTATOES: Self = Self {
id: 142,
registry_key: "minecraft:potatoes",
@ -77132,7 +77132,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\x08\x11using_converts_to\0\x03\rcooldown_time\0\x03\ron_use_action\x01\t\x07effects\n\x06\x03\x02id&\x08\x04name\x06poison\x03\x08durationx\x08\rdescriptionId\rpotion.poison\x03\tamplifier\x02\x05\x06chance\0\0\x80?\0\x08\x04name\x06nausea\x05\x06chance\0\0\x80?\x03\tamplifier\0\x03\x02id\x12\x08\rdescriptionId\x10potion.confusion\x03\x08duration\x1E\0\x03\tamplifier\x04\x03\x02id\"\x08\rdescriptionId\rpotion.hunger\x05\x06chance\0\0\x80?\x08\x04name\x06hunger\x03\x08duration\x1E\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\tnutrition\x02\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\n\x0Eminecraft:food\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x03\ron_use_action\x01\t\x07effects\n\x06\x03\x02id&\x05\x06chance\0\0\x80?\x03\x08durationx\x08\rdescriptionId\rpotion.poison\x03\tamplifier\x02\x08\x04name\x06poison\0\x03\x02id\x12\x08\x04name\x06nausea\x08\rdescriptionId\x10potion.confusion\x05\x06chance\0\0\x80?\x03\tamplifier\0\x03\x08duration\x1E\0\x03\x02id\"\x03\x08duration\x1E\x05\x06chance\0\0\x80?\x03\tamplifier\x04\x08\rdescriptionId\rpotion.hunger\x08\x04name\x06hunger\0\x03\tnutrition\x02\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\0\0" } ;
pub const PUFFERFISH_BUCKET: Self = Self {
id: 370,
registry_key: "minecraft:pufferfish_bucket",
@ -77154,8 +77154,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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\x08\x11using_converts_to\0\x03\tnutrition\x10\x05\x13saturation_modifier\x9A\x99\x99>\x01\x0Ecan_always_eat\0\x03\rcooldown_time\0\0\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\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x16minecraft:pumpkin_stem\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\x9A\x99\x99>\x03\ron_use_action\x01\x03\tnutrition\x10\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\rcooldown_type\0\0\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\t\x08plant_at\x08\x02\x12minecraft:farmland\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x16minecraft:pumpkin_stem\x01\x1Aplant_at_any_solid_surface\0\0\0\0" } ;
pub const PUMPKIN_STEM: Self = Self {
id: 104,
registry_key: "minecraft:pumpkin_stem",
@ -77163,7 +77163,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\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\x01\x04foil\0\x03\x0Cuse_duration\0\x08\x0Ecreative_group\0\x01\x12hidden_in_commands\x02\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\x03\x11enchantable_value\0\x01\x0Fstacked_by_data\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\x03\x0Emax_stack_size\x02\x03\x11creative_category\x06\x01\rhand_equipped\0\x08\x10enchantable_slot\x04none\x01\x0Eshould_despawn\x01\x03\x06damage\0\x03\ruse_animation\0\0\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\0\t\titem_tags\0\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\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\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\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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\t\titem_tags\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\x03\x11enchantable_value\0\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x08\x0Ecreative_group\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\x04foil\0\x01\rhand_equipped\0\x03\x0Emax_stack_size\x02\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x01\x0Eallow_off_hand\0\x01\x0Eshould_despawn\x01\x01\x0Eliquid_clipped\0\x03\x11creative_category\x06\x08\x10enchantable_slot\x04none\x03\x06damage\0\x05\x0Cmining_speed\0\0\x80?\x01\x12hidden_in_commands\x02\x03\x0Bframe_count\x02\0\0\0" } ;
pub const PURPLE_CANDLE: Self = Self {
id: -423,
registry_key: "minecraft:purple_candle",
@ -77353,7 +77353,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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x99>\x03\tnutrition\x06\x03\ron_use_action\x01\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\0\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\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x05\x13saturation_modifier\x9A\x99\x99>\x03\rcooldown_time\0\x08\rcooldown_type\0\x08\x11using_converts_to\0\x01\x0Ecan_always_eat\0\x03\tnutrition\x06\x03\ron_use_action\x01\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const RABBIT_FOOT: Self = Self {
id: 538,
registry_key: "minecraft:rabbit_foot",
@ -77375,7 +77375,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\n\x0Eminecraft:food\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\x04bowl\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\x19?\x03\tnutrition\x14\x08\rcooldown_type\0\x03\rcooldown_time\0\0\x03\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\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\x03\tnutrition\x14\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x19?\x08\x11using_converts_to\x04bowl\x03\rcooldown_time\0\x01\x0Ecan_always_eat\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\0\x03\x18minecraft:max_stack_size\x02\0\0" } ;
pub const RAIL: Self = Self {
id: 66,
registry_key: "minecraft:rail",
@ -77453,7 +77453,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\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x0Fitem_properties\x01\x17can_destroy_in_creative\x01\x03\ruse_animation\0\x01\x04foil\0\x01\x12hidden_in_commands\x02\x03\x0Emax_stack_size\x02\x03\x11enchantable_value\0\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x14bundle_red_open_back\x08\x07default\nbundle_red\x08\x11bundle_open_front\x15bundle_red_open_front\0\0\x01\x0Fstacked_by_data\0\x08\x0Ecreative_group\0\x01\x0Eliquid_clipped\0\x01\rhand_equipped\0\x03\x11creative_category\x06\x05\x0Cmining_speed\0\0\x80?\x03\x0Cuse_duration\0\x03\x0Bframe_count\x02\x03\x06damage\0\x08\x10enchantable_slot\x04none\x01\x0Eshould_despawn\x01\0\t\titem_tags\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\n!minecraft:storage_weight_modifier\x03\x16weight_in_storage_item\x08\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\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\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\x01\x1Aallow_nested_storage_items\x01\x03\tmax_slots\x80\x01\t\rallowed_items\0\0\0\n\x0Fitem_properties\x01\x04foil\0\x08\x10enchantable_slot\x04none\x05\x0Cmining_speed\0\0\x80?\x01\x17can_destroy_in_creative\x01\x01\x0Fstacked_by_data\0\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\0\x03\x0Bframe_count\x02\x01\rhand_equipped\0\x08\x0Ecreative_group\0\x03\x11creative_category\x06\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\x01\x0Eshould_despawn\x01\x01\x12hidden_in_commands\x02\x03\x11enchantable_value\0\x03\ruse_animation\0\x03\x06damage\0\x03\x0Emax_stack_size\x02\x01\x0Eallow_off_hand\0\0\t\titem_tags\0\0\0\0" } ;
pub const RED_CANDLE: Self = Self {
id: -427,
registry_key: "minecraft:red_candle",
@ -77811,7 +77811,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\x08\rcooldown_type\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x08\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\ron_use_action\x01\t\x07effects\n\x02\x05\x06chance\xCD\xCCL?\x03\x02id\"\x03\tamplifier\0\x08\rdescriptionId\rpotion.hunger\x03\x08duration<\x08\x04name\x06hunger\0\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\rcooldown_time\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\x03\ron_use_action\x01\x08\x11using_converts_to\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\rcooldown_time\0\x03\tnutrition\x08\x01\x0Ecan_always_eat\0\t\x07effects\n\x02\x08\rdescriptionId\rpotion.hunger\x08\x04name\x06hunger\x05\x06chance\xCD\xCCL?\x03\tamplifier\0\x03\x08duration<\x03\x02id\"\0\x05\x13saturation_modifier\xCD\xCC\xCC=\0\x03\x16minecraft:use_duration@\0\0" } ;
pub const SADDLE: Self = Self {
id: 374,
registry_key: "minecraft:saddle",
@ -77819,7 +77819,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\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x04\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x08\x11using_converts_to\0\x03\rcooldown_time\0\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\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\x03\ron_use_action\x01\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\tnutrition\x04\x08\x11using_converts_to\0\x08\rcooldown_type\0\x03\rcooldown_time\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x01\x0Ecan_always_eat\0\0\x01\x19minecraft:stacked_by_data\x01\x03\x16minecraft:use_duration@\0\0" } ;
pub const SALMON_BUCKET: Self = Self {
id: 368,
registry_key: "minecraft:salmon_bucket",
@ -78380,7 +78380,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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\t\x07effects\n\x02\x08\x04name\x06poison\x03\x02id&\x08\rdescriptionId\rpotion.poison\x03\tamplifier\0\x05\x06chance\0\0\x80?\x03\x08duration\n\0\x03\rcooldown_time\0\x03\tnutrition\x04\x08\x11using_converts_to\0\x08\rcooldown_type\0\x05\x13saturation_modifier\xCD\xCCL?\0\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\xCD\xCCL?\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\t\x07effects\n\x02\x08\x04name\x06poison\x08\rdescriptionId\rpotion.poison\x03\tamplifier\0\x05\x06chance\0\0\x80?\x03\x08duration\n\x03\x02id&\0\x08\rcooldown_type\0\x03\ron_use_action\x01\x03\tnutrition\x04\x03\rcooldown_time\0\0\0\0" } ;
pub const SPIDER_SPAWN_EGG: Self = Self {
id: 450,
registry_key: "minecraft:spider_spawn_egg",
@ -78745,7 +78745,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\x0Eminecraft:tags\t\x04tags\x08\x04\x14minecraft:stone_tier\x12minecraft:is_spear\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x16minecraft:display_name\x08\x05value\x15item.stone_spear.name\0\n\x17minecraft:use_modifiers\x05\x0Cuse_duration\0\xA0\x8CG\x05\x11movement_modifier\0\0\x80?\x08\x0Bstart_sound\x14item.stone_spear.use\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\0\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x05\x08duration\0\0@?\x08\x08category\x05spear\0\n\x14minecraft:durability\x03\x0Emax_durability\x84\x02\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\0\n\x10minecraft:damage\x02\x05value\x02\0\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x05\rhitbox_margin\0\0\x80>\x02\x05delay\x0E\0\n\x11damage_conditions\x02\x0Cmax_duration\x13\x01\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\0\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\n\x14knockback_conditions\x02\x0Cmax_duration\xB4\0\x05\tmin_speed33\xA3@\x05\x12min_relative_speed\0\0\0\0\0\x05\x0Fdamage_modifier\0\0\0\0\n\x13dismount_conditions\x05\tmin_speed\0\0PA\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_durationZ\0\0\x05\x11damage_multiplier\x85\xEBQ?\0\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\x05\rhitbox_margin\0\0\x80>\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\0\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\x05\0\t\titem_tags\x08\x04\x14minecraft:stone_tier\x12minecraft:is_spear\n\x0Fitem_properties\x01\x0Eshould_despawn\x01\x03\x11creative_category\x06\x03\x11enchantable_value\n\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\rhand_equipped\x01\x08\x0Ecreative_group\0\x01\x04foil\0\x01\x0Eallow_off_hand\0\x01\x12hidden_in_commands\x02\x03\x0Bframe_count\x02\x03\x06damage\x04\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\x01\x17can_destroy_in_creative\x01\x08\x10enchantable_slot\x0Bmelee_spear\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bstone_spear\0\0\x03\x0Emax_stack_size\x02\0\n\x18minecraft:swing_duration\x05\x05value\0\0@?\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Bitem.stone_spear.attack_hit\x08\x0Battack_miss\x1Citem.stone_spear.attack_miss\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\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\x17minecraft:hand_equipped\x01\x05value\x01\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\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\x16minecraft:display_name\x08\x05value\x15item.stone_spear.name\0\n\x17minecraft:use_modifiers\x08\x0Bstart_sound\x14item.stone_spear.use\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x01\x0Femit_vibrations\0\x08\x0Bstart_using\x06always\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x13dismount_conditions\x05\tmin_speed\0\0PA\x02\x0Cmax_durationZ\0\x05\x12min_relative_speed\0\0\0\0\0\x05\rhitbox_margin\0\0\x80>\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\x0Fdamage_modifier\0\0\0\0\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\n\x11damage_conditions\x02\x0Cmax_duration\x13\x01\x05\tmin_speed\0\0\0\0\x05\x12min_relative_speed33\x93@\0\x02\x05delay\x0E\0\0\0\n\x18minecraft:swing_duration\x05\x05value\0\0@?\0\n\x18minecraft:max_stack_size\x01\x05value\x01\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:durability\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\x03\x0Emax_durability\x84\x02\0\n\x10minecraft:damage\x02\x05value\x02\0\0\n\x15minecraft:enchantable\x01\x05value\x05\x08\x04slot\x0Bmelee_spear\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x08\x08category\x05spear\x05\x08duration\0\0@?\0\n\x0Fitem_properties\x01\x04foil\0\x03\x0Emax_stack_size\x02\x08\x0Ecreative_group\0\x08\x10enchantable_slot\x0Bmelee_spear\x01\rhand_equipped\x01\x01\x17can_destroy_in_creative\x01\x03\x06damage\x04\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bstone_spear\0\0\x05\x0Cmining_speed\0\0\x80?\x03\x11enchantable_value\n\x01\x0Eallow_off_hand\0\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x0Eliquid_clipped\0\x03\x0Bframe_count\x02\x03\ruse_animation\0\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Bitem.stone_spear.attack_hit\x08\x0Battack_miss\x1Citem.stone_spear.attack_miss\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\0\0" } ;
pub const STONE_STAIRS: Self = Self {
id: 67,
registry_key: "minecraft:stone_stairs",
@ -79124,8 +79124,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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\rcooldown_time\0\x01\x0Ecan_always_eat\x01\x03\tnutrition\x0C\x03\ron_use_action\x02\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\x04bowl\x08\rcooldown_type\0\x05\x13saturation_modifier\x9A\x99\x19?\0\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\t\x08plant_at\x08\x14\x08farmland\x05grass\x04dirt\x0Bcoarse_dirt\x06podzol\nmoss_block\x08mycelium\x03mud\x14muddy_mangrove_roots\x0Fdirt_with_roots\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x1Aminecraft:sweet_berry_bush\0\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x05\x13saturation_modifier\x9A\x99\x99>\x08\rcooldown_type\0\x03\rcooldown_time\0\x03\ron_use_action\x01\x08\x11using_converts_to\0\x03\tnutrition\x04\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 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\x08\rcooldown_type\0\x03\rcooldown_time\0\x03\ron_use_action\x02\x01\x0Ecan_always_eat\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\0\x03\x18minecraft:max_stack_size\x02\x03\x16minecraft:use_duration@\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\x03\x16minecraft:use_duration@\n\x0Eminecraft:food\x03\tnutrition\x04\x08\rcooldown_type\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\x05\x13saturation_modifier\x9A\x99\x99>\x08\x11using_converts_to\0\x03\ron_use_action\x01\0\n\x0Eminecraft:seed\x08\rplant_at_face\x02up\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x1Aminecraft:sweet_berry_bush\t\x08plant_at\x08\x14\x08farmland\x05grass\x04dirt\x0Bcoarse_dirt\x06podzol\nmoss_block\x08mycelium\x03mud\x14muddy_mangrove_roots\x0Fdirt_with_roots\0\0\0" } ;
pub const SWEET_BERRY_BUSH: Self = Self {
id: -207,
registry_key: "minecraft:sweet_berry_bush",
@ -79224,7 +79224,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\x08\x0Bcrop_result\x1Aminecraft:torchflower_crop\x01\x1Aplant_at_any_solid_surface\0\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\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\x08\rplant_at_face\x02up\x08\x0Bcrop_result\x1Aminecraft:torchflower_crop\0\0\0" } ;
pub const TOTEM_OF_UNDYING: Self = Self {
id: 578,
registry_key: "minecraft:totem_of_undying",
@ -79253,7 +79253,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\n\x0Fitem_properties\x03\x11creative_category\x08\x03\x0Bframe_count\x02\x08\x0Ecreative_group\0\x03\x0Emax_stack_size\x80\x01\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ttrial_key\0\0\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x08\x10enchantable_slot\x04none\x03\x06damage\0\x01\x0Eallow_off_hand\0\x03\ruse_animation\0\x03\x0Cuse_duration\0\x01\x04foil\0\x01\x0Fstacked_by_data\0\x03\x11enchantable_value\0\x01\x17can_destroy_in_creative\x01\x01\rhand_equipped\0\0\t\titem_tags\0\0\n\x16minecraft:display_name\x08\x05value\x13item.trial_key.name\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\x05\x0Cmining_speed\0\0\x80?\x03\ruse_animation\0\x03\x0Cuse_duration\0\x01\x0Fstacked_by_data\0\x08\x10enchantable_slot\x04none\x01\x0Eshould_despawn\x01\x01\x17can_destroy_in_creative\x01\x01\x04foil\0\x01\x12hidden_in_commands\x02\x03\x0Bframe_count\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\ttrial_key\0\0\x03\x11creative_category\x08\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x80\x01\x08\x0Ecreative_group\0\x01\rhand_equipped\0\x03\x11enchantable_value\0\x03\x06damage\0\x01\x0Eallow_off_hand\0\0\0\0" } ;
pub const TRIAL_SPAWNER: Self = Self {
id: -315,
registry_key: "minecraft:trial_spawner",
@ -79282,7 +79282,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\n\x0Eminecraft:food\x08\rcooldown_type\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\xCD\xCC\xCC=\x03\tnutrition\x02\x03\ron_use_action\x01\x03\rcooldown_time\0\0\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\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\x08\rcooldown_type\0\x03\tnutrition\x02\x03\ron_use_action\x01\x01\x0Ecan_always_eat\0\x05\x13saturation_modifier\xCD\xCC\xCC=\x03\rcooldown_time\0\t\x0Con_use_range\x05\x06\0\0\0A\0\0\0A\0\0\0A\x08\x11using_converts_to\0\0\x03\x16minecraft:use_duration@\x01\x19minecraft:stacked_by_data\x01\0\0" } ;
pub const TROPICAL_FISH_BUCKET: Self = Self {
id: 369,
registry_key: "minecraft:tropical_fish_bucket",
@ -80333,8 +80333,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\x08\x0Bcrop_result\x0Fminecraft:wheat\x08\rplant_at_face\x02up\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\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!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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\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\x0Fitem_properties\x08\x0Ecreative_group\0\x03\x0Cuse_duration\0\x03\x11creative_category\x06\x01\x12hidden_in_commands\x02\x01\x0Eshould_despawn\x01\x03\x11enchantable_value\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Cbundle_white\x08\x10bundle_open_back\x16bundle_white_open_back\x08\x11bundle_open_front\x17bundle_white_open_front\0\0\x05\x0Cmining_speed\0\0\x80?\x08\x10enchantable_slot\x04none\x01\x0Fstacked_by_data\0\x03\x0Bframe_count\x02\x01\x0Eliquid_clipped\0\x03\ruse_animation\0\x01\x17can_destroy_in_creative\x01\x01\rhand_equipped\0\x03\x06damage\0\x01\x04foil\0\x03\x0Emax_stack_size\x02\x01\x0Eallow_off_hand\0\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\t\x08plant_at\x08\x02\x12minecraft:farmland\x01\x1Aplant_at_any_solid_surface\0\x08\x0Bcrop_result\x0Fminecraft:wheat\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\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\x0Fitem_properties\x01\x04foil\0\x03\x11creative_category\x06\x01\x17can_destroy_in_creative\x01\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x08\x10enchantable_slot\x04none\x01\x0Eshould_despawn\x01\x03\x0Cuse_duration\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Cbundle_white\x08\x10bundle_open_back\x16bundle_white_open_back\x08\x11bundle_open_front\x17bundle_white_open_front\0\0\x03\x0Bframe_count\x02\x01\x0Eallow_off_hand\0\x01\x0Eliquid_clipped\0\x01\x12hidden_in_commands\x02\x03\x06damage\0\x08\x0Ecreative_group\0\x03\x11enchantable_value\0\x01\rhand_equipped\0\x03\x0Emax_stack_size\x02\x05\x0Cmining_speed\0\0\x80?\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\t\titem_tags\0\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\0\0" } ;
pub const WHITE_CANDLE: Self = Self {
id: -413,
registry_key: "minecraft:white_candle",
@ -80454,7 +80454,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\x12minecraft:cooldown\x08\x08category\x0Bwind_charge\x05\x08duration\0\0\0?\x08\x04type\x03use\0\n\x13minecraft:throwable\x05\x11min_draw_duration\0\0\0\0\x01\x1Cscale_power_by_draw_duration\0\x05\x12launch_power_scale\0\0\xC0?\x05\x10max_launch_power\0\0\xC0?\x05\x11max_draw_duration\0\0\0\0\x01\x12do_swing_animation\x01\0\n\x16minecraft:display_name\x08\x05value\x15item.wind_charge.name\0\n\x14minecraft:projectile\x05\x16minimum_critical_power\0\0\0\0\x08\x11projectile_entity\"minecraft:wind_charge_projectile<>\0\n\x0Fitem_properties\x01\x12hidden_in_commands\x02\x08\x10enchantable_slot\x04none\x05\x0Cmining_speed\0\0\x80?\x01\rhand_equipped\0\x03\x11enchantable_value\0\x01\x17can_destroy_in_creative\x01\x03\x0Emax_stack_size\x80\x01\x03\x0Bframe_count\x02\x01\x0Fstacked_by_data\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bwind_charge\0\0\x01\x0Eallow_off_hand\0\x03\x0Cuse_duration\0\x03\x11creative_category\x06\x01\x0Eshould_despawn\x01\x03\ruse_animation\0\x03\x06damage\0\x01\x0Eliquid_clipped\0\x08\x0Ecreative_group\0\x01\x04foil\0\0\t\titem_tags\0\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\x05\x16minimum_critical_power\0\0\0\0\x08\x11projectile_entity\"minecraft:wind_charge_projectile<>\0\t\titem_tags\0\0\n\x13minecraft:throwable\x05\x10max_launch_power\0\0\xC0?\x01\x12do_swing_animation\x01\x05\x11min_draw_duration\0\0\0\0\x05\x11max_draw_duration\0\0\0\0\x05\x12launch_power_scale\0\0\xC0?\x01\x1Cscale_power_by_draw_duration\0\0\n\x0Fitem_properties\x08\x10enchantable_slot\x04none\x03\x11enchantable_value\0\x01\x12hidden_in_commands\x02\x03\x06damage\0\x05\x0Cmining_speed\0\0\x80?\x08\x0Ecreative_group\0\x01\x0Eallow_off_hand\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\x0Bwind_charge\0\0\x01\x0Fstacked_by_data\0\x03\x0Cuse_duration\0\x01\x17can_destroy_in_creative\x01\x03\x0Bframe_count\x02\x01\rhand_equipped\0\x01\x0Eliquid_clipped\0\x03\x0Emax_stack_size\x80\x01\x03\x11creative_category\x06\x03\ruse_animation\0\x01\x04foil\0\x01\x0Eshould_despawn\x01\0\n\x12minecraft:cooldown\x05\x08duration\0\0\0?\x08\x08category\x0Bwind_charge\x08\x04type\x03use\0\n\x16minecraft:display_name\x08\x05value\x15item.wind_charge.name\0\0\0" } ;
pub const WITCH_SPAWN_EGG: Self = Self {
id: 456,
registry_key: "minecraft:witch_spawn_egg",
@ -80567,7 +80567,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\x0Fitem_properties\x03\x0Bframe_count\x02\x05\x0Cmining_speed\0\0\x80?\x01\rhand_equipped\x01\x03\ruse_animation\0\x03\x0Emax_stack_size\x02\x08\x10enchantable_slot\x0Bmelee_spear\x03\x11enchantable_value\x1E\x03\x11creative_category\x06\x01\x17can_destroy_in_creative\x01\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x01\x04foil\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x0Fstacked_by_data\0\x03\x06damage\x02\x01\x12hidden_in_commands\x02\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nwood_spear\0\0\x08\x0Ecreative_group\0\x01\x0Eliquid_clipped\0\0\n\x16minecraft:swing_sounds\x08\x0Battack_miss\x1Ditem.wooden_spear.attack_miss\x08\nattack_hit\x1Citem.wooden_spear.attack_hit\0\n\x17minecraft:use_modifiers\x08\x0Bstart_sound\x15item.wooden_spear.use\x08\x0Bstart_using\x06always\x05\x11movement_modifier\0\0\x80?\x01\x0Femit_vibrations\0\x05\x0Cuse_duration\0\xA0\x8CG\0\n\x17minecraft:hand_equipped\x01\x05value\x01\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_durabilityx\0\n\x0Eminecraft:fuel\x05\x08duration\0\0 A\0\n\x18minecraft:swing_duration\x05\x05valueff&?\0\n\x16minecraft:display_name\x08\x05value\x16item.wooden_spear.name\0\n\x10minecraft:damage\x02\x05value\x01\0\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x16minecraft:wooden_spear\0\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\t\x05items\n\x02\x08\x04tags\x1Eq.all_tags('minecraft:planks')\0\0\0\n\x12minecraft:cooldown\x08\x08category\x05spear\x05\x08durationff&?\x08\x04type\x06attack\0\t\titem_tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\n\x15minecraft:enchantable\x08\x04slot\x0Bmelee_spear\x01\x05value\x0F\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x05\rhitbox_margin\0\0\x80>\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\n\x0Ecreative_reach\x05\x03min\0\0\0@\x05\x03max\0\0\xF0@\0\x05\x11damage_multiplier333?\x05\x0Fdamage_modifier\0\0\0\0\x02\x05delay\x0F\0\n\x13dismount_conditions\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0`A\x02\x0Cmax_durationd\0\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\xC8\0\x05\tmin_speed33\xA3@\0\n\x05reach\x05\x03max\0\0\x90@\x05\x03min\0\0\0@\0\x05\rhitbox_margin\0\0\x80>\n\x11damage_conditions\x05\x12min_relative_speed33\x93@\x05\tmin_speed\0\0\0\0\x02\x0Cmax_duration,\x01\0\0\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\x10minecraft:damage\x02\x05value\x01\0\0\n\x15minecraft:enchantable\x01\x05value\x0F\x08\x04slot\x0Bmelee_spear\0\n\x17minecraft:use_modifiers\x08\x0Bstart_sound\x15item.wooden_spear.use\x05\x11movement_modifier\0\0\x80?\x05\x0Cuse_duration\0\xA0\x8CG\x08\x0Bstart_using\x06always\x01\x0Femit_vibrations\0\0\n\x14minecraft:durability\n\rdamage_chance\x03\x03max\xC8\x01\x03\x03min\0\0\x03\x0Emax_durabilityx\0\n\x12minecraft:cooldown\x08\x04type\x06attack\x08\x08category\x05spear\x05\x08durationff&?\0\n\x14minecraft:repairable\t\x0Crepair_items\n\x04\x08\rrepair_amount)context.other->query.remaining_durability\t\x05items\n\x02\x08\x04name\x16minecraft:wooden_spear\0\0\t\x05items\n\x02\x08\x04tags\x1Eq.all_tags('minecraft:planks')\0\x08\rrepair_amount\x1Bquery.max_durability * 0.25\0\0\n\x0Eminecraft:tags\t\x04tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\0\n\x18minecraft:kinetic_weapon\n\x18minecraft:kinetic_weapon\x02\x05delay\x0F\0\x05\x0Fdamage_modifier\0\0\0\0\n\x14knockback_conditions\x05\x12min_relative_speed\0\0\0\0\x02\x0Cmax_duration\xC8\0\x05\tmin_speed33\xA3@\0\x05\rhitbox_margin\0\0\x80>\n\x11damage_conditions\x02\x0Cmax_duration,\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\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\x05\x11damage_multiplier333?\n\x13dismount_conditions\x02\x0Cmax_durationd\0\x05\x12min_relative_speed\0\0\0\0\x05\tmin_speed\0\0`A\0\0\0\n\x19minecraft:piercing_weapon\n\x0Ecreative_reach\x05\x03max\0\0\xF0@\x05\x03min\0\0\0@\0\n\x05reach\x05\x03min\0\0\0@\x05\x03max\0\0\x90@\0\x05\rhitbox_margin\0\0\x80>\0\t\titem_tags\x08\x04\x15minecraft:wooden_tier\x12minecraft:is_spear\n\x0Fitem_properties\x08\x10enchantable_slot\x0Bmelee_spear\x01\x0Eshould_despawn\x01\x03\x0Bframe_count\x02\x01\x12hidden_in_commands\x02\x08\x0Ecreative_group\0\x01\rhand_equipped\x01\x03\x11enchantable_value\x1E\x03\x06damage\x02\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x03\x0Emax_stack_size\x02\x01\x04foil\0\x05\x0Cmining_speed\0\0\x80?\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\x80\xE4\xAF\x01\x01\x17can_destroy_in_creative\x01\n\x0Eminecraft:icon\n\x08textures\x08\x07default\nwood_spear\0\0\x01\x0Eallow_off_hand\0\x03\x11creative_category\x06\0\n\x0Eminecraft:fuel\x05\x08duration\0\0 A\0\n\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x18minecraft:swing_duration\x05\x05valueff&?\0\n\x17minecraft:hand_equipped\x01\x05value\x01\0\n\x16minecraft:swing_sounds\x08\nattack_hit\x1Citem.wooden_spear.attack_hit\x08\x0Battack_miss\x1Ditem.wooden_spear.attack_miss\0\n\x16minecraft:display_name\x08\x05value\x16item.wooden_spear.name\0\0\0" } ;
pub const WOODEN_SWORD: Self = Self {
id: 310,
registry_key: "minecraft:wooden_sword",
@ -80596,7 +80596,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\x0Fitem_properties\x01\x12hidden_in_commands\x02\x03\x06damage\0\x08\x0Ecreative_group\0\x03\x0Bframe_count\x02\x01\rhand_equipped\0\x01\x0Fstacked_by_data\0\x03\ruse_animation\0\x05\x0Cmining_speed\0\0\x80?\x01\x04foil\0\x03\x11creative_category\x06\x01\x0Eliquid_clipped\0\x03\x0Cuse_duration\0\n\x0Eminecraft:icon\n\x08textures\x08\x07default\rbundle_yellow\x08\x11bundle_open_front\x18bundle_yellow_open_front\x08\x10bundle_open_back\x17bundle_yellow_open_back\0\0\x03\x0Emax_stack_size\x02\x08\x10enchantable_slot\x04none\x01\x0Eshould_despawn\x01\x01\x0Eallow_off_hand\0\x03\x11enchantable_value\0\x01\x17can_destroy_in_creative\x01\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\rallowed_items\0\0\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\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 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\x18minecraft:max_stack_size\x01\x05value\x01\0\n\x1Eminecraft:storage_weight_limit\x03\x10max_weight_limit\x80\x01\0\n\x0Fitem_properties\x08\x0Ecreative_group\0\x01\x0Fstacked_by_data\0\x03\x06damage\0\x01\x0Eliquid_clipped\0\n\x0Eminecraft:icon\n\x08textures\x08\x10bundle_open_back\x17bundle_yellow_open_back\x08\x11bundle_open_front\x18bundle_yellow_open_front\x08\x07default\rbundle_yellow\0\0\x05\x0Cmining_speed\0\0\x80?\x01\rhand_equipped\0\x03\ruse_animation\0\x01\x12hidden_in_commands\x02\x03\x0Bframe_count\x02\x08\x10enchantable_slot\x04none\x01\x0Eallow_off_hand\0\x01\x0Eshould_despawn\x01\x03\x0Emax_stack_size\x02\x03\x11enchantable_value\0\x03\x0Cuse_duration\0\x01\x17can_destroy_in_creative\x01\x03\x11creative_category\x06\x01\x04foil\0\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\t\rallowed_items\0\0\x01\x1Aallow_nested_storage_items\x01\0\n\x1Cminecraft:bundle_interaction\x03\x12num_viewable_slots\x18\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 one or more lines are too long

View File

@ -19,6 +19,7 @@ pumpkin-world.workspace = true
pumpkin-util.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
cesu8.workspace = true
uuid.workspace = true
thiserror.workspace = true

View File

@ -34,10 +34,9 @@ use pumpkin_data::data_component_type_id_remap::{
remap_data_component_type_id_for_version, remap_data_component_type_id_from_version,
};
fn serialize_any_item_stack_with_id(
fn serialize_item_stack_with_id(
stack: &ItemStack,
item_id: u16,
is_template: bool,
version: JavaMinecraftVersion,
write: &mut impl NetworkWriteExt,
) -> Result<(), WritingError> {
@ -46,13 +45,8 @@ fn serialize_any_item_stack_with_id(
write.put_var_int(&VarInt(0))
} else {
let (to_add, to_remove) = item_component_counts(stack);
if is_template {
write.put_var_int(&VarInt::from(item_id))?;
write.put_var_int(&VarInt::from(stack.item_count))?;
} else {
write.put_var_int(&VarInt::from(stack.item_count))?;
write.put_var_int(&VarInt::from(item_id))?;
}
write.put_var_int(&VarInt::from(stack.item_count))?;
write.put_var_int(&VarInt::from(item_id))?;
write.put_var_int(&VarInt::from(to_add))?;
write.put_var_int(&VarInt::from(to_remove))?;
@ -75,7 +69,7 @@ fn serialize_any_item_stack_with_id(
Ok(())
}
} else if version >= JavaMinecraftVersion::V_1_13 {
} else if version >= JavaMinecraftVersion::V_1_13_2 {
if stack.is_empty() {
write.write_bool(false)
} else {
@ -85,8 +79,18 @@ fn serialize_any_item_stack_with_id(
write.write_u8(0)?; // TAG_End (no NBT)
Ok(())
}
} else if version >= JavaMinecraftVersion::V_1_13 {
// 1.13 and 1.13.1: short id (-1 if empty), byte count, TAG_End
if stack.is_empty() {
write.write_i16_be(-1)
} else {
write.write_i16_be(item_id as i16)?;
write.write_i8(stack.item_count as i8)?;
write.write_u8(0)?; // TAG_End (no NBT)
Ok(())
}
} else {
// <= 1.12.2
// <= 1.12.2: short id (-1 if empty), byte count, short damage, TAG_End
if stack.is_empty() {
write.write_i16_be(-1)
} else {
@ -99,15 +103,6 @@ fn serialize_any_item_stack_with_id(
}
}
fn serialize_item_stack_with_id(
stack: &ItemStack,
item_id: u16,
version: JavaMinecraftVersion,
write: &mut impl NetworkWriteExt,
) -> Result<(), WritingError> {
serialize_any_item_stack_with_id(stack, item_id, false, version, write)
}
fn serialize_length_prefixed_item_stack_with_id(
stack: &ItemStack,
item_id: u16,
@ -147,7 +142,7 @@ fn serialize_length_prefixed_item_stack_with_id(
Ok(())
}
} else {
serialize_any_item_stack_with_id(stack, item_id, false, version, write)
serialize_item_stack_with_id(stack, item_id, version, write)
}
}
@ -331,23 +326,44 @@ impl ItemStackSerializer<'_> {
version: &JavaMinecraftVersion,
) -> Result<ItemStackSerializer<'static>, ReadingError> {
if *version >= JavaMinecraftVersion::V_1_20_5 {
Self::read(read)
} else if *version >= JavaMinecraftVersion::V_1_13 {
let serializer = Self::read(read)?;
if *version < JavaMinecraftVersion::V_26_2 {
Ok(ItemStackSerializer(Cow::Owned(
serializer.to_stack_for_version(version),
)))
} else {
Ok(serializer)
}
} else if *version >= JavaMinecraftVersion::V_1_13_2 {
let present = read.get_bool()?;
if !present {
return Ok(ItemStackSerializer(Cow::Borrowed(ItemStack::EMPTY)));
}
let item_id = read.get_var_int()?.0 as u16;
let raw_item_id = read.get_var_int()?.0 as u16;
let count = read.get_i8()? as u8;
let nbt_type = read.get_u8()?;
if nbt_type != 0 {
// TAG_End is 0 when no NBT is present
}
let item_id = remap_item_id_from_version(raw_item_id, *version);
let item = Item::from_id(item_id).unwrap_or(&Item::AIR);
Ok(ItemStackSerializer(Cow::Owned(ItemStack::new(count, item))))
} else if *version >= JavaMinecraftVersion::V_1_13 {
let raw_item_id = read.get_i16_be()?;
if raw_item_id == -1 || raw_item_id < 0 {
return Ok(ItemStackSerializer(Cow::Borrowed(ItemStack::EMPTY)));
}
let count = read.get_i8()? as u8;
let nbt_type = read.get_u8()?;
if nbt_type != 0 {
// TAG_End is 0 when no NBT is present
}
let item_id = remap_item_id_from_version(raw_item_id as u16, *version);
let item = Item::from_id(item_id).unwrap_or(&Item::AIR);
Ok(ItemStackSerializer(Cow::Owned(ItemStack::new(count, item))))
} else {
let item_id = read.get_i16_be()?;
if item_id == -1 || item_id < 0 {
let raw_item_id = read.get_i16_be()?;
if raw_item_id == -1 || raw_item_id < 0 {
return Ok(ItemStackSerializer(Cow::Borrowed(ItemStack::EMPTY)));
}
let count = read.get_i8()? as u8;
@ -356,18 +372,126 @@ impl ItemStackSerializer<'_> {
if nbt_type != 0 {
// TAG_End is 0 when no NBT is present
}
let item = Item::from_id(item_id as u16).unwrap_or(&Item::AIR);
let item_id = remap_item_id_from_version(raw_item_id as u16, *version);
let item = Item::from_id(item_id).unwrap_or(&Item::AIR);
Ok(ItemStackSerializer(Cow::Owned(ItemStack::new(count, item))))
}
}
pub fn read_untrusted_with_version(
read: &mut impl NetworkReadExt,
version: &JavaMinecraftVersion,
) -> Result<ItemStackSerializer<'static>, ReadingError> {
if *version >= JavaMinecraftVersion::V_1_21_5 {
let serializer = Self::read_length_prefixed_optional(read)?;
if *version < JavaMinecraftVersion::V_26_2 {
Ok(ItemStackSerializer(Cow::Owned(
serializer.to_stack_for_version(version),
)))
} else {
Ok(serializer)
}
} else {
Self::read_with_version(read, version)
}
}
pub fn read_template_with_version(
read: &mut impl NetworkReadExt,
version: &JavaMinecraftVersion,
) -> Result<ItemStackSerializer<'static>, ReadingError> {
if *version < JavaMinecraftVersion::V_26_1 {
Self::read_with_version(read, version)
} else {
Self::read_template0(read, version)
}
}
pub fn read_optional_template_with_version(
read: &mut impl NetworkReadExt,
version: &JavaMinecraftVersion,
) -> Result<ItemStackSerializer<'static>, ReadingError> {
if *version < JavaMinecraftVersion::V_26_1 {
Self::read_with_version(read, version)
} else if read.get_bool()? {
Self::read_template0(read, version)
} else {
Ok(ItemStackSerializer(Cow::Borrowed(ItemStack::EMPTY)))
}
}
pub fn read_template0(
read: &mut impl NetworkReadExt,
version: &JavaMinecraftVersion,
) -> Result<ItemStackSerializer<'static>, ReadingError> {
const MAX_COMPONENTS: i32 = 256;
let raw_item_id = read.get_var_int()?;
let item_count = read.get_var_int()?;
let item_id_u16: u16 = raw_item_id
.0
.try_into()
.map_err(|_| ReadingError::Message("Invalid item id!".into()))?;
let item_id = remap_item_id_from_version(item_id_u16, *version);
let item = Item::from_id(item_id).unwrap_or(&Item::AIR);
let num_to_add = read.get_var_int()?.0;
let num_to_remove = read.get_var_int()?.0;
if num_to_add < 0 || num_to_remove < 0 {
return Err(ReadingError::Message("Negative component count".into()));
}
let total_components = num_to_add
.checked_add(num_to_remove)
.ok_or_else(|| ReadingError::Message("Component count overflow".into()))?;
if total_components > MAX_COMPONENTS {
return Err(ReadingError::Message(
"Too many components in ItemStack patch".into(),
));
}
let mut patch = Vec::with_capacity(total_components as usize);
for _ in 0..num_to_add {
let id_val = read.get_var_int()?.0;
let remapped_comp_id =
remap_data_component_type_id_from_version(id_val as u32, *version);
let id = DataComponent::try_from_id(remapped_comp_id as u8)
.ok_or_else(|| ReadingError::Message(format!("Unknown component ID: {id_val}")))?;
let component_impl = deserialize(id, read)?;
patch.push((id, Some(component_impl)));
}
for _ in 0..num_to_remove {
let id_val = read.get_var_int()?.0;
let remapped_comp_id =
remap_data_component_type_id_from_version(id_val as u32, *version);
let id = DataComponent::try_from_id(remapped_comp_id as u8)
.ok_or_else(|| ReadingError::Message("Unknown component ID".into()))?;
patch.push((id, None));
}
let item_count_u8: u8 = item_count
.0
.try_into()
.map_err(|_| ReadingError::Message("Invalid item count!".into()))?;
let stack = ItemStack::new_with_component(item_count_u8, item, patch);
if stack.is_empty() {
return Err(ReadingError::Message(
"Can't read empty item stack template".into(),
));
}
Ok(ItemStackSerializer(Cow::Owned(stack)))
}
pub fn write(&self, write: &mut impl NetworkWriteExt) -> Result<(), WritingError> {
serialize_item_stack_with_id(
self.0.as_ref(),
self.0.item.id,
JavaMinecraftVersion::V_26_2,
write,
)
self.write_with_version(write, &JavaMinecraftVersion::V_26_2)
}
pub fn read_length_prefixed_optional(
@ -459,6 +583,82 @@ impl ItemStackSerializer<'_> {
serialize_item_cost_with_id(self.0.as_ref(), remapped_item_id, *version, write)
}
pub fn write_untrusted_with_version(
&self,
write: &mut impl NetworkWriteExt,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
if *version >= JavaMinecraftVersion::V_1_21_5 {
self.write_length_prefixed_with_version(write, version)
} else {
self.write_with_version(write, version)
}
}
pub fn write_template_with_version(
&self,
write: &mut impl NetworkWriteExt,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
if *version < JavaMinecraftVersion::V_26_1 {
self.write_with_version(write, version)
} else {
self.write_template0(write, version)
}
}
pub fn write_optional_template_with_version(
&self,
write: &mut impl NetworkWriteExt,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
if *version < JavaMinecraftVersion::V_26_1 {
self.write_with_version(write, version)
} else if !self.0.is_empty() {
write.write_bool(true)?;
self.write_template0(write, version)
} else {
write.write_bool(false)
}
}
pub fn write_template0(
&self,
write: &mut impl NetworkWriteExt,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
if self.0.is_empty() {
return Err(WritingError::Message(
"Can't write empty item stack template".into(),
));
}
let remapped_item_id = remap_item_id_for_version(self.0.item.id, *version);
let (to_add, to_remove) = item_component_counts(self.0.as_ref());
write.put_var_int(&VarInt::from(remapped_item_id))?;
write.put_var_int(&VarInt::from(self.0.item_count))?;
write.put_var_int(&VarInt::from(to_add))?;
write.put_var_int(&VarInt::from(to_remove))?;
for (id, data) in &self.0.patch {
if let Some(data) = data {
let remapped_comp_id =
remap_data_component_type_id_for_version(u32::from(id.to_id()), *version);
write.put_var_int(&VarInt(remapped_comp_id as i32))?;
serialize(*id, data.as_ref(), write)?;
}
}
for (id, data) in &self.0.patch {
if data.is_none() {
let remapped_comp_id =
remap_data_component_type_id_for_version(u32::from(id.to_id()), *version);
write.put_var_int(&VarInt(remapped_comp_id as i32))?;
}
}
Ok(())
}
#[must_use]
pub fn to_stack(self) -> ItemStack {
self.0.into_owned()
@ -649,24 +849,12 @@ impl ItemStackTemplateSerializer<'_> {
write: &mut impl NetworkWriteExt,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
let remapped_item_id = remap_item_id_for_version(self.0.item.id, *version);
serialize_any_item_stack_with_id(
self.0.as_ref(),
remapped_item_id,
*version >= JavaMinecraftVersion::V_26_1,
*version,
write,
)
let serializer = ItemStackSerializer(Cow::Borrowed(self.0.as_ref()));
serializer.write_template_with_version(write, version)
}
pub fn write(&self, write: &mut impl NetworkWriteExt) -> Result<(), WritingError> {
serialize_any_item_stack_with_id(
self.0.as_ref(),
self.0.item.id,
true,
JavaMinecraftVersion::V_26_2,
write,
)
self.write_with_version(write, &JavaMinecraftVersion::V_26_2)
}
}
@ -675,3 +863,35 @@ impl From<ItemStack> for ItemStackTemplateSerializer<'_> {
ItemStackTemplateSerializer(Cow::Owned(item))
}
}
pub struct ItemStackOptionalTemplateSerializer<'a>(pub Cow<'a, ItemStack>);
impl ItemStackOptionalTemplateSerializer<'_> {
pub fn write_with_version(
&self,
write: &mut impl NetworkWriteExt,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
let serializer = ItemStackSerializer(Cow::Borrowed(self.0.as_ref()));
serializer.write_optional_template_with_version(write, version)
}
pub fn write(&self, write: &mut impl NetworkWriteExt) -> Result<(), WritingError> {
self.write_with_version(write, &JavaMinecraftVersion::V_26_2)
}
}
impl From<ItemStack> for ItemStackOptionalTemplateSerializer<'_> {
fn from(item: ItemStack) -> Self {
ItemStackOptionalTemplateSerializer(Cow::Owned(item))
}
}
impl From<Option<ItemStack>> for ItemStackOptionalTemplateSerializer<'_> {
fn from(item: Option<ItemStack>) -> Self {
item.map_or_else(
|| ItemStackOptionalTemplateSerializer(Cow::Borrowed(ItemStack::EMPTY)),
ItemStackOptionalTemplateSerializer::from,
)
}
}

View File

@ -19,7 +19,7 @@ impl<'a> DialogNBT<'a> {
pub fn write_packet_data(
&self,
mut write: impl std::io::Write,
_version: &JavaMinecraftVersion,
version: &JavaMinecraftVersion,
) -> Result<(), crate::ser::WritingError> {
match &self.0 {
DialogNBTSource::Struct(_dialog) => Err(crate::ser::WritingError::Message(
@ -27,7 +27,7 @@ impl<'a> DialogNBT<'a> {
)),
DialogNBTSource::Nbt(nbt) => {
let tag = pumpkin_nbt::tag::NbtTag::Compound((*nbt).clone());
write.write_nbt(tag)?;
write.write_nbt_with_version(Some(&tag), version)?;
Ok(())
}
}

View File

@ -3,20 +3,15 @@ use pumpkin_util::version::JavaMinecraftVersion;
use pumpkin_world::chunk::format::LightContainer;
use std::io::Write;
use crate::ser::NetworkWriteExt;
/// Writes an NBT compound tag to the writer, formatted appropriately for the target Minecraft version.
pub fn write_compound_nbt(
mut write: impl Write,
comp: pumpkin_nbt::compound::NbtCompound,
comp: &pumpkin_nbt::compound::NbtCompound,
version: JavaMinecraftVersion,
) -> Result<(), WritingError> {
if version >= JavaMinecraftVersion::V_1_20_2 {
let bytes = pumpkin_nbt::Nbt::from(comp).write_unnamed();
write.write_all(&bytes)?;
} else {
let bytes = pumpkin_nbt::Nbt::from(comp).write();
write.write_all(&bytes)?;
}
Ok(())
write.write_compound_nbt_with_version(Some(comp), &version)
}
/// Retrieves the 2048-byte nibble array from a light container, filling with `default_val` if empty.

View File

@ -67,7 +67,7 @@ pub fn write_chunk_data(
pumpkin_nbt::tag::NbtTag::LongArray(mbnl.to_vec()),
);
}
write_compound_nbt(&mut write, comp, *version)?;
write_compound_nbt(&mut write, &comp, *version)?;
}
drop(heightmaps);
@ -245,7 +245,7 @@ pub fn write_chunk_data(
client_nbt.child_tags.remove("LootTableSeed");
client_nbt.child_tags.remove("PumpkinCustomData");
client_nbt.child_tags.remove("BukkitValues");
write_compound_nbt(&mut write, client_nbt, *version)?;
write_compound_nbt(&mut write, &client_nbt, *version)?;
}
{

View File

@ -108,7 +108,7 @@ pub fn write_chunk_data(
"MOTION_BLOCKING_NO_LEAVES",
pumpkin_nbt::tag::NbtTag::LongArray(mbnl_vec),
);
write_compound_nbt(&mut write, comp, *version)?;
write_compound_nbt(&mut write, &comp, *version)?;
}
if version >= &JavaMinecraftVersion::V_1_15 {
@ -266,7 +266,7 @@ pub fn write_chunk_data(
entity_nbt.put("x", pumpkin_nbt::tag::NbtTag::Int(pos.0.x));
entity_nbt.put("y", pumpkin_nbt::tag::NbtTag::Int(pos.0.y));
entity_nbt.put("z", pumpkin_nbt::tag::NbtTag::Int(pos.0.z));
write_compound_nbt(&mut write, entity_nbt, *version)?;
write_compound_nbt(&mut write, &entity_nbt, *version)?;
}
}

View File

@ -338,9 +338,9 @@ impl MetadataSerializer for crate::codec::item_stack_seralizer::ItemStackSeriali
fn write_metadata(
&self,
writer: &mut impl std::io::Write,
_version: &JavaMinecraftVersion,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
self.write(writer)
self.write_with_version(writer, version)
}
}

View File

@ -1,75 +1,219 @@
use pumpkin_data::packet::clientbound::play::SECTION_BLOCKS_UPDATE;
use pumpkin_data::{BlockStateId, block_state_remap::remap_block_state_for_version};
use pumpkin_util::math::{
position::{BlockPos, chunk_section_from_pos, pack_local_chunk_section},
vector3::{self},
};
use pumpkin_util::version::JavaMinecraftVersion;
use pumpkin_macros::java_packet;
use pumpkin_util::math::position::{BlockPos, chunk_section_from_pos, pack_local_chunk_section};
use pumpkin_util::math::vector3::{self, Vector3};
use pumpkin_util::version::JavaMinecraftVersion;
use std::io::Write;
use crate::{
ClientPacket,
ClientPacket, ServerPacket,
codec::{var_int::VarInt, var_long::VarLong},
ser::{NetworkWriteExt, WritingError},
ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError},
};
/// Updates multiple blocks within a single 16x16x16 chunk section.
/// Updates multiple blocks within a single chunk section (or chunk in older versions).
///
/// This packet is much more efficient than sending multiple individual
/// `CBlockUpdate` packets when many changes occur in the same area
/// (e.g., explosions, structure generation, or large-scale terraforming).
#[java_packet(SECTION_BLOCKS_UPDATE)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CMultiBlockUpdate {
/// Chunk section position (x << 42 | z << 20 | y)
pub chunk_section: i64,
/// Array of `VarLongs`: (Block State ID << 12 | Relative Position)
pub updates: Vec<VarLong>,
/// Chunk section position (x, y, z)
pub chunk_section: Vector3<i32>,
/// Suppress light updates (used in 1.16..=1.19.4)
pub suppress_light_updates: bool,
/// Array of block updates: (`BlockPos`, `BlockStateId`)
pub updates: Vec<(BlockPos, BlockStateId)>,
}
impl CMultiBlockUpdate {
#[must_use]
pub fn new(updates: &[(BlockPos, BlockStateId)]) -> Self {
let first_pos = updates[0].0;
let chunk_section_vec = chunk_section_from_pos(&first_pos);
let chunk_section = vector3::packed_chunk_pos(&chunk_section_vec);
let packed_updates = updates
.iter()
.map(|(pos, state_id)| {
let local_pos = pack_local_chunk_section(pos) as u64;
let packed = (u64::from(state_id.as_u16()) << 12) | (local_pos & 0xFFF);
VarLong(packed as i64)
})
.collect();
let chunk_section = updates
.first()
.map_or_else(Vector3::default, |(pos, _)| chunk_section_from_pos(pos));
Self {
chunk_section,
updates: packed_updates,
suppress_light_updates: false,
updates: updates.to_vec(),
}
}
#[must_use]
pub const fn new_with_section(
chunk_section: Vector3<i32>,
suppress_light_updates: bool,
updates: Vec<(BlockPos, BlockStateId)>,
) -> Self {
Self {
chunk_section,
suppress_light_updates,
updates,
}
}
}
impl ClientPacket for CMultiBlockUpdate {
fn write_packet_data(
&self,
write: impl Write,
mut write: impl Write,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
let mut write = write;
write.write_i64_be(self.chunk_section)?;
write.write_var_int(&VarInt(self.updates.len() as i32))?;
if *version >= JavaMinecraftVersion::V_1_16 {
let chunk_section = vector3::packed_chunk_pos(&self.chunk_section);
write.write_i64_be(chunk_section)?;
for update in &self.updates {
let packed_update = update.0 as u64;
let local_pos = packed_update & 0xFFF;
let state_id = (packed_update >> 12) as u16;
let remapped_state_id = remap_block_state_for_version(state_id, *version);
let remapped_packed = (u64::from(remapped_state_id) << 12) | local_pos;
write.write_var_long(&VarLong(remapped_packed as i64))?;
if *version <= JavaMinecraftVersion::V_1_19_4 {
write.write_bool(self.suppress_light_updates)?;
}
write.write_var_int(&VarInt(self.updates.len() as i32))?;
for (pos, state_id) in &self.updates {
let local_pos = pack_local_chunk_section(pos) as u64;
let remapped_state_id = remap_block_state_for_version(state_id.as_u16(), *version);
let packed = (u64::from(remapped_state_id) << 12) | (local_pos & 0xFFF);
write.write_var_long(&VarLong(packed as i64))?;
}
} else if *version <= JavaMinecraftVersion::V_1_7_6 {
write.write_i32_be(self.chunk_section.x)?;
write.write_i32_be(self.chunk_section.z)?;
write.write_i16_be(self.updates.len() as i16)?;
write.write_i32_be((self.updates.len() * 4) as i32)?;
for (pos, state_id) in &self.updates {
let rel_x = (pos.0.x & 0xF) as u16;
let rel_z = (pos.0.z & 0xF) as u16;
let rel_y = (pos.0.y & 0xFF) as u16;
let packed_pos = (rel_x << 12) | (rel_z << 8) | rel_y;
write.write_i16_be(packed_pos as i16)?;
let remapped_state_id = remap_block_state_for_version(state_id.as_u16(), *version);
write.write_i16_be(remapped_state_id as i16)?;
}
} else {
write.write_i32_be(self.chunk_section.x)?;
write.write_i32_be(self.chunk_section.z)?;
write.write_var_int(&VarInt(self.updates.len() as i32))?;
for (pos, state_id) in &self.updates {
let rel_x = (pos.0.x & 0xF) as u16;
let rel_z = (pos.0.z & 0xF) as u16;
let rel_y = (pos.0.y & 0xFF) as u16;
let packed_pos = (rel_x << 12) | (rel_z << 8) | rel_y;
write.write_i16_be(packed_pos as i16)?;
let remapped_state_id = remap_block_state_for_version(state_id.as_u16(), *version);
write.write_var_int(&VarInt(i32::from(remapped_state_id)))?;
}
}
Ok(())
}
}
impl<'a> ServerPacket<'a> for CMultiBlockUpdate {
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
if *version >= JavaMinecraftVersion::V_1_16 {
let encoded_pos = bytebuf.get_i64_be()?;
let chunk_section = vector3::unpacked_chunk_pos(encoded_pos);
let suppress_light_updates = if *version <= JavaMinecraftVersion::V_1_19_4 {
bytebuf.get_bool()?
} else {
false
};
let count = bytebuf.get_var_int()?.0 as usize;
let mut updates = Vec::with_capacity(count);
for _ in 0..count {
let val = bytebuf.get_var_long()?.0 as u64;
let local_pos = (val & 0xFFF) as i32;
let state_id = (val >> 12) as u16;
let rel_x = (local_pos >> 8) & 0xF;
let rel_z = (local_pos >> 4) & 0xF;
let rel_y = local_pos & 0xF;
let block_pos = BlockPos::new(
(chunk_section.x << 4) + rel_x,
(chunk_section.y << 4) + rel_y,
(chunk_section.z << 4) + rel_z,
);
updates.push((block_pos, BlockStateId::new_or_air(state_id)));
}
Ok(Self {
chunk_section,
suppress_light_updates,
updates,
})
} else if *version <= JavaMinecraftVersion::V_1_7_6 {
let chunk_x = bytebuf.get_i32_be()?;
let chunk_z = bytebuf.get_i32_be()?;
let count = bytebuf.get_i16_be()? as usize;
let _data_size = bytebuf.get_i32_be()?;
let mut updates = Vec::with_capacity(count);
for _ in 0..count {
let pos = bytebuf.get_i16_be()? as u16;
let rel_x = ((pos >> 12) & 0xF) as i32;
let rel_z = ((pos >> 8) & 0xF) as i32;
let y = (pos & 0xFF) as i32;
let x = (chunk_x << 4) + rel_x;
let z = (chunk_z << 4) + rel_z;
let block_state_id = bytebuf.get_i16_be()? as u16;
updates.push((
BlockPos::new(x, y, z),
BlockStateId::new_or_air(block_state_id),
));
}
let chunk_section = updates.first().map_or_else(
|| Vector3::new(chunk_x, 0, chunk_z),
|(pos, _)| chunk_section_from_pos(pos),
);
Ok(Self {
chunk_section,
suppress_light_updates: false,
updates,
})
} else {
let chunk_x = bytebuf.get_i32_be()?;
let chunk_z = bytebuf.get_i32_be()?;
let count = bytebuf.get_var_int()?.0 as usize;
let mut updates = Vec::with_capacity(count);
for _ in 0..count {
let pos = bytebuf.get_i16_be()? as u16;
let rel_x = ((pos >> 12) & 0xF) as i32;
let rel_z = ((pos >> 8) & 0xF) as i32;
let y = (pos & 0xFF) as i32;
let x = (chunk_x << 4) + rel_x;
let z = (chunk_z << 4) + rel_z;
let block_state_id = bytebuf.get_var_int()?.0 as u16;
updates.push((
BlockPos::new(x, y, z),
BlockStateId::new_or_air(block_state_id),
));
}
let chunk_section = updates.first().map_or_else(
|| Vector3::new(chunk_x, 0, chunk_z),
|(pos, _)| chunk_section_from_pos(pos),
);
Ok(Self {
chunk_section,
suppress_light_updates: false,
updates,
})
}
}
}

View File

@ -2,7 +2,8 @@ use std::io::Write;
use crate::VarInt;
use crate::codec::item_stack_seralizer::ItemStackSerializer;
use crate::{ClientPacket, WritingError, ser::NetworkWriteExt};
use crate::ser::{NetworkReadExt, ReadingError};
use crate::{ClientPacket, ServerPacket, WritingError, ser::NetworkWriteExt};
use pumpkin_data::packet::clientbound::play::CONTAINER_SET_CONTENT;
use pumpkin_macros::java_packet;
@ -72,3 +73,39 @@ impl ClientPacket for CSetContainerContent<'_> {
Ok(())
}
}
impl<'a> ServerPacket<'a> for CSetContainerContent<'a> {
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let window_id = bytebuf.get_container_id(version)?;
let state_id = if *version >= JavaMinecraftVersion::V_1_17_1 {
bytebuf.get_var_int()?
} else {
VarInt(0)
};
let count = if *version >= JavaMinecraftVersion::V_1_17_1 {
bytebuf.get_var_int()?.0
} else {
i32::from(bytebuf.get_i16_be()?)
};
if !(0..=4096).contains(&count) {
return Err(ReadingError::Message("Slot count out of bounds".into()));
}
let mut slot_data = Vec::with_capacity(count as usize);
for _ in 0..count {
slot_data.push(ItemStackSerializer::read_with_version(bytebuf, version)?);
}
let carried_item = if *version >= JavaMinecraftVersion::V_1_17_1 {
ItemStackSerializer::read_with_version(bytebuf, version)?
} else {
ItemStackSerializer(std::borrow::Cow::Borrowed(
pumpkin_data::item_stack::ItemStack::EMPTY,
))
};
Ok(Self {
window_id,
state_id,
slot_data: Box::leak(slot_data.into_boxed_slice()),
carried_item: Box::leak(Box::new(carried_item)),
})
}
}

View File

@ -2,7 +2,8 @@ use std::io::Write;
use crate::VarInt;
use crate::codec::item_stack_seralizer::ItemStackSerializer;
use crate::{ClientPacket, WritingError, ser::NetworkWriteExt};
use crate::ser::{NetworkReadExt, ReadingError};
use crate::{ClientPacket, ServerPacket, WritingError, ser::NetworkWriteExt};
use pumpkin_data::packet::clientbound::play::CONTAINER_SET_SLOT;
use pumpkin_macros::java_packet;
@ -51,3 +52,22 @@ impl ClientPacket for CSetContainerSlot<'_> {
Ok(())
}
}
impl<'a> ServerPacket<'a> for CSetContainerSlot<'a> {
fn read(bytebuf: &mut &'a [u8], version: &JavaMinecraftVersion) -> Result<Self, ReadingError> {
let window_id = bytebuf.get_container_id(version)?.0 as i8;
let state_id = if *version >= JavaMinecraftVersion::V_1_17_1 {
bytebuf.get_var_int()?
} else {
VarInt(0)
};
let slot = bytebuf.get_i16_be()?;
let slot_data = ItemStackSerializer::read_with_version(bytebuf, version)?;
Ok(Self {
window_id,
state_id,
slot,
slot_data: Box::leak(Box::new(slot_data)),
})
}
}

View File

@ -9,7 +9,9 @@ use crate::{
},
};
use pumpkin_nbt::{serializer::NbtWriteHelperJava, tag::NbtTag};
use pumpkin_nbt::{
compound::NbtCompound, deserializer::NbtReadHelper, serializer::NbtWriteHelperJava, tag::NbtTag,
};
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::{text::TextComponent, version::JavaMinecraftVersion};
use thiserror::Error;
@ -50,6 +52,71 @@ impl serde::ser::Error for WritingError {
}
}
struct NetworkReadDataSource<'a, R: NetworkReadExt + ?Sized>(&'a mut R);
impl<'a, R: NetworkReadExt + ?Sized> pumpkin_nbt::deserializer::NbtDataSource<'a>
for NetworkReadDataSource<'a, R>
{
fn read_u8(&mut self) -> Result<u8, pumpkin_nbt::Error> {
self.0.get_u8().map_err(|e| {
pumpkin_nbt::Error::Incomplete(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
e.to_string(),
))
})
}
fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), pumpkin_nbt::Error> {
self.0.read_bytes_to_buf(buf).map_err(|e| {
pumpkin_nbt::Error::Incomplete(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
e.to_string(),
))
})
}
fn seek_relative(&mut self, offset: i64) -> Result<(), pumpkin_nbt::Error> {
if offset < 0 {
return Err(pumpkin_nbt::Error::Incomplete(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"negative seek not supported",
)));
}
let mut skipped = vec![0u8; offset as usize];
self.0.read_bytes_to_buf(&mut skipped).map_err(|e| {
pumpkin_nbt::Error::Incomplete(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
e.to_string(),
))
})
}
fn read_string(&mut self, len: usize) -> Result<Cow<'a, str>, pumpkin_nbt::Error> {
let mut buf = vec![0u8; len];
self.0.read_bytes_to_buf(&mut buf).map_err(|e| {
pumpkin_nbt::Error::Incomplete(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
e.to_string(),
))
})?;
let string =
cesu8::from_java_cesu8(&buf).map_err(|_| pumpkin_nbt::Error::Cesu8DecodingError)?;
Ok(Cow::Owned(string.into_owned()))
}
fn read_byte_array(&mut self, len: usize) -> Result<Cow<'a, [i8]>, pumpkin_nbt::Error> {
let mut buf = vec![0u8; len];
self.0.read_bytes_to_buf(&mut buf).map_err(|e| {
pumpkin_nbt::Error::Incomplete(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
e.to_string(),
))
})?;
let i8_buf: Vec<i8> = buf.into_iter().map(|b| b as i8).collect();
Ok(Cow::Owned(i8_buf))
}
}
pub trait NetworkReadExt {
fn get_i8(&mut self) -> Result<i8, ReadingError>;
fn get_u8(&mut self) -> Result<u8, ReadingError>;
@ -159,6 +226,83 @@ pub trait NetworkReadExt {
}
Ok(list)
}
fn get_nbt_with_version(
&mut self,
version: &JavaMinecraftVersion,
) -> Result<Option<NbtTag>, ReadingError> {
if *version >= JavaMinecraftVersion::V_1_8 {
let tag_id = self.get_u8()?;
if tag_id == pumpkin_nbt::END_ID {
return Ok(None);
}
let mut helper =
pumpkin_nbt::deserializer::NbtReadHelperJava::new(NetworkReadDataSource(self));
if *version < JavaMinecraftVersion::V_1_20_2 {
let _name = helper
.get_string()
.map_err(|e| ReadingError::Message(e.to_string()))?;
}
let tag = if tag_id == pumpkin_nbt::COMPOUND_ID {
NbtTag::Compound(
NbtCompound::deserialize_content(&mut helper)
.map_err(|e| ReadingError::Message(e.to_string()))?,
)
} else {
NbtTag::deserialize_data(&mut helper, tag_id)
.map_err(|e| ReadingError::Message(e.to_string()))?
};
Ok(Some(tag))
} else {
let length = self.get_i16_be()?;
if length <= 0 {
return Ok(None);
}
let mut compressed = vec![0u8; length as usize];
self.read_bytes_to_buf(&mut compressed)?;
let mut decoder = flate2::read::GzDecoder::new(&compressed[..]);
let mut decompressed = Vec::new();
decoder
.read_to_end(&mut decompressed)
.map_err(|e| ReadingError::Message(e.to_string()))?;
let mut cursor = std::io::Cursor::new(decompressed);
let mut helper = pumpkin_nbt::deserializer::NbtReadHelperJava::new(&mut cursor);
let tag_id = helper
.get_u8()
.map_err(|e| ReadingError::Message(e.to_string()))?;
if tag_id == pumpkin_nbt::END_ID {
return Ok(None);
}
let _name = helper
.get_string()
.map_err(|e| ReadingError::Message(e.to_string()))?;
let tag = if tag_id == pumpkin_nbt::COMPOUND_ID {
NbtTag::Compound(
NbtCompound::deserialize_content(&mut helper)
.map_err(|e| ReadingError::Message(e.to_string()))?,
)
} else {
NbtTag::deserialize_data(&mut helper, tag_id)
.map_err(|e| ReadingError::Message(e.to_string()))?
};
Ok(Some(tag))
}
}
#[inline]
fn get_compound_nbt_with_version(
&mut self,
version: &JavaMinecraftVersion,
) -> Result<Option<NbtCompound>, ReadingError> {
match self.get_nbt_with_version(version)? {
Some(NbtTag::Compound(comp)) => Ok(Some(comp)),
Some(NbtTag::End) | None => Ok(None),
Some(other) => Err(ReadingError::Message(format!(
"Expected NBT compound, found tag ID {}",
other.get_type_id()
))),
}
}
}
pub trait NetworkReadSliceExt<'a> {
@ -178,6 +322,39 @@ pub trait NetworkReadSliceExt<'a> {
fn read_slice_borrowed(&mut self, count: usize) -> Result<&'a [u8], ReadingError>;
fn read_remaining_slice_borrowed(&mut self, bound: usize) -> Result<&'a [u8], ReadingError>;
fn get_nbt_borrowed(
&mut self,
version: &JavaMinecraftVersion,
) -> Result<Option<NbtTag>, ReadingError>;
#[inline]
fn get_nbt(&mut self, version: &JavaMinecraftVersion) -> Result<Option<NbtTag>, ReadingError> {
self.get_nbt_borrowed(version)
}
#[inline]
fn get_compound_nbt_borrowed(
&mut self,
version: &JavaMinecraftVersion,
) -> Result<Option<NbtCompound>, ReadingError> {
match self.get_nbt_borrowed(version)? {
Some(NbtTag::Compound(comp)) => Ok(Some(comp)),
Some(NbtTag::End) | None => Ok(None),
Some(other) => Err(ReadingError::Message(format!(
"Expected NBT compound, found tag ID {}",
other.get_type_id()
))),
}
}
#[inline]
fn get_compound_nbt(
&mut self,
version: &JavaMinecraftVersion,
) -> Result<Option<NbtCompound>, ReadingError> {
self.get_compound_nbt_borrowed(version)
}
#[inline]
fn read_cow_slice_borrowed(&mut self, count: usize) -> Result<Cow<'a, [u8]>, ReadingError> {
Ok(Cow::Borrowed(self.read_slice_borrowed(count)?))
@ -284,6 +461,87 @@ impl<'a> NetworkReadSliceExt<'a> for &'a [u8] {
})
}
}
fn get_nbt_borrowed(
&mut self,
version: &JavaMinecraftVersion,
) -> Result<Option<NbtTag>, ReadingError> {
if *version >= JavaMinecraftVersion::V_1_8 {
if self.is_empty() {
return Ok(None);
}
if (*self)[0] == pumpkin_nbt::END_ID {
*self = &(*self)[1..];
return Ok(None);
}
let mut cursor = std::io::Cursor::new(*self);
let mut helper = pumpkin_nbt::deserializer::NbtReadHelperJava::new(&mut cursor);
let tag_id = helper
.get_u8()
.map_err(|e| ReadingError::Message(e.to_string()))?;
if tag_id == pumpkin_nbt::END_ID {
let pos = cursor.position() as usize;
*self = &(*self)[pos..];
return Ok(None);
}
if *version < JavaMinecraftVersion::V_1_20_2 {
let _name = helper
.get_string()
.map_err(|e| ReadingError::Message(e.to_string()))?;
}
let tag = if tag_id == pumpkin_nbt::COMPOUND_ID {
NbtTag::Compound(
NbtCompound::deserialize_content(&mut helper)
.map_err(|e| ReadingError::Message(e.to_string()))?,
)
} else {
NbtTag::deserialize_data(&mut helper, tag_id)
.map_err(|e| ReadingError::Message(e.to_string()))?
};
let pos = cursor.position() as usize;
*self = &(*self)[pos..];
Ok(Some(tag))
} else {
let length = self.get_i16_be()?;
if length <= 0 {
return Ok(None);
}
let length = length as usize;
if self.len() < length {
return Err(ReadingError::Incomplete(
"Not enough bytes for compressed NBT".into(),
));
}
let compressed = &(*self)[..length];
*self = &(*self)[length..];
let mut decoder = flate2::read::GzDecoder::new(compressed);
let mut decompressed = Vec::new();
decoder
.read_to_end(&mut decompressed)
.map_err(|e| ReadingError::Message(e.to_string()))?;
let mut cursor = std::io::Cursor::new(decompressed);
let mut helper = pumpkin_nbt::deserializer::NbtReadHelperJava::new(&mut cursor);
let tag_id = helper
.get_u8()
.map_err(|e| ReadingError::Message(e.to_string()))?;
if tag_id == pumpkin_nbt::END_ID {
return Ok(None);
}
let _name = helper
.get_string()
.map_err(|e| ReadingError::Message(e.to_string()))?;
let tag = if tag_id == pumpkin_nbt::COMPOUND_ID {
NbtTag::Compound(
NbtCompound::deserialize_content(&mut helper)
.map_err(|e| ReadingError::Message(e.to_string()))?,
)
} else {
NbtTag::deserialize_data(&mut helper, tag_id)
.map_err(|e| ReadingError::Message(e.to_string()))?
};
Ok(Some(tag))
}
}
}
impl<'a, R: NetworkReadSliceExt<'a> + ?Sized> NetworkReadSliceExt<'a> for &mut R {
@ -310,6 +568,13 @@ impl<'a, R: NetworkReadSliceExt<'a> + ?Sized> NetworkReadSliceExt<'a> for &mut R
fn read_remaining_slice_borrowed(&mut self, bound: usize) -> Result<&'a [u8], ReadingError> {
(**self).read_remaining_slice_borrowed(bound)
}
#[inline]
fn get_nbt_borrowed(
&mut self,
version: &JavaMinecraftVersion,
) -> Result<Option<NbtTag>, ReadingError> {
(**self).get_nbt_borrowed(version)
}
}
macro_rules! get_number_be {
@ -434,10 +699,62 @@ impl<R: Read> NetworkReadExt for R {
}
}
fn nbt_tag_to_json(tag: &NbtTag) -> serde_json::Value {
#[must_use]
pub fn json_to_nbt_tag(value: &serde_json::Value) -> NbtTag {
match value {
serde_json::Value::Null => NbtTag::Compound(NbtCompound::new()),
serde_json::Value::Bool(b) => NbtTag::Byte(i8::from(*b)),
serde_json::Value::Number(num) => num.as_i64().map_or_else(
|| num.as_f64().map_or(NbtTag::Int(0), NbtTag::Double),
|i| {
i8::try_from(i).map_or_else(
|_| {
i16::try_from(i).map_or_else(
|_| i32::try_from(i).map_or(NbtTag::Long(i), NbtTag::Int),
NbtTag::Short,
)
},
NbtTag::Byte,
)
},
),
serde_json::Value::String(s) => NbtTag::String(s.clone().into_boxed_str()),
serde_json::Value::Array(arr) => {
let list: Vec<NbtTag> = arr.iter().map(json_to_nbt_tag).collect();
NbtTag::List(list)
}
serde_json::Value::Object(obj) => {
let mut compound = NbtCompound::new();
for (k, v) in obj {
compound.put(k, json_to_nbt_tag(v));
}
NbtTag::Compound(compound)
}
}
}
#[must_use]
pub fn nbt_tag_to_json(tag: &NbtTag) -> serde_json::Value {
nbt_tag_to_json_ext(tag, false)
}
#[must_use]
pub fn nbt_tag_to_json_ext(tag: &NbtTag, parse_byte_as_bool: bool) -> serde_json::Value {
match tag {
NbtTag::End => serde_json::Value::Null,
NbtTag::Byte(b) => serde_json::Value::Number((*b).into()),
NbtTag::Byte(b) => {
if parse_byte_as_bool {
if *b == 0 {
serde_json::Value::Bool(false)
} else if *b == 1 {
serde_json::Value::Bool(true)
} else {
serde_json::Value::Number((*b).into())
}
} else {
serde_json::Value::Number((*b).into())
}
}
NbtTag::Short(s) => serde_json::Value::Number((*s).into()),
NbtTag::Int(i) => serde_json::Value::Number((*i).into()),
NbtTag::Long(l) => serde_json::Value::Number((*l).into()),
@ -452,11 +769,15 @@ fn nbt_tag_to_json(tag: &NbtTag) -> serde_json::Value {
.collect(),
),
NbtTag::String(s) => serde_json::Value::String(s.to_string()),
NbtTag::List(list) => serde_json::Value::Array(list.iter().map(nbt_tag_to_json).collect()),
NbtTag::List(list) => serde_json::Value::Array(
list.iter()
.map(|t| nbt_tag_to_json_ext(t, parse_byte_as_bool))
.collect(),
),
NbtTag::Compound(compound) => {
let mut map = serde_json::Map::new();
for (k, v) in &compound.child_tags {
map.insert(k.to_string(), nbt_tag_to_json(v));
map.insert(k.to_string(), nbt_tag_to_json_ext(v, parse_byte_as_bool));
}
serde_json::Value::Object(map)
}
@ -474,8 +795,124 @@ fn nbt_tag_to_json(tag: &NbtTag) -> serde_json::Value {
}
}
pub fn write_nbt_payload(
mut write: impl Write,
nbt_data: &[u8],
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
if *version >= JavaMinecraftVersion::V_1_8 {
if nbt_data.is_empty() || nbt_data == [0] {
write.write_u8(0)?;
} else if *version < JavaMinecraftVersion::V_1_20_2 {
if nbt_data.len() >= 3 && nbt_data[0] == 0x0A && nbt_data[1] == 0 && nbt_data[2] == 0 {
write.write_all(nbt_data).map_err(WritingError::IoError)?;
} else if nbt_data[0] == 0x0A {
write.write_u8(0x0A)?;
write.write_u16_be(0)?;
write
.write_all(&nbt_data[1..])
.map_err(WritingError::IoError)?;
} else {
write.write_all(nbt_data).map_err(WritingError::IoError)?;
}
} else {
write.write_all(nbt_data).map_err(WritingError::IoError)?;
}
} else {
if nbt_data.is_empty() || nbt_data == [0] {
write.write_i16_be(-1)?;
} else {
let mut named_bytes = Vec::with_capacity(nbt_data.len() + 2);
if nbt_data.len() >= 3 && nbt_data[0] == 0x0A && nbt_data[1] == 0 && nbt_data[2] == 0 {
named_bytes.extend_from_slice(nbt_data);
} else if nbt_data[0] == 0x0A {
named_bytes.push(0x0A);
named_bytes.extend_from_slice(&[0x00, 0x00]);
named_bytes.extend_from_slice(&nbt_data[1..]);
} else {
named_bytes.extend_from_slice(nbt_data);
}
let mut encoder =
flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default());
encoder
.write_all(&named_bytes)
.map_err(WritingError::IoError)?;
let compressed = encoder.finish().map_err(WritingError::IoError)?;
write.write_i16_be(compressed.len() as i16)?;
write
.write_all(&compressed)
.map_err(WritingError::IoError)?;
}
}
Ok(())
}
pub fn read_nbt_payload(
bytebuf: &mut &[u8],
version: &JavaMinecraftVersion,
) -> Result<Box<[u8]>, ReadingError> {
if *version >= JavaMinecraftVersion::V_1_8 {
if bytebuf.is_empty() || bytebuf[0] == 0 {
if !bytebuf.is_empty() {
let _ = bytebuf.get_u8()?;
}
Ok(Box::new([]))
} else if *version < JavaMinecraftVersion::V_1_20_2 {
let all = bytebuf.to_vec();
*bytebuf = &[];
if all.len() >= 3 && all[0] == 0x0A && all[1] == 0 && all[2] == 0 {
let mut unnamed = Vec::with_capacity(all.len() - 2);
unnamed.push(0x0A);
unnamed.extend_from_slice(&all[3..]);
Ok(unnamed.into_boxed_slice())
} else {
Ok(all.into_boxed_slice())
}
} else {
let all = bytebuf.to_vec().into_boxed_slice();
*bytebuf = &[];
Ok(all)
}
} else {
let length = bytebuf.get_i16_be()?;
if length <= 0 {
Ok(Box::new([]))
} else {
if bytebuf.len() < length as usize {
return Err(ReadingError::Incomplete(
"Not enough bytes for compressed NBT".into(),
));
}
let compressed = &bytebuf[..length as usize];
*bytebuf = &bytebuf[length as usize..];
let mut decoder = flate2::read::GzDecoder::new(compressed);
let mut decompressed = Vec::new();
decoder
.read_to_end(&mut decompressed)
.map_err(|e| ReadingError::Message(e.to_string()))?;
if decompressed.len() >= 3
&& decompressed[0] == 0x0A
&& decompressed[1] == 0
&& decompressed[2] == 0
{
let mut unnamed = Vec::with_capacity(decompressed.len() - 2);
unnamed.push(0x0A);
unnamed.extend_from_slice(&decompressed[3..]);
Ok(unnamed.into_boxed_slice())
} else {
Ok(decompressed.into_boxed_slice())
}
}
}
}
#[inline]
pub fn read_remaining_bytes(read: &mut impl Read, bound: usize) -> Result<Box<[u8]>, ReadingError> {
pub fn read_remaining_bytes(
read: &mut (impl Read + ?Sized),
bound: usize,
) -> Result<Box<[u8]>, ReadingError> {
let mut return_buf = Vec::with_capacity(bound.min(1024));
// Take one extra byte to check for exceeding bound
@ -623,8 +1060,26 @@ pub trait NetworkWriteExt {
Ok(())
}
fn write_nbt_with_version(
&mut self,
data: Option<&NbtTag>,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError>;
fn write_nbt(&mut self, data: NbtTag) -> Result<(), WritingError>;
#[inline]
fn write_compound_nbt_with_version(
&mut self,
data: Option<&NbtCompound>,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
let tag = data.map(|c| NbtTag::Compound(c.clone()));
self.write_nbt_with_version(tag.as_ref(), version)
}
#[inline]
fn write_nbt(&mut self, data: NbtTag) -> Result<(), WritingError> {
self.write_nbt_with_version(Some(&data), &JavaMinecraftVersion::V_26_2)
}
}
macro_rules! write_number_be {
@ -755,11 +1210,55 @@ impl<W: Write> NetworkWriteExt for W {
Ok(())
}
fn write_nbt(&mut self, data: NbtTag) -> Result<(), WritingError> {
let mut write_adaptor = NbtWriteHelperJava::new(self);
data.serialize(&mut write_adaptor)
.map_err(|e| WritingError::Message(e.to_string()))?;
fn write_nbt_with_version(
&mut self,
data: Option<&NbtTag>,
version: &JavaMinecraftVersion,
) -> Result<(), WritingError> {
if *version >= JavaMinecraftVersion::V_1_8 {
if let Some(tag) = data
&& !matches!(tag, NbtTag::End)
{
if *version < JavaMinecraftVersion::V_1_20_2 {
self.write_u8(tag.get_type_id())?;
self.write_u16_be(0)?; // empty root name
let mut write_adaptor = NbtWriteHelperJava::new(self);
tag.clone()
.serialize_data(&mut write_adaptor)
.map_err(|e| WritingError::Message(e.to_string()))?;
} else {
let mut write_adaptor = NbtWriteHelperJava::new(self);
tag.clone()
.serialize(&mut write_adaptor)
.map_err(|e| WritingError::Message(e.to_string()))?;
}
} else {
self.write_u8(pumpkin_nbt::END_ID)?;
}
} else {
// <= 1.7.10
if let Some(tag) = data
&& !matches!(tag, NbtTag::End)
{
let mut buf = Vec::new();
buf.push(tag.get_type_id());
buf.extend_from_slice(&[0x00, 0x00]); // empty root name
let mut write_adaptor = NbtWriteHelperJava::new(&mut buf);
tag.clone()
.serialize_data(&mut write_adaptor)
.map_err(|e| WritingError::Message(e.to_string()))?;
let mut encoder =
flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default());
encoder.write_all(&buf).map_err(WritingError::IoError)?;
let compressed = encoder.finish().map_err(WritingError::IoError)?;
self.write_i16_be(compressed.len() as i16)?;
self.write_slice(&compressed)?;
} else {
self.write_i16_be(-1)?;
}
}
Ok(())
}
}

View File

@ -810,12 +810,22 @@ vector_codec_impl!(Vector3<T>, 3, x, y, z);
pub const fn packed_chunk_pos(vec: &Vector3<i32>) -> i64 {
let mut result = 0i64;
// NOTE: Need to go to i64 first to conserve a sign.
result |= (vec.x as i64 & 0x03FF_FFFF) << 42;
result |= (vec.x as i64 & 0x003F_FFFF) << 42;
result |= (vec.z as i64 & 0x003F_FFFF) << 20;
result |= vec.y as i64 & 0xFFFFF;
result
}
/// Unpacks a 64-bit integer into a chunk section position vector.
#[inline]
#[must_use]
pub const fn unpacked_chunk_pos(packed: i64) -> Vector3<i32> {
let x = (packed >> 42) as i32;
let y = ((packed << 44) >> 44) as i32;
let z = ((packed << 22) >> 42) as i32;
Vector3::new(x, y, z)
}
/// Packs a local position within a chunk into a single 16-bit integer.
///
/// The packing format is:

View File

@ -28,6 +28,7 @@ use super::features::{
end_gateway::EndGatewayFeature,
end_island::EndIslandFeature,
end_platform::EndPlatformFeature,
end_podium::EndPodiumFeature,
end_spike::EndSpikeFeature,
fallen_tree::FallenTreeFeature,
fill_layer::FillLayerFeature,
@ -125,6 +126,7 @@ pub enum ConfiguredFeature {
Lake(LakeFeature),
Ore(OreFeature),
EndPlatform(EndPlatformFeature),
EndPodium(EndPodiumFeature),
EndSpike(EndSpikeFeature),
EndIsland(EndIslandFeature),
EndGateway(EndGatewayFeature),
@ -240,6 +242,7 @@ impl ConfiguredFeature {
random,
pos,
),
Self::EndPodium(feature) => feature.generate(chunk, pos),
Self::EndSpike(feature) => feature.generate(
chunk,
block_registry,
@ -424,9 +427,7 @@ impl ConfiguredFeature {
}
Self::DripstoneCluster(feature) => feature.generate(chunk, pos),
Self::LargeDripstone(feature) => feature.generate(chunk, random, pos),
Self::EndGateway(_feature) => {
EndGatewayFeature::generate(chunk, min_y, height, feature_name, random, pos)
}
Self::EndGateway(feature) => feature.generate(chunk, pos),
Self::FillLayer(feature) => {
feature.generate(chunk, min_y, height, feature_name, random, pos)
}

View File

@ -1,30 +1,65 @@
use pumpkin_data::Block;
use pumpkin_util::{math::position::BlockPos, random::RandomGenerator};
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
use crate::generation::proto_chunk::GenerationCache;
pub struct EndGatewayFeature;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct EndGatewayFeature {
pub exit: Option<BlockPos>,
pub exact: bool,
}
impl EndGatewayFeature {
pub fn generate<T: GenerationCache>(
chunk: &mut T,
_min_y: i8,
_height: u16,
_feature: pumpkin_data::placed_feature::PlacedFeature,
_random: &mut RandomGenerator,
pos: BlockPos,
) -> bool {
for dx in -1..=1 {
for dy in -1..=1 {
for dz in -1..=1 {
let target = BlockPos::new(pos.0.x + dx, pos.0.y + dy, pos.0.z + dz);
let is_center = dx == 0 && dy == 0 && dz == 0;
let is_corner = dx.abs() + dy.abs() + dz.abs() == 3;
#[must_use]
pub const fn known_exit(exit: BlockPos, exact: bool) -> Self {
Self {
exit: Some(exit),
exact,
}
}
if is_center {
chunk.set_block_state(&target.0, Block::END_GATEWAY.default_state);
} else if !is_corner {
chunk.set_block_state(&target.0, Block::BEDROCK.default_state);
#[must_use]
pub const fn delayed_exit_search() -> Self {
Self {
exit: None,
exact: false,
}
}
pub fn generate<T: GenerationCache>(&self, chunk: &mut T, pos: BlockPos) -> bool {
for dx in -1i32..=1 {
for dy in -2i32..=2 {
for dz in -1i32..=1 {
let same_x = dx == 0;
let same_y = dy == 0;
let same_z = dz == 0;
let end = dy.abs() == 2;
let target = Vector3::new(pos.0.x + dx, pos.0.y + dy, pos.0.z + dz);
if same_x && same_y && same_z {
chunk.set_block_state(&target, Block::END_GATEWAY.default_state);
if let Some(exit) = self.exit {
let mut entity_nbt = NbtCompound::new();
entity_nbt.put_string("id", "minecraft:end_gateway".to_string());
entity_nbt.put_int("x", target.x);
entity_nbt.put_int("y", target.y);
entity_nbt.put_int("z", target.z);
entity_nbt.put_long("Age", 0);
entity_nbt.put_bool("ExactTeleport", self.exact);
let mut exit_nbt = NbtCompound::new();
exit_nbt.put_int("X", exit.0.x);
exit_nbt.put_int("Y", exit.0.y);
exit_nbt.put_int("Z", exit.0.z);
entity_nbt.put_compound("ExitPortal", exit_nbt);
chunk.add_block_entity(&target, entity_nbt);
}
} else if same_y {
chunk.set_block_state(&target, Block::AIR.default_state);
} else if (end && same_x && same_z) || ((same_x || same_z) && !end) {
chunk.set_block_state(&target, Block::BEDROCK.default_state);
} else {
chunk.set_block_state(&target, Block::AIR.default_state);
}
}
}

View File

@ -0,0 +1,122 @@
use pumpkin_data::{
Block,
block_properties::{BlockProperties, HorizontalFacing, WallTorchLikeProperties},
};
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
use crate::generation::proto_chunk::GenerationCache;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct EndPodiumFeature {
pub active: bool,
}
impl EndPodiumFeature {
pub const PODIUM_RADIUS: i32 = 4;
pub const PODIUM_PILLAR_HEIGHT: i32 = 4;
pub const RIM_RADIUS: i32 = 1;
pub const CORNER_ROUNDING: f32 = 0.5;
pub const END_PODIUM_LOCATION: BlockPos = BlockPos::new(0, 0, 0);
#[must_use]
pub const fn new(active: bool) -> Self {
Self { active }
}
#[must_use]
pub const fn get_location(offset: BlockPos) -> BlockPos {
BlockPos::new(
Self::END_PODIUM_LOCATION.0.x + offset.0.x,
Self::END_PODIUM_LOCATION.0.y + offset.0.y,
Self::END_PODIUM_LOCATION.0.z + offset.0.z,
)
}
pub fn generate<T: GenerationCache>(&self, chunk: &mut T, origin: BlockPos) -> bool {
let chunk_x = chunk.get_center_chunk().x;
let chunk_z = chunk.get_center_chunk().z;
let min_x = chunk_x * 16;
let max_x = min_x + 15;
let min_z = chunk_z * 16;
let max_z = min_z + 15;
let ox = origin.0.x;
let mut oy = origin.0.y;
let oz = origin.0.z;
// Podium spans [ox - 4, ox + 4] and [oz - 4, oz + 4]
if ox + 4 < min_x || ox - 4 > max_x || oz + 4 < min_z || oz - 4 > max_z {
return false;
}
if oy < 50 {
oy = 65;
}
let in_chunk =
|x: i32, z: i32| -> bool { x >= min_x && x <= max_x && z >= min_z && z <= max_z };
for y in (oy - 1)..=(oy + 32) {
for x in (ox - 4)..=(ox + 4) {
for z in (oz - 4)..=(oz + 4) {
if !in_chunk(x, z) {
continue;
}
let dx = (x - ox) as f64;
let dy = (y - oy) as f64;
let dz = (z - oz) as f64;
let dist_sq = dx * dx + dy * dy + dz * dz;
let closer_than_2_5 = dist_sq < 2.5 * 2.5;
let closer_than_3_5 = dist_sq < 3.5 * 3.5;
if closer_than_2_5 || closer_than_3_5 {
let target = Vector3::new(x, y, z);
if y < oy {
if closer_than_2_5 {
chunk.set_block_state(&target, Block::BEDROCK.default_state);
} else if self.active {
chunk.set_block_state(&target, Block::END_STONE.default_state);
}
} else if y > oy {
chunk.set_block_state(&target, Block::AIR.default_state);
} else if !closer_than_2_5 {
chunk.set_block_state(&target, Block::BEDROCK.default_state);
} else if self.active {
chunk.set_block_state(&target, Block::END_PORTAL.default_state);
} else {
chunk.set_block_state(&target, Block::AIR.default_state);
}
}
}
}
}
if in_chunk(ox, oz) {
for y in 0..4 {
let target = Vector3::new(ox, oy + y, oz);
chunk.set_block_state(&target, Block::BEDROCK.default_state);
}
}
let center_of_pillar_y = oy + 2;
for (dx, dz, facing) in [
(0i32, -1i32, HorizontalFacing::North),
(0, 1, HorizontalFacing::South),
(-1, 0, HorizontalFacing::West),
(1, 0, HorizontalFacing::East),
] {
let tx = ox + dx;
let tz = oz + dz;
if in_chunk(tx, tz) {
let props = WallTorchLikeProperties { facing };
let state = props.to_state_id(&Block::WALL_TORCH);
let target = Vector3::new(tx, center_of_pillar_y, tz);
chunk.set_block_state(&target, pumpkin_data::BlockState::from_id(state));
}
}
true
}
}

View File

@ -2,10 +2,7 @@ use pumpkin_data::{
Block, BlockState,
block_properties::{BlockProperties, OakFenceLikeProperties},
};
use pumpkin_util::{
math::position::BlockPos,
random::{RandomGenerator, RandomImpl},
};
use pumpkin_util::{math::position::BlockPos, random::RandomGenerator};
use crate::generation::proto_chunk::GenerationCache;
use crate::{generation::section_coords, world::WorldPortalExt};
@ -15,7 +12,7 @@ pub struct EndSpikeFeature {
pub spikes: Vec<Spike>,
}
#[derive(Clone)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Spike {
pub center_x: i32,
pub center_z: i32,
@ -25,14 +22,113 @@ pub struct Spike {
}
impl Spike {
#[must_use]
pub const fn is_in_chunk(&self, pos: &BlockPos) -> bool {
section_coords::block_to_section(pos.0.x) == section_coords::block_to_section(self.center_x)
&& section_coords::block_to_section(pos.0.z)
== section_coords::block_to_section(self.center_z)
}
#[must_use]
pub const fn is_center_within_chunk(&self, chunk_origin: &BlockPos) -> bool {
section_coords::block_to_section(chunk_origin.0.x)
== section_coords::block_to_section(self.center_x)
&& section_coords::block_to_section(chunk_origin.0.z)
== section_coords::block_to_section(self.center_z)
}
#[must_use]
pub const fn top_bounding_box(&self) -> (f64, f64, f64, f64, f64, f64) {
(
(self.center_x - self.radius) as f64,
0.0,
(self.center_z - self.radius) as f64,
(self.center_x + self.radius) as f64 + 1.0,
256.0,
(self.center_z + self.radius) as f64 + 1.0,
)
}
}
pub struct JavaRandom {
seed: u64,
}
impl JavaRandom {
#[must_use]
pub const fn new(seed: u64) -> Self {
Self {
seed: (seed ^ 0x5DEECE66D) & ((1u64 << 48) - 1),
}
}
pub const fn next(&mut self, bits: u32) -> i32 {
self.seed = (self.seed.wrapping_mul(0x5DEECE66D).wrapping_add(0xB)) & ((1u64 << 48) - 1);
(self.seed >> (48 - bits)) as i32
}
pub const fn next_i32(&mut self, bound: i32) -> i32 {
if bound <= 0 {
return 0;
}
if (bound & -bound) == bound {
return ((bound as i64 * self.next(31) as i64) >> 31) as i32;
}
let mut bits = self.next(31);
let mut val = bits % bound;
while bits - val + (bound - 1) < 0 {
bits = self.next(31);
val = bits % bound;
}
val
}
pub const fn next_i64(&mut self) -> i64 {
((self.next(32) as i64) << 32) + self.next(32) as i64
}
}
impl EndSpikeFeature {
#[must_use]
pub fn get_spikes_for_seed(seed: u64) -> [Spike; 10] {
let mut random = JavaRandom::new(seed);
let key = (random.next_i64() & 65535) as u64;
let mut key_random = JavaRandom::new(key);
let mut sizes: [i32; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for i in (1..10usize).rev() {
let j = key_random.next_i32(i as i32 + 1) as usize;
sizes.swap(i, j);
}
let mut spikes = [Spike {
center_x: 0,
center_z: 0,
radius: 0,
height: 0,
guarded: false,
}; 10];
for i in 0..10 {
let angle = 2.0 * (-std::f64::consts::PI + (std::f64::consts::PI / 10.0) * i as f64);
let center_x = (42.0 * angle.cos()).floor() as i32;
let center_z = (42.0 * angle.sin()).floor() as i32;
let size = sizes[i];
let radius = 2 + size / 3;
let height = 76 + size * 3;
let guarded = size == 1 || size == 2;
spikes[i] = Spike {
center_x,
center_z,
radius,
height,
guarded,
};
}
spikes
}
#[expect(clippy::too_many_arguments)]
pub fn generate<T: GenerationCache>(
&self,
@ -40,38 +136,18 @@ impl EndSpikeFeature {
_block_registry: &dyn WorldPortalExt,
_min_y: i8,
_height: u16,
_feature: pumpkin_data::placed_feature::PlacedFeature, // This placed feature
random: &mut RandomGenerator,
_feature: pumpkin_data::placed_feature::PlacedFeature,
_random: &mut RandomGenerator,
pos: BlockPos,
) -> bool {
let mut spikes = self.spikes.clone();
if spikes.is_empty() {
let mut sizes: Vec<i32> = (0..10).collect();
for i in (1..10usize).rev() {
let j = random.next_bounded_i32(i as i32 + 1) as usize;
sizes.swap(i, j);
}
let spikes = if self.spikes.is_empty() {
Self::get_spikes_for_seed(0).to_vec()
} else {
self.spikes.clone()
};
for (i, &l) in sizes.iter().enumerate() {
let angle = 2.0 * (-std::f64::consts::PI + 0.3141592653589793 * i as f64);
let center_x = (42.0 * angle.cos()).floor() as i32;
let center_z = (42.0 * angle.sin()).floor() as i32;
let radius = 2 + l / 3;
let height = 76 + l * 3;
let guarded = l == 1 || l == 2;
spikes.push(Spike {
center_x,
center_z,
radius,
height,
guarded,
});
}
}
for spike in spikes {
if !spike.is_in_chunk(&pos) {
if !spike.is_center_within_chunk(&pos) {
continue;
}
Self::gen_spike(&spike, chunk);

View File

@ -14,6 +14,7 @@ pub mod drip_stone;
pub mod end_gateway;
pub mod end_island;
pub mod end_platform;
pub mod end_podium;
pub mod end_spike;
pub mod fallen_tree;
pub mod fill_layer;

View File

@ -56,6 +56,7 @@ impl AcaciaFoliagePlacer {
foliage_positions
}
#[must_use]
pub const fn get_random_height() -> i32 {
0
}

View File

@ -42,6 +42,7 @@ impl BlobFoliagePlacer {
foliage_positions
}
#[must_use]
pub const fn get_random_height(&self) -> i32 {
self.height
}

View File

@ -42,6 +42,7 @@ impl BushFoliagePlacer {
foliage_positions
}
#[must_use]
pub const fn get_random_height(&self) -> i32 {
self.height
}

View File

@ -88,6 +88,7 @@ impl DarkOakFoliagePlacer {
foliage_positions
}
#[must_use]
pub const fn get_random_height() -> i32 {
4
}

View File

@ -41,6 +41,7 @@ impl LargeOakFoliagePlacer {
foliage_positions
}
#[must_use]
pub const fn get_random_height(&self) -> i32 {
self.height
}

View File

@ -46,6 +46,7 @@ impl JungleFoliagePlacer {
}
foliage_positions
}
#[must_use]
pub const fn get_random_height(&self) -> i32 {
self.height
}

View File

@ -182,14 +182,17 @@ impl TreeFeature {
}
}
#[must_use]
pub fn can_replace_or_log(state: &BlockState, id: BlockId) -> bool {
Self::can_replace(state, id) || id.has_tag(tag::Block::MINECRAFT_LOGS)
}
#[must_use]
pub fn is_air_or_leaves(state: &BlockState, id: BlockId) -> bool {
state.is_air() || id.has_tag(tag::Block::MINECRAFT_LEAVES)
}
#[must_use]
pub fn can_replace(state: &BlockState, id: BlockId) -> bool {
state.is_air() || id.has_tag(tag::Block::MINECRAFT_REPLACEABLE_BY_TREES)
}

View File

@ -258,6 +258,7 @@ pub struct BranchPosition {
}
impl BranchPosition {
#[must_use]
pub const fn new(pos: BlockPos, end_y: i32) -> Self {
Self {
node: TreeNode {
@ -269,6 +270,7 @@ impl BranchPosition {
}
}
#[must_use]
pub const fn get_end_y(&self) -> i32 {
self.end_y
}

View File

@ -5,5 +5,5 @@ pub mod configured_features;
// feature.
pub mod placed_features;
mod features;
pub mod features;
mod size;

View File

@ -628,6 +628,7 @@ impl Level {
return res;
}
let chunk = self.fetch_chunk(pos).await;
self.loaded_chunks.insert(pos, chunk.clone());
f(&chunk)
}

View File

@ -150,10 +150,10 @@ impl BlockBehaviour for BedBlock {
let is_creative = args.player.gamemode.load() == GameMode::Creative;
let flags = if bed_props.part == BedPart::Foot && !is_creative {
// Breaking foot in survival -> allow head to drop
BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::NOTIFY_ALL
} else {
// Breaking head OR creative mode -> skip drops
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL
};
args.world
@ -165,15 +165,6 @@ impl BlockBehaviour for BedBlock {
return;
}
// If the block is being replaced with air (i.e., broken), the `broken` callback
// will handle breaking the other half with the correct drop flags. Only handle it here
// if the block is being replaced with something else (e.g., piston movement).
let new_state_id = args.world.get_block_state_id(args.position);
let new_block = Block::from_state_id(new_state_id);
if new_block == &Block::AIR {
return;
}
let bed_props = BedProperties::from_state_id(args.old_state_id, args.block);
let other_half_pos = if bed_props.part == BedPart::Head {
args.position
@ -189,7 +180,7 @@ impl BlockBehaviour for BedBlock {
args.world.break_block(
&other_half_pos,
None,
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS,
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL,
);
}
}

View File

@ -267,12 +267,17 @@ impl BlockBehaviour for DoorBlock {
DoubleBlockHalf::Lower => args.position.up(),
};
let neighbor_state_id = args.world.get_block_state_id(&other_half_pos);
if neighbor_state_id.to_block_id() != args.block.id {
let (other_block, other_state) = args.world.get_block_and_state(&other_half_pos);
if other_block.id != args.block.id {
args.world.update_neighbors(&other_half_pos, None);
return; // Neighbor is already gone or is a different block
}
let other_props = DoorProperties::from_state_id(other_state.id, other_block);
if other_props.half == door_props.half {
return;
}
let is_creative = args.player.gamemode.load() == GameMode::Creative;
let flags = if door_props.half == DoubleBlockHalf::Upper && !is_creative {
BlockFlags::NOTIFY_ALL
@ -285,56 +290,57 @@ impl BlockBehaviour for DoorBlock {
}
fn on_neighbor_update(&self, args: OnNeighborUpdateArgs<'_>) {
{
let block_state = args.world.get_block_state(args.position);
let mut door_props = DoorProperties::from_state_id(block_state.id, args.block);
let other_half = match door_props.half {
DoubleBlockHalf::Upper => BlockDirection::Down,
DoubleBlockHalf::Lower => BlockDirection::Up,
let block_state = args.world.get_block_state(args.position);
let mut door_props = DoorProperties::from_state_id(block_state.id, args.block);
let other_half = match door_props.half {
DoubleBlockHalf::Upper => BlockDirection::Down,
DoubleBlockHalf::Lower => BlockDirection::Up,
};
let other_pos = args.position.offset(other_half.to_offset());
let (other_block, other_state_id) = args.world.get_block_and_state_id(&other_pos);
if other_block.id != args.block.id {
return;
}
let powered = block_receives_redstone_power(args.world, args.position)
|| block_receives_redstone_power(args.world, &other_pos);
if door_props.powered != powered {
let sound_half = if door_props.open {
DoubleBlockHalf::Lower
} else {
DoubleBlockHalf::Upper
};
let other_pos = args.position.offset(other_half.to_offset());
let (other_block, other_state_id) = args.world.get_block_and_state_id(&other_pos);
let powered = block_receives_redstone_power(args.world, args.position)
|| block_receives_redstone_power(args.world, &other_pos);
let mut other_door_props = DoorProperties::from_state_id(other_state_id, other_block);
if door_props.powered != powered {
let sound_half = if door_props.open {
DoubleBlockHalf::Lower
} else {
DoubleBlockHalf::Upper
};
door_props.powered = powered;
other_door_props.powered = powered;
let mut other_door_props =
DoorProperties::from_state_id(other_state_id, other_block);
if door_props.open != powered {
door_props.open = powered;
other_door_props.open = powered;
}
door_props.powered = powered;
other_door_props.powered = powered;
if door_props.open != powered {
door_props.open = powered;
other_door_props.open = powered;
}
if door_props.half == sound_half {
args.world.play_block_sound(
get_sound(args.block, powered),
SoundCategory::Blocks,
*args.position,
);
}
args.world.set_block_state(
args.position,
door_props.to_state_id(args.block),
BlockFlags::NOTIFY_ALL,
);
args.world.set_block_state(
&other_pos,
other_door_props.to_state_id(other_block),
BlockFlags::NOTIFY_ALL,
if door_props.half == sound_half {
args.world.play_block_sound(
get_sound(args.block, powered),
SoundCategory::Blocks,
*args.position,
);
}
args.world.set_block_state(
args.position,
door_props.to_state_id(args.block),
BlockFlags::NOTIFY_ALL,
);
args.world.set_block_state(
&other_pos,
other_door_props.to_state_id(other_block),
BlockFlags::NOTIFY_ALL,
);
}
}
@ -365,28 +371,26 @@ impl BlockBehaviour for DoorBlock {
}
fn on_state_replaced(&self, args: OnStateReplacedArgs<'_>) {
{
if args.moved {
return;
if args.moved {
return;
}
let door_props = DoorProperties::from_state_id(args.old_state_id, args.block);
let other_half_pos = match door_props.half {
DoubleBlockHalf::Upper => args.position.down(),
DoubleBlockHalf::Lower => args.position.up(),
};
let (other_block, other_state) = args.world.get_block_and_state(&other_half_pos);
if other_block.id == args.block.id {
let other_props = DoorProperties::from_state_id(other_state.id, other_block);
if other_props.half != door_props.half {
args.world.break_block(
&other_half_pos,
None,
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL,
);
}
let new_state_id = args.world.get_block_state_id(args.position);
let new_block = Block::from_state_id(new_state_id);
if new_block == &Block::AIR {
return;
}
let door_props = DoorProperties::from_state_id(args.old_state_id, args.block);
let other_half_pos = match door_props.half {
DoubleBlockHalf::Upper => args.position.down(),
DoubleBlockHalf::Lower => args.position.up(),
};
args.world.break_block(
&other_half_pos,
None,
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL,
);
}
}
}

View File

@ -0,0 +1,62 @@
use std::sync::Arc;
use pumpkin_macros::pumpkin_block;
use crate::block::entities::end_gateway::EndGatewayBlockEntity;
use crate::block::{BlockBehaviour, OnEntityCollisionArgs, OnSyncedBlockEventArgs, PlacedArgs};
#[pumpkin_block("minecraft:end_gateway")]
pub struct EndGatewayBlock;
impl BlockBehaviour for EndGatewayBlock {
fn on_entity_collision(&self, args: OnEntityCollisionArgs<'_>) {
let entity = args.entity.get_entity();
if entity
.portal_cooldown
.load(std::sync::atomic::Ordering::Relaxed)
> 0
{
return;
}
let Some(block_entity) = args.world.get_block_entity(args.position) else {
return;
};
let Some(end_gateway) = block_entity
.as_any()
.downcast_ref::<EndGatewayBlockEntity>()
else {
return;
};
if end_gateway.is_cooling_down() {
return;
}
end_gateway.trigger_cooldown(args.world, *args.position);
if let Some(destination) = end_gateway.get_portal_position(args.world, *args.position) {
let yaw = entity.yaw.load();
let pitch = entity.pitch.load();
args.entity
.teleport(destination, Some(yaw), Some(pitch), args.world.clone());
}
}
fn on_synced_block_event(&self, args: OnSyncedBlockEventArgs<'_>) -> bool {
if let Some(block_entity) = args.world.get_block_entity(args.position)
&& let Some(end_gateway) = block_entity
.as_any()
.downcast_ref::<EndGatewayBlockEntity>()
{
end_gateway.trigger_event(args.r#type, args.data)
} else {
args.r#type == EndGatewayBlockEntity::EVENT_COOLDOWN
}
}
fn placed(&self, args: PlacedArgs<'_>) {
let block_entity = EndGatewayBlockEntity::new(*args.position);
args.world.add_block_entity(Arc::new(block_entity));
}
}

View File

@ -21,11 +21,6 @@ impl BlockBehaviour for EndPortalBlock {
if Arc::ptr_eq(&target_world, args.world) {
return;
}
tracing::info!(
"End portal collision at {:?}, targeting world {:?}",
args.position,
target_world.dimension.minecraft_name
);
args.entity
.get_entity()
.try_use_portal(target_world, *args.position);

View File

@ -1,4 +1,5 @@
// Portals & dimension blocks
pub mod end_gateway;
pub mod end_portal;
pub mod end_portal_frame;
pub mod end_rod;

View File

@ -113,7 +113,9 @@ impl BlockBehaviour for TallPlantBlock {
args.world.break_block(
&other_block_pos,
None,
BlockFlags::SKIP_DROPS | BlockFlags::SKIP_BLOCK_ADDED_CALLBACK,
BlockFlags::SKIP_DROPS
| BlockFlags::SKIP_BLOCK_ADDED_CALLBACK
| BlockFlags::NOTIFY_ALL,
);
}
}

View File

@ -1,11 +1,20 @@
use super::BlockEntity;
use pumpkin_data::Block;
use pumpkin_nbt::compound::NbtCompound;
use pumpkin_util::math::position::BlockPos;
use std::sync::Mutex;
use pumpkin_util::math::vector2::Vector2;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::random::xoroshiro128::Xoroshiro;
use pumpkin_util::random::{RandomGenerator, RandomImpl};
use pumpkin_world::world::BlockFlags;
use std::sync::{Arc, Mutex};
use crate::world::World;
pub struct EndGatewayBlockEntity {
pub position: BlockPos,
pub age: Mutex<i64>,
pub teleport_cooldown: Mutex<i32>,
pub exact_teleport: Mutex<bool>,
pub exit_portal: Mutex<Option<BlockPos>>,
}
@ -25,16 +34,23 @@ impl BlockEntity for EndGatewayBlockEntity {
{
let age = nbt.get_long("Age").unwrap_or(0);
let exact_teleport = nbt.get_bool("ExactTeleport").unwrap_or(false);
let exit_portal = nbt.get_compound("ExitPortal").map(|c| {
BlockPos::new(
c.get_int("X").unwrap_or(0),
c.get_int("Y").unwrap_or(0),
c.get_int("Z").unwrap_or(0),
)
});
let exit_portal = nbt
.get_compound("ExitPortal")
.map(|c| {
BlockPos::new(
c.get_int("X").unwrap_or(0),
c.get_int("Y").unwrap_or(0),
c.get_int("Z").unwrap_or(0),
)
})
.or_else(|| {
nbt.get_int_array("exit_portal")
.and_then(|arr| (arr.len() == 3).then(|| BlockPos::new(arr[0], arr[1], arr[2])))
});
Self {
position,
age: Mutex::new(age),
teleport_cooldown: Mutex::new(0),
exact_teleport: Mutex::new(exact_teleport),
exit_portal: Mutex::new(exit_portal),
}
@ -44,8 +60,10 @@ impl BlockEntity for EndGatewayBlockEntity {
if let Ok(age) = self.age.lock() {
nbt.put_long("Age", *age);
}
if let Ok(exact_teleport) = self.exact_teleport.lock() {
nbt.put_bool("ExactTeleport", *exact_teleport);
if let Ok(exact_teleport) = self.exact_teleport.lock()
&& *exact_teleport
{
nbt.put_bool("ExactTeleport", true);
}
if let Ok(exit_portal) = self.exit_portal.lock()
&& let Some(exit) = exit_portal.as_ref()
@ -61,9 +79,13 @@ impl BlockEntity for EndGatewayBlockEntity {
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
let mut nbt = NbtCompound::new();
nbt.put_long("Age", *self.age.try_lock().ok()?);
nbt.put_bool("ExactTeleport", *self.exact_teleport.try_lock().ok()?);
if let Ok(exit) = self.exit_portal.try_lock()
&& let Some(ref exit) = *exit
if let Ok(exact_teleport) = self.exact_teleport.try_lock()
&& *exact_teleport
{
nbt.put_bool("ExactTeleport", true);
}
if let Ok(exit_portal) = self.exit_portal.try_lock()
&& let Some(ref exit) = *exit_portal
{
let mut exit_nbt = NbtCompound::new();
exit_nbt.put_int("X", exit.0.x);
@ -74,6 +96,20 @@ impl BlockEntity for EndGatewayBlockEntity {
Some(nbt)
}
fn tick(&self, world: &Arc<World>) {
let cooling_down = self.is_cooling_down();
if let Ok(mut age) = self.age.lock() {
*age += 1;
if cooling_down {
if let Ok(mut cooldown) = self.teleport_cooldown.lock() {
*cooldown -= 1;
}
} else if *age % Self::ATTENTION_INTERVAL == 0 {
self.trigger_cooldown(world, self.position);
}
}
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
@ -81,13 +117,357 @@ impl BlockEntity for EndGatewayBlockEntity {
impl EndGatewayBlockEntity {
pub const ID: &'static str = "minecraft:end_gateway";
pub const SPAWN_TIME: i64 = 200;
pub const COOLDOWN_TIME: i32 = 40;
pub const ATTENTION_INTERVAL: i64 = 2400;
pub const EVENT_COOLDOWN: u8 = 1;
pub const GATEWAY_HEIGHT_ABOVE_SURFACE: i32 = 10;
#[must_use]
pub const fn new(position: BlockPos) -> Self {
Self {
position,
age: Mutex::new(0),
teleport_cooldown: Mutex::new(0),
exact_teleport: Mutex::new(false),
exit_portal: Mutex::new(None),
}
}
#[must_use]
pub fn is_spawning(&self) -> bool {
self.age.lock().is_ok_and(|age| *age < Self::SPAWN_TIME)
}
#[must_use]
pub fn is_cooling_down(&self) -> bool {
self.teleport_cooldown.lock().is_ok_and(|cd| *cd > 0)
}
#[must_use]
pub fn get_spawn_percent(&self, a: f32) -> f32 {
let age = self.age.lock().map_or(0, |g| *g);
((age as f32 + a) / Self::SPAWN_TIME as f32).clamp(0.0, 1.0)
}
#[must_use]
pub fn get_cooldown_percent(&self, a: f32) -> f32 {
let cd = self.teleport_cooldown.lock().map_or(0, |g| *g);
1.0 - ((cd as f32 - a) / Self::COOLDOWN_TIME as f32).clamp(0.0, 1.0)
}
pub fn trigger_cooldown(&self, world: &World, pos: BlockPos) {
if let Ok(mut cd) = self.teleport_cooldown.lock() {
*cd = Self::COOLDOWN_TIME;
}
world.add_synced_block_event(pos, Self::EVENT_COOLDOWN, 0);
}
pub fn beam_animation_tick(&self) {
if let Ok(mut age) = self.age.lock() {
*age += 1;
}
if self.is_cooling_down()
&& let Ok(mut cd) = self.teleport_cooldown.lock()
{
*cd -= 1;
}
}
pub fn trigger_event(&self, b0: u8, _b1: u8) -> bool {
if b0 == Self::EVENT_COOLDOWN {
if let Ok(mut cd) = self.teleport_cooldown.lock() {
*cd = Self::COOLDOWN_TIME;
}
true
} else {
false
}
}
pub fn set_exit_position(&self, exact_position: BlockPos, exact: bool) {
if let Ok(mut exact_tp) = self.exact_teleport.lock() {
*exact_tp = exact;
}
if let Ok(mut exit) = self.exit_portal.lock() {
*exit = Some(exact_position);
}
}
#[must_use]
pub fn get_portal_position(
&self,
current_level: &Arc<World>,
portal_entry_pos: BlockPos,
) -> Option<Vector3<f64>> {
let exit_portal_opt = self.exit_portal.lock().ok().and_then(|opt| *opt);
if exit_portal_opt.is_none()
&& current_level.dimension == pumpkin_data::dimension::Dimension::THE_END
{
let exit_portal_pos =
Self::find_or_create_valid_teleport_pos(current_level, portal_entry_pos);
let exit_portal_pos = BlockPos::new(
exit_portal_pos.0.x,
exit_portal_pos.0.y + Self::GATEWAY_HEIGHT_ABOVE_SURFACE,
exit_portal_pos.0.z,
);
tracing::debug!("Creating portal at {:?}", exit_portal_pos);
Self::spawn_gateway_portal(current_level, exit_portal_pos, portal_entry_pos);
let exact = self.exact_teleport.lock().is_ok_and(|g| *g);
self.set_exit_position(exit_portal_pos, exact);
}
let exit_portal = self.exit_portal.lock().ok().and_then(|opt| *opt)?;
let exact = self.exact_teleport.lock().is_ok_and(|g| *g);
let pos = if exact {
exit_portal
} else {
Self::find_exit_position(current_level, exit_portal)
};
Some(Vector3::new(
pos.0.x as f64 + 0.5,
pos.0.y as f64,
pos.0.z as f64 + 0.5,
))
}
fn find_exit_position(level: &World, exit_portal: BlockPos) -> BlockPos {
let search_center = BlockPos::new(exit_portal.0.x, exit_portal.0.y + 2, exit_portal.0.z);
let tallest = Self::find_tallest_block(level, search_center, 5, false);
tracing::debug!(
"Best exit position for portal at {:?} is {:?}",
exit_portal,
tallest
);
BlockPos::new(tallest.0.x, tallest.0.y + 1, tallest.0.z)
}
fn find_or_create_valid_teleport_pos(
level: &Arc<World>,
end_gateway_pos: BlockPos,
) -> BlockPos {
let exit_portal_xz = Self::find_exit_portal_xz_pos_tentative(level, end_gateway_pos);
let chunk_x = (exit_portal_xz.x / 16.0).floor() as i32;
let chunk_z = (exit_portal_xz.z / 16.0).floor() as i32;
let exit_portal_pos = Self::find_valid_spawn_in_chunk(level, chunk_x, chunk_z);
let exit_portal_pos = exit_portal_pos.map_or_else(
|| {
let new_exit_portal_pos = BlockPos::new(
(exit_portal_xz.x + 0.5).floor() as i32,
75,
(exit_portal_xz.z + 0.5).floor() as i32,
);
tracing::debug!(
"Failed to find a suitable block to teleport to, spawning an island on {:?}",
new_exit_portal_pos
);
Self::spawn_end_island(level, new_exit_portal_pos);
new_exit_portal_pos
},
|pos| {
tracing::debug!("Found suitable block to teleport to: {:?}", pos);
pos
},
);
Self::find_tallest_block(level, exit_portal_pos, 16, true)
}
fn find_exit_portal_xz_pos_tentative(level: &World, end_gateway_pos: BlockPos) -> Vector3<f64> {
let mut dir = Vector3::new(end_gateway_pos.0.x as f64, 0.0, end_gateway_pos.0.z as f64);
let len = dir.x.hypot(dir.z);
if len > 0.0 {
dir.x /= len;
dir.z /= len;
} else {
dir.x = 1.0;
}
let mut exit_portal_xz = Vector3::new(dir.x * 1024.0, 0.0, dir.z * 1024.0);
let mut chunk_limit = 16;
while !Self::is_chunk_empty(level, exit_portal_xz) && chunk_limit > 0 {
chunk_limit -= 1;
exit_portal_xz.x -= dir.x * 16.0;
exit_portal_xz.z -= dir.z * 16.0;
}
let mut forward_limit = 16;
while Self::is_chunk_empty(level, exit_portal_xz) && forward_limit > 0 {
forward_limit -= 1;
exit_portal_xz.x += dir.x * 16.0;
exit_portal_xz.z += dir.z * 16.0;
}
exit_portal_xz
}
fn is_chunk_empty(level: &World, xz_pos: Vector3<f64>) -> bool {
let chunk_x = (xz_pos.x / 16.0).floor() as i32;
let chunk_z = (xz_pos.z / 16.0).floor() as i32;
let chunk_pos = Vector2::new(chunk_x, chunk_z);
level
.level
.read_chunk_sync(&chunk_pos, |chunk| {
let sections = chunk
.section
.block_sections
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner);
sections.iter().all(|s| match s {
pumpkin_world::chunk::palette::BlockPalette::Homogeneous(id) => {
pumpkin_data::block_properties::is_air(*id)
}
pumpkin_world::chunk::palette::BlockPalette::Heterogeneous(_) => false,
})
})
.unwrap_or(true)
}
fn find_tallest_block(
level: &World,
around: BlockPos,
dist: i32,
allow_bedrock: bool,
) -> BlockPos {
let mut tallest: Option<BlockPos> = None;
let max_y = level.dimension.min_y + level.dimension.height - 1;
let min_y = level.dimension.min_y;
for xd in -dist..=dist {
for zd in -dist..=dist {
if xd != 0 || zd != 0 || allow_bedrock {
let mut y = max_y;
let target_min_y = tallest.map_or(min_y, |t| t.0.y);
while y > target_min_y {
let check_pos = BlockPos::new(around.0.x + xd, y, around.0.z + zd);
let (block, state) = level.get_block_and_state(&check_pos);
if !state.is_air()
&& (allow_bedrock || block != &Block::BEDROCK)
&& state.is_full_cube()
{
tallest = Some(check_pos);
break;
}
y -= 1;
}
}
}
}
tallest.unwrap_or(around)
}
fn find_valid_spawn_in_chunk(level: &World, chunk_x: i32, chunk_z: i32) -> Option<BlockPos> {
let min_x = chunk_x * 16;
let max_x = min_x + 15;
let min_z = chunk_z * 16;
let max_z = min_z + 15;
let min_y = 30;
let max_y = level.dimension.min_y + level.dimension.height - 1;
let mut closest: Option<BlockPos> = None;
let mut closest_dist = 0.0f64;
for x in min_x..=max_x {
for z in min_z..=max_z {
for y in min_y..=max_y {
let pos = BlockPos::new(x, y, z);
let (block, _state) = level.get_block_and_state(&pos);
if block == &Block::END_STONE {
let above = BlockPos::new(x, y + 1, z);
let above2 = BlockPos::new(x, y + 2, z);
let above_state = level.get_block_state(&above);
let above2_state = level.get_block_state(&above2);
if !above_state.is_full_cube() && !above2_state.is_full_cube() {
let dist = (x * x + z * z) as f64;
if closest.is_none() || dist < closest_dist {
closest = Some(pos);
closest_dist = dist;
}
}
}
}
}
}
closest
}
fn spawn_end_island(world: &Arc<World>, pos: BlockPos) {
let seed = (pos.0.x as u64) ^ ((pos.0.z as u64) << 32) ^ (pos.0.y as u64);
let mut random = RandomGenerator::Xoroshiro(Xoroshiro::from_seed(seed));
let mut size = random.next_bounded_i32(3) as f32 + 4.0;
let mut dy = 0i32;
while size > 0.5 {
let start = size.copysign(-1.0).floor() as i32;
let end = size.ceil() as i32;
let radius_sq = (size + 1.0) * (size + 1.0);
for dx in start..=end {
for dz in start..=end {
if (dx * dx + dz * dz) as f32 <= radius_sq {
let target = BlockPos::new(pos.0.x + dx, pos.0.y + dy, pos.0.z + dz);
world.set_block_state(
&target,
Block::END_STONE.default_state.id,
BlockFlags::NOTIFY_ALL,
);
}
}
}
size -= random.next_bounded_i32(2) as f32 + 0.5;
dy -= 1;
}
}
fn spawn_gateway_portal(world: &Arc<World>, portal_pos: BlockPos, exit_pos: BlockPos) {
let origin = portal_pos;
for dx in -1i32..=1 {
for dy in -2i32..=2 {
for dz in -1i32..=1 {
let same_x = dx == 0;
let same_y = dy == 0;
let same_z = dz == 0;
let end = dy.abs() == 2;
let target = BlockPos::new(origin.0.x + dx, origin.0.y + dy, origin.0.z + dz);
if same_x && same_y && same_z {
world.set_block_state(
&target,
Block::END_GATEWAY.default_state.id,
BlockFlags::NOTIFY_LISTENERS,
);
let return_gateway = Arc::new(Self {
position: target,
age: Mutex::new(0),
teleport_cooldown: Mutex::new(0),
exact_teleport: Mutex::new(false),
exit_portal: Mutex::new(Some(exit_pos)),
});
world.add_block_entity(return_gateway);
} else if same_y {
world.set_block_state(
&target,
Block::AIR.default_state.id,
BlockFlags::NOTIFY_LISTENERS,
);
} else if (end && same_x && same_z) || ((same_x || same_z) && !end) {
world.set_block_state(
&target,
Block::BEDROCK.default_state.id,
BlockFlags::NOTIFY_LISTENERS,
);
} else {
world.set_block_state(
&target,
Block::AIR.default_state.id,
BlockFlags::NOTIFY_LISTENERS,
);
}
}
}
}
}
}

View File

@ -30,6 +30,7 @@ use crate::block::blocks::decorated_pot::DecoratedPotBlock;
use crate::block::blocks::dirt_path::DirtPathBlock;
use crate::block::blocks::doors::DoorBlock;
use crate::block::blocks::dripstone::DripstoneBlock;
use crate::block::blocks::end_gateway::EndGatewayBlock;
use crate::block::blocks::end_portal::EndPortalBlock;
use crate::block::blocks::end_portal_frame::EndPortalFrameBlock;
use crate::block::blocks::falling::FallingBlock;
@ -331,6 +332,7 @@ pub fn default_registry() -> Arc<BlockRegistry> {
manager.register(BeehiveBlock);
manager.register(PressurePlateBlock);
manager.register(WeightedPressurePlateBlock);
manager.register(EndGatewayBlock);
manager.register(EndPortalBlock);
manager.register(SpawnerBlock);
manager.register(EndPortalFrameBlock);

View File

@ -134,15 +134,17 @@ pub fn send_attribute_updates_for_living(
));
let name = match attribute.id {
22 => "minecraft:movement".to_string(),
19 => "minecraft:health".to_string(),
18 => "minecraft:absorption".to_string(),
2 => "minecraft:attack_damage".to_string(),
0 => "minecraft:armor".to_string(),
16 => "minecraft:knockback_resistance".to_string(),
17 => "minecraft:luck".to_string(),
13 => "minecraft:follow_range".to_string(),
15 => "minecraft:horse.jump_strength".to_string(),
id if id == Attributes::MOVEMENT_SPEED.id => "minecraft:movement".to_string(),
id if id == Attributes::MAX_HEALTH.id => "minecraft:health".to_string(),
id if id == Attributes::MAX_ABSORPTION.id => "minecraft:absorption".to_string(),
id if id == Attributes::ATTACK_DAMAGE.id => "minecraft:attack_damage".to_string(),
id if id == Attributes::ARMOR.id => "minecraft:armor".to_string(),
id if id == Attributes::KNOCKBACK_RESISTANCE.id => {
"minecraft:knockback_resistance".to_string()
}
id if id == Attributes::LUCK.id => "minecraft:luck".to_string(),
id if id == Attributes::FOLLOW_RANGE.id => "minecraft:follow_range".to_string(),
id if id == Attributes::JUMP_STRENGTH.id => "minecraft:horse.jump_strength".to_string(),
// Fallback for others
_ => format!("minecraft:attribute.{}", attribute.id),
};
@ -261,3 +263,85 @@ impl AttributeRegistry {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use pumpkin_data::attributes::Attributes;
use pumpkin_data::entity::EntityType;
#[test]
fn player_base_attributes() {
let speed_attr = EntityType::PLAYER
.attributes
.iter()
.find(|(attr, _)| attr.id == Attributes::MOVEMENT_SPEED.id);
assert!(speed_attr.is_some());
let (_, base_speed) = speed_attr.unwrap();
assert!((base_speed - 0.1).abs() < f64::EPSILON);
}
#[test]
fn sprinting_modifier_calculation() {
let mut instance = AttributeInstance::new(0.1);
assert!((instance.value() - 0.1).abs() < f64::EPSILON);
let sprinting_mod = Modifier {
id: "minecraft:sprinting".to_string(),
amount: 0.300_000_011_920_928_96,
operation: ModifierOperation::MultiplyTotal,
};
instance.add_or_replace_modifier(sprinting_mod);
let sprinting_value = instance.value();
// 0.1 * (1.0 + 0.30000001192092896) = 0.1300000011920929
assert!((sprinting_value - 0.130_000_001_192_092_9).abs() < 1e-9);
instance.remove_modifier("minecraft:sprinting");
assert!((instance.value() - 0.1).abs() < f64::EPSILON);
}
#[test]
fn attribute_modifier_operations() {
let mut instance = AttributeInstance::new(10.0);
// ADD: 10.0 + 2.0 + 3.0 = 15.0
instance.add_or_replace_modifier(Modifier {
id: "add_1".to_string(),
amount: 2.0,
operation: ModifierOperation::Add,
});
instance.add_or_replace_modifier(Modifier {
id: "add_2".to_string(),
amount: 3.0,
operation: ModifierOperation::Add,
});
assert!((instance.value() - 15.0).abs() < f64::EPSILON);
// MULTIPLY_BASE: 15.0 * (1.0 + 0.5 + 0.2) = 15.0 * 1.7 = 25.5
instance.add_or_replace_modifier(Modifier {
id: "mul_base_1".to_string(),
amount: 0.5,
operation: ModifierOperation::MultiplyBase,
});
instance.add_or_replace_modifier(Modifier {
id: "mul_base_2".to_string(),
amount: 0.2,
operation: ModifierOperation::MultiplyBase,
});
assert!((instance.value() - 25.5).abs() < f64::EPSILON);
// MULTIPLY_TOTAL: 25.5 * (1.0 + 0.1) * (1.0 + 0.2) = 25.5 * 1.1 * 1.2 = 33.66
instance.add_or_replace_modifier(Modifier {
id: "mul_total_1".to_string(),
amount: 0.1,
operation: ModifierOperation::MultiplyTotal,
});
instance.add_or_replace_modifier(Modifier {
id: "mul_total_2".to_string(),
amount: 0.2,
operation: ModifierOperation::MultiplyTotal,
});
assert!((instance.value() - 33.66).abs() < 1e-9);
}
}

View File

@ -763,6 +763,9 @@ impl EnderDragonEntity {
}
pub fn ai_step(&self) {
if self.mob_entity.living_entity.entity.is_removed() {
return;
}
self.mob_entity.living_entity.entity.update_last_pos();
self.ensure_nodes_initialized();
self.update_flap_time();
@ -784,7 +787,14 @@ impl EnderDragonEntity {
if let Some(ref fight_mutex) = world.dragon_fight {
let living = &self.mob_entity.living_entity;
if let Ok(mut fight) = fight_mutex.lock() {
fight.update_dragon(&world, living.health.load(), living.get_max_health());
let custom_name = living.entity.custom_name.load();
fight.update_dragon(
&world,
living.entity.entity_uuid,
living.health.load(),
living.get_max_health(),
custom_name.as_ref().as_ref(),
);
}
}
}
@ -807,17 +817,19 @@ impl EnderDragonEntity {
phase.tick(self);
if phase_type == EnderDragonPhase::Dying {
if self.mob_entity.living_entity.entity.is_removed() {
return;
}
let target_location = *self
.target_location
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if let Some(target) = target_location {
let pos = self.mob_entity.living_entity.entity.pos.load();
self.steer_toward(pos, target, phase.get_fly_speed(), phase.get_turn_speed());
if phase_type != EnderDragonPhase::Dying {
let target_location = *self
.target_location
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if let Some(target) = target_location {
let pos = self.mob_entity.living_entity.entity.pos.load();
self.steer_toward(pos, target, phase.get_fly_speed(), phase.get_turn_speed());
}
}
self.mob_entity.living_entity.entity.send_pos_rot();

View File

@ -1,9 +1,9 @@
use super::EnderDragonPhase;
use crate::entity::boss::ender_dragon::{DEATH_TIMER_MAX, EnderDragonEntity};
use crate::entity::boss::ender_dragon::{DEATH_TIMER_MAX, EnderDragonEntity, Vector3Ext};
use crate::entity::experience_orb::ExperienceOrbEntity;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::math::{vector2::Vector2, vector3::Vector3};
pub struct DyingPhase;
@ -17,31 +17,82 @@ impl super::Phase for DyingPhase {
.target_location
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = None;
*dragon
.dragon_death_time
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = 0;
}
fn get_fly_speed(&self) -> f32 {
3.0
}
fn get_fly_target_location(&self) -> Option<Vector3<f64>> {
None
}
fn tick(&self, dragon: &EnderDragonEntity) {
let mut t = dragon
.dragon_death_time
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
*t += 1;
let death_time = {
let mut t = dragon
.dragon_death_time
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
*t += 1;
*t
};
let entity = &dragon.mob_entity.living_entity.entity;
let world = entity.world.load();
let pos = entity.pos.load();
if *t == 1 {
world.play_sound(
Sound::EntityEnderDragonDeath,
SoundCategory::Hostile,
&entity.pos.load(),
);
// 1. Resolve target location (center of the exit podium) if unset
let target = {
let mut target_loc_lock = dragon
.target_location
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if target_loc_lock.is_none() {
let fight_origin = *dragon
.fight_origin
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let top_y = world.get_top_block(Vector2::new(fight_origin.0.x, fight_origin.0.z));
let egg_y = if top_y > world.min_y {
top_y as f64
} else {
65.0
};
*target_loc_lock = Some(Vector3::new(
fight_origin.0.x as f64 + 0.5,
egg_y,
fight_origin.0.z as f64 + 0.5,
));
}
*target_loc_lock
};
// 2. Steer towards target podium and update health matching vanilla doServerTick
if let Some(target_pos) = target {
let dist_sq = pos.distance_squared(target_pos);
if (100.0..=22500.0).contains(&dist_sq) {
dragon.steer_toward(pos, target_pos, 3.0, 0.1);
dragon.mob_entity.living_entity.health.store(1.0);
} else {
dragon.mob_entity.living_entity.health.store(0.0);
}
}
if *t >= 180 && *t <= 200 {
// 3. Play death sound at tick 1
if death_time == 1 {
world.play_sound(Sound::EntityEnderDragonDeath, SoundCategory::Hostile, &pos);
}
// 4. Explosion particles matching doClientTick (every 10 ticks and during final ticks)
if death_time % 10 == 0 || (180..=200).contains(&death_time) {
let xo = (rand::random::<f32>() - 0.5) * 8.0;
let yo = (rand::random::<f32>() - 0.5) * 4.0;
let zo = (rand::random::<f32>() - 0.5) * 8.0;
let pos = entity.pos.load();
world.spawn_particle(
Vector3::new(
pos.x + xo as f64,
@ -55,6 +106,7 @@ impl super::Phase for DyingPhase {
);
}
// 5. Spawn experience orbs
let xp_count = if let Some(ref fight_mutex) = world.dragon_fight
&& !fight_mutex
.lock()
@ -66,14 +118,15 @@ impl super::Phase for DyingPhase {
500
};
if *t > 150 && *t % 5 == 0 {
ExperienceOrbEntity::spawn(&world, entity.pos.load(), (xp_count as f32 * 0.08) as u32);
if death_time > 150 && death_time % 5 == 0 {
ExperienceOrbEntity::spawn(&world, pos, (xp_count as f32 * 0.08) as u32);
}
entity.velocity.store(Vector3::new(0.0, 0.1, 0.0));
if *t >= DEATH_TIMER_MAX {
ExperienceOrbEntity::spawn(&world, entity.pos.load(), (xp_count as f32 * 0.2) as u32);
// 6. Complete death sequence at DEATH_TIMER_MAX
if death_time >= DEATH_TIMER_MAX {
ExperienceOrbEntity::spawn(&world, pos, (xp_count as f32 * 0.2) as u32);
if let Some(ref fight_mutex) = world.dragon_fight {
fight_mutex

View File

@ -1,4 +1,5 @@
use core::f32;
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::entity::{Entity, EntityBase, living::LivingEntity};
use pumpkin_data::{
@ -6,20 +7,28 @@ use pumpkin_data::{
tag::{self, Taggable},
};
use pumpkin_protocol::java::client::play::Metadata;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
pub struct EndCrystalEntity {
entity: Entity,
beam_target: Mutex<Option<BlockPos>>,
show_bottom: AtomicBool,
invulnerable: AtomicBool,
}
impl EndCrystalEntity {
#[must_use]
pub const fn new(entity: Entity) -> Self {
Self { entity }
Self {
entity,
beam_target: Mutex::new(None),
show_bottom: AtomicBool::new(false),
invulnerable: AtomicBool::new(false),
}
}
}
impl EndCrystalEntity {
pub fn set_show_bottom(&self, show_bottom: bool) {
self.show_bottom.store(show_bottom, Ordering::Relaxed);
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::end_crystal::SHOW_BOTTOM,
@ -28,6 +37,39 @@ impl EndCrystalEntity {
None,
);
}
pub fn show_bottom(&self) -> bool {
self.show_bottom.load(Ordering::Relaxed)
}
pub fn set_beam_target(&self, beam_target: Option<BlockPos>) {
*self
.beam_target
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = beam_target;
self.entity.send_meta_data(
&[Metadata::new(
pumpkin_data::tracked_data::end_crystal::BEAM_TARGET,
beam_target,
)],
None,
);
}
pub fn beam_target(&self) -> Option<BlockPos> {
*self
.beam_target
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
}
pub fn set_invulnerable(&self, invulnerable: bool) {
self.invulnerable.store(invulnerable, Ordering::Relaxed);
}
pub fn is_invulnerable(&self) -> bool {
self.invulnerable.load(Ordering::Relaxed)
}
}
impl EntityBase for EndCrystalEntity {
@ -48,16 +90,26 @@ impl EntityBase for EndCrystalEntity {
_source: Option<&dyn EntityBase>,
_cause: Option<&dyn EntityBase>,
) -> bool {
if self.is_invulnerable() {
return false;
}
self.entity.remove();
let world = self.entity.world.load();
if !damage_type.has_tag(&tag::DamageType::MINECRAFT_IS_EXPLOSION) {
let world = self.entity.world.load();
let pos = self.entity.pos.load();
world.explode(pos, 6.0, crate::world::ExplosionInteraction::Block);
}
// TODO
if let Some(ref fight_mutex) = world.dragon_fight
&& let Ok(mut fight) = fight_mutex.lock()
{
fight.on_crystal_destroyed(&world, self.entity.entity_uuid);
}
true
}
fn cast_any(&self) -> &dyn std::any::Any {
self
}

View File

@ -2643,10 +2643,17 @@ impl EntityBase for LivingEntity {
// We allow movement during death animation (20 ticks) so knockback is applied.
let is_alive = !self.dead.load(Relaxed) && self.health.load() > 0.0;
let in_death_animation = self.health.load() <= 0.0 && self.death_time.load(Relaxed) < 20;
if is_alive || (in_death_animation && self.entity.entity_type != &EntityType::PLAYER) {
let is_player = self.entity.entity_type == &EntityType::PLAYER;
if (is_alive || in_death_animation) && !is_player {
self.tick_movement(caller);
// Vanilla-like order: freeze logic runs after movement/collisions.
self.entity.tick_frozen(caller);
} else if is_alive {
let suffocating = self.entity.tick_block_collisions(caller);
if suffocating {
caller.damage(caller, 1.0, DamageType::IN_WALL);
}
self.entity.tick_frozen(caller);
}
// TODO
@ -2860,7 +2867,35 @@ impl EntityBase for LivingEntity {
}
}
pub const SPEED_MODIFIER_SPRINTING_ID: &str = "minecraft:sprinting";
pub const SPEED_MODIFIER_SPRINTING_AMOUNT: f64 = 0.300_000_011_920_928_96;
impl LivingEntity {
pub fn set_sprinting(&self, is_sprinting: bool) {
self.entity.set_sprinting(is_sprinting);
self.update_attribute(&Attributes::MOVEMENT_SPEED, |speed| {
speed.remove_modifier(SPEED_MODIFIER_SPRINTING_ID);
if is_sprinting {
speed.add_or_replace_modifier(Modifier {
id: SPEED_MODIFIER_SPRINTING_ID.to_string(),
amount: SPEED_MODIFIER_SPRINTING_AMOUNT,
operation: ModifierOperation::MultiplyTotal,
});
}
});
crate::entity::attributes::send_attribute_updates_for_living(
self,
vec![Attributes::MOVEMENT_SPEED],
);
}
#[must_use]
pub fn get_block_speed_factor(&self) -> f32 {
let efficiency = self.get_attribute_value(&Attributes::MOVEMENT_EFFICIENCY) as f32;
let super_factor = self.entity.get_block_speed_factor();
super_factor + efficiency * (1.0 - super_factor)
}
/// Applies data-driven `apply_effects` consume effects after an item completes use.
/// Vanilla: `Consumable.onConsume` invokes every configured effect server-side.
fn apply_consumable_effects(&self, caller: &dyn EntityBase, item: &ItemStack) {

View File

@ -280,6 +280,21 @@ pub trait EntityBase: Send + Sync + std::any::Any {
false
}
fn set_sprinting(&self, is_sprinting: bool) {
if let Some(living) = self.get_living_entity() {
living.set_sprinting(is_sprinting);
} else {
self.get_entity().set_sprinting(is_sprinting);
}
}
fn get_block_speed_factor(&self) -> f32 {
self.get_living_entity().map_or_else(
|| self.get_entity().get_block_speed_factor(),
LivingEntity::get_block_speed_factor,
)
}
/// Custom Y-axis velocity drag multiplier applied during `travel_in_air`.
/// Bats return `Some(0.6)` to match vanilla's `travel()` override.
fn get_y_velocity_drag(&self) -> Option<f64> {
@ -2157,18 +2172,27 @@ impl Entity {
)
}
#[must_use]
pub fn get_block_pos_below_that_affects_my_movement(&self) -> BlockPos {
self.get_pos_with_y_offset(0.500_001).0
}
#[must_use]
#[expect(clippy::float_cmp)]
fn get_velocity_multiplier(&self) -> f32 {
let block = self.world.load().get_block(&self.block_pos.load());
let multiplier = block.velocity_multiplier;
if multiplier != 1.0 || block == &Block::WATER || block == &Block::BUBBLE_COLUMN {
multiplier
pub fn get_block_speed_factor(&self) -> f32 {
let world = self.world.load();
let (block, _state) = world.get_block_and_state(&self.block_pos.load());
let speed_factor_here = block.get_speed_factor();
if block != &Block::WATER && block != &Block::BUBBLE_COLUMN {
if speed_factor_here == 1.0 {
let below_pos = self.get_block_pos_below_that_affects_my_movement();
let (below_block, _below_state) = world.get_block_and_state(&below_pos);
below_block.get_speed_factor()
} else {
speed_factor_here
}
} else {
let (_pos, block, _state) = self.get_block_with_y_offset(0.500_001);
block.velocity_multiplier
speed_factor_here
}
}
@ -2224,7 +2248,7 @@ impl Entity {
self.move_pos(final_move);
let velocity_multiplier = f64::from(self.get_velocity_multiplier());
let velocity_multiplier = f64::from(caller.get_block_speed_factor());
self.velocity.store(final_move * velocity_multiplier);
@ -2317,7 +2341,9 @@ impl Entity {
let entity_id = self.entity_id;
let yaw = self.yaw.load();
let rt_handle = world_clone.server.upgrade().map(|s| s.runtime.clone());
rayon::spawn(move || {
let _guard = rt_handle.as_ref().map(tokio::runtime::Handle::enter);
let Some(entity_arc) = world_clone.get_entity_by_id(entity_id) else {
return;
};
@ -2445,23 +2471,15 @@ impl Entity {
let mut new_manager = PortalProcessor::new(portal_type, pos, portal_world);
if let Some(portal) = NetherPortal::get_on_axis(
&world,
&pos,
pumpkin_data::block_properties::HorizontalAxis::X,
) && portal.was_already_valid()
{
new_manager.set_source_portal(SourcePortalInfo {
lower_corner: portal.lower_corner(),
axis: portal.axis(),
width: portal.width(),
height: portal.height(),
});
} else if let Some(portal) = NetherPortal::get_on_axis(
&world,
&pos,
pumpkin_data::block_properties::HorizontalAxis::Z,
) && portal.was_already_valid()
let (block, state) = world.get_block_and_state(&pos);
let source_axis = (block == &pumpkin_data::Block::NETHER_PORTAL).then(|| {
let props = <pumpkin_data::block_properties::NetherPortalLikeProperties as pumpkin_data::block_properties::BlockProperties>::from_state_id(state.id, block);
props.axis
});
if let Some(axis) = source_axis
&& let Some(portal) = NetherPortal::get_on_axis(&world, &pos, axis)
&& portal.was_already_valid()
{
new_manager.set_source_portal(SourcePortalInfo {
lower_corner: portal.lower_corner(),
@ -2475,6 +2493,22 @@ impl Entity {
} else if let Some(manager) = manager.as_mut() {
manager.entry_position = pos;
manager.inside_portal_this_tick = true;
if manager.source_portal.is_none() {
let (block, state) = world.get_block_and_state(&pos);
if block == &pumpkin_data::Block::NETHER_PORTAL {
let props = <pumpkin_data::block_properties::NetherPortalLikeProperties as pumpkin_data::block_properties::BlockProperties>::from_state_id(state.id, block);
if let Some(portal) = NetherPortal::get_on_axis(&world, &pos, props.axis)
&& portal.was_already_valid()
{
manager.set_source_portal(SourcePortalInfo {
lower_corner: portal.lower_corner(),
axis: portal.axis(),
width: portal.width(),
height: portal.height(),
});
}
}
}
}
}
@ -2667,6 +2701,41 @@ impl Entity {
self.sneaking.load(Ordering::Relaxed)
}
#[must_use]
pub fn is_swimming(&self) -> bool {
self.swimming.load(Ordering::Relaxed)
}
#[must_use]
pub fn is_visually_swimming(&self) -> bool {
self.pose.load() == EntityPose::Swimming
}
#[must_use]
pub fn is_in_water(&self) -> bool {
self.touching_water.load(Ordering::Relaxed)
}
#[must_use]
pub fn is_submerged_in_water(&self) -> bool {
let pos = self.pos.load();
let eye_height = self.get_eye_height();
let eye_pos = BlockPos::floored(pos.x, pos.y + eye_height - 0.111_111_11, pos.z);
let world = self.world.load();
let (fluid, _) = world.get_fluid_and_fluid_state(&eye_pos);
fluid.id == Fluid::WATER.id || fluid.id == Fluid::FLOWING_WATER.id
}
#[must_use]
pub fn is_under_water(&self) -> bool {
self.is_in_water() && self.is_submerged_in_water()
}
#[must_use]
pub fn is_visually_crawling(&self) -> bool {
self.is_visually_swimming() && !self.is_in_water()
}
pub fn set_swimming(&self, swimming: bool) {
if self.swimming.load(Ordering::Relaxed) != swimming {
let mut event =
@ -2970,6 +3039,10 @@ impl Entity {
}
pub fn set_pose(&self, pose: EntityPose) {
if self.pose.load() == pose {
return;
}
let mut pose_event =
crate::plugin::api::events::entity::entity_pose_change::EntityPoseChangeEvent::new(
self.entity_id,
@ -2987,27 +3060,24 @@ impl Entity {
let dimension = Self::get_entity_dimensions(pose);
let position = self.pos.load();
let aabb = BoundingBox::new_from_pos(position.x, position.y, position.z, &dimension);
if self.world.load().is_space_empty(aabb.contract_all(1.0E-7)) {
self.pose.store(pose);
let dimension = Self::get_entity_dimensions(pose);
self.bounding_box.store(aabb);
self.entity_dimension.store(dimension);
let pose = pose as i32;
let mut bedrock_meta = SyncedActorDataList::new();
bedrock_meta.set(entity_data_key::POSE_INDEX, MetadataValue::Int(pose));
bedrock_meta.set(
entity_data_key::WIDTH,
MetadataValue::Float(dimension.width),
);
bedrock_meta.set(
entity_data_key::HEIGHT,
MetadataValue::Float(dimension.height),
);
self.send_meta_data(
&[Metadata::new(tracked_data::entity::DATA_POSE, VarInt(pose))],
Some(&bedrock_meta),
);
}
self.pose.store(pose);
self.bounding_box.store(aabb);
self.entity_dimension.store(dimension);
let pose = pose as i32;
let mut bedrock_meta = SyncedActorDataList::new();
bedrock_meta.set(entity_data_key::POSE_INDEX, MetadataValue::Int(pose));
bedrock_meta.set(
entity_data_key::WIDTH,
MetadataValue::Float(dimension.width),
);
bedrock_meta.set(
entity_data_key::HEIGHT,
MetadataValue::Float(dimension.height),
);
self.send_meta_data(
&[Metadata::new(tracked_data::entity::DATA_POSE, VarInt(pose))],
Some(&bedrock_meta),
);
}
/// Checks if the entity is invulnerable to the given damage type, considering both general invulnerability and specific immunities.

View File

@ -2191,22 +2191,51 @@ impl Player {
self.abilities.try_lock().is_ok_and(|a| a.flying)
}
pub fn set_sprinting(&self, is_sprinting: bool) {
self.living_entity.set_sprinting(is_sprinting);
}
#[must_use]
pub fn get_block_speed_factor(&self) -> f32 {
self.living_entity.get_block_speed_factor()
}
fn is_sleeping(&self) -> bool {
// TODO: Track sleeping position state explicitly (vanilla checks sleepingPosition.isPresent()).
self.sleeping_since.load().is_some()
}
fn is_swimming(&self, flying: bool) -> bool {
let entity = self.get_entity();
let touching_water = entity.touching_water.load(Ordering::Relaxed);
let can_start_swimming = entity.water_height.load() > self.living_entity.get_swim_height();
#[must_use]
pub fn is_swimming(&self) -> bool {
!self.is_flying()
&& self.gamemode.load() != GameMode::Spectator
&& self.get_entity().is_swimming()
}
touching_water
&& (entity.swimming.load(Ordering::Relaxed) || can_start_swimming)
&& entity.is_sprinting()
&& !entity.on_ground.load(Ordering::Relaxed)
&& !flying
&& !entity.has_vehicle()
pub fn update_swimming(&self) {
if self.is_flying() {
self.get_entity().set_swimming(false);
} else {
let entity = self.get_entity();
let is_sprinting = entity.is_sprinting();
let in_water = entity.is_in_water();
let is_passenger = entity.has_vehicle();
if entity.is_swimming() {
entity.set_swimming(is_sprinting && in_water && !is_passenger);
} else {
let is_under_water = entity.is_under_water();
let block_pos = entity.block_pos.load();
let world = entity.world.load();
let (fluid, _) = world.get_fluid_and_fluid_state(&block_pos);
let is_water_block = fluid.id == pumpkin_data::fluid::Fluid::WATER.id
|| fluid.id == pumpkin_data::fluid::Fluid::FLOWING_WATER.id;
entity.set_swimming(
is_sprinting && is_under_water && !is_passenger && is_water_block,
);
}
}
}
const fn is_auto_spin_attack() -> bool {
@ -2225,31 +2254,33 @@ impl Player {
.is_space_empty(aabb.contract_all(1.0E-7))
}
pub fn update_player_pose(&self) {
#[must_use]
pub fn get_desired_pose(&self) -> EntityPose {
let entity = self.get_entity();
if !self.can_fit_pose(EntityPose::Swimming) {
return;
}
let flying = self.is_flying();
let swimming = self.is_swimming(flying);
entity.set_swimming(swimming);
let desired_pose = if self.is_sleeping() {
if self.is_sleeping() {
EntityPose::Sleeping
} else if swimming {
} else if self.is_swimming() {
EntityPose::Swimming
} else if entity.is_fall_flying() {
EntityPose::FallFlying
} else if Self::is_auto_spin_attack() {
EntityPose::SpinAttack
} else if entity.is_sneaking() && !flying {
} else if entity.is_sneaking() && !self.is_flying() {
EntityPose::Crouching
} else {
EntityPose::Standing
};
}
}
let new_pose = if self.gamemode.load() == GameMode::Spectator
|| entity.has_vehicle()
pub fn update_player_pose(&self) {
if !self.can_fit_pose(EntityPose::Swimming) {
return;
}
self.update_swimming();
let desired_pose = self.get_desired_pose();
let actual_pose = if self.gamemode.load() == GameMode::Spectator
|| self.get_entity().has_vehicle()
|| self.can_fit_pose(desired_pose)
{
desired_pose
@ -2259,9 +2290,7 @@ impl Player {
EntityPose::Swimming
};
if entity.pose.load() != new_pose {
entity.set_pose(new_pose);
}
self.get_entity().set_pose(actual_pose);
}
pub fn wake_up(&self) {
@ -2648,10 +2677,10 @@ impl Player {
let block = Block::from_state_id(state.id);
let can_harvest = p.can_harvest(state, block);
let flags = if can_harvest {
pumpkin_world::world::BlockFlags::NOTIFY_NEIGHBORS
pumpkin_world::world::BlockFlags::NOTIFY_ALL
} else {
pumpkin_world::world::BlockFlags::SKIP_DROPS
| pumpkin_world::world::BlockFlags::NOTIFY_NEIGHBORS
| pumpkin_world::world::BlockFlags::NOTIFY_ALL
};
if world.break_block(&pos, Some(&p), flags).is_some() {
if let Some(server) = server_clone {
@ -3689,7 +3718,8 @@ impl Player {
self.send_permission_lvl_update();
player.request_teleport(position, yaw, pitch);
player.get_entity().set_pos(position);
player.get_entity().set_rotation(yaw, pitch);
player.get_entity().last_pos.store(position);
self.send_abilities_update();
@ -3703,6 +3733,17 @@ impl Player {
self.send_health();
new_world.send_world_info(&player, position, yaw, pitch);
if let ClientPlatform::Java(java_client) = player.client.as_ref() {
let center_chunk = player.get_entity().chunk_pos.load();
let chunk = new_world
.level
.get_or_fetch_chunk(center_chunk, std::clone::Clone::clone)
.await;
java_client.send_chunks(&[chunk]).await;
}
player.request_teleport(position, yaw, pitch);
}
}}
}

View File

@ -57,6 +57,12 @@ impl ItemBehaviour for EndCrystalItem {
world.spawn_entity(end_crystal.clone());
end_crystal.set_show_bottom(false);
item.decrement_unless_creative(player.gamemode.load(), 1);
if let Some(ref fight_mutex) = world.dragon_fight
&& let Ok(mut fight) = fight_mutex.lock()
{
fight.try_respawn(&world);
}
}
fn as_any(&self) -> &dyn std::any::Any {

View File

@ -46,7 +46,7 @@ impl BedrockClient {
let new_state = world.break_block(
&location,
Some(player),
BlockFlags::NOTIFY_NEIGHBORS | BlockFlags::SKIP_DROPS,
BlockFlags::NOTIFY_ALL | BlockFlags::SKIP_DROPS,
);
if new_state.is_some() {
server
@ -60,9 +60,9 @@ impl BedrockClient {
let broken_state = world.get_block_state(&location);
let can_harvest = player.can_harvest(broken_state, block);
let flags = if can_harvest {
BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::NOTIFY_ALL
} else {
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL
};
let new_state = world.break_block(&location, Some(player), flags);
if new_state.is_some() {
@ -154,9 +154,9 @@ impl BedrockClient {
let can_harvest = player.can_harvest(state, block);
let flags = if can_harvest {
BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::NOTIFY_ALL
} else {
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL
};
if world.break_block(&location, Some(player), flags).is_some() {
server

View File

@ -152,9 +152,9 @@ impl BedrockClient {
let input_data = packet.input_data;
if input_data.get(InputData::StartSprinting as usize) {
entity.set_sprinting(true);
player.set_sprinting(true);
} else if input_data.get(InputData::StopSprinting as usize) {
entity.set_sprinting(false);
player.set_sprinting(false);
}
if input_data.get(InputData::StartSneaking as usize) {

View File

@ -90,6 +90,7 @@ pub struct JavaClient {
pub player: ArcSwap<Option<Arc<Player>>>,
/// A collection of tasks associated with this client. The tasks await completion when removing the client.
tasks: TaskTracker,
rt_handle: tokio::runtime::Handle,
/// An notifier that is triggered when this client is closed.
close_token: CancellationToken,
/// A normal-priority queue of serialized packets to send to the network.
@ -167,6 +168,7 @@ impl JavaClient {
connection_state: pending.connection_state,
close_token: pending.close_token,
tasks: TaskTracker::new(),
rt_handle: tokio::runtime::Handle::current(),
outgoing_packet_queue_send: send,
outgoing_packet_queue_recv: Some(recv),
outgoing_packet_priority_send: priority_send,
@ -306,6 +308,7 @@ impl JavaClient {
if self.close_token.is_cancelled() {
None
} else {
let _guard = self.rt_handle.enter();
Some(self.tasks.spawn(task))
}
}

View File

@ -77,7 +77,7 @@ impl JavaClient {
let new_state = world.break_block(
&position,
Some(player),
BlockFlags::NOTIFY_NEIGHBORS | BlockFlags::SKIP_DROPS,
BlockFlags::NOTIFY_ALL | BlockFlags::SKIP_DROPS,
);
if new_state.is_some() {
server
@ -99,9 +99,9 @@ impl JavaClient {
let broken_state = world.get_block_state(&position);
let can_harvest = player.can_harvest(broken_state, block);
let flags = if can_harvest {
BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::NOTIFY_ALL
} else {
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL
};
let new_state = world.break_block(&position, Some(player), flags);
if new_state.is_some() {
@ -196,9 +196,9 @@ impl JavaClient {
&location,
Some(player),
if block_drop {
BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::NOTIFY_ALL
} else {
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_NEIGHBORS
BlockFlags::SKIP_DROPS | BlockFlags::NOTIFY_ALL
},
);
if new_state.is_some() {

View File

@ -24,7 +24,8 @@ impl JavaClient {
server;
PlayerToggleSprintEvent::new(player.clone(), true);
'after: {
player.get_entity().set_sprinting(event.is_sprinting);
player.set_sprinting(event.is_sprinting);
player.update_player_pose();
}
}}
}
@ -35,7 +36,8 @@ impl JavaClient {
server;
PlayerToggleSprintEvent::new(player.clone(), false);
'after: {
player.get_entity().set_sprinting(event.is_sprinting);
player.set_sprinting(event.is_sprinting);
player.update_player_pose();
}
}}
}

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,38 @@ use pumpkin_world::world::BlockFlags;
use super::World;
pub const PODIUM_RADIUS: i32 = 4;
pub const PODIUM_PILLAR_HEIGHT: i32 = 4;
pub const RIM_RADIUS: i32 = 1;
pub const CORNER_ROUNDING: f32 = 0.5;
pub const END_PODIUM_LOCATION: BlockPos = BlockPos::new(0, 0, 0);
#[must_use]
pub const fn get_location(offset: BlockPos) -> BlockPos {
BlockPos::new(
END_PODIUM_LOCATION.0.x + offset.0.x,
END_PODIUM_LOCATION.0.y + offset.0.y,
END_PODIUM_LOCATION.0.z + offset.0.z,
)
}
fn set_block(world: &Arc<World>, pos: &BlockPos, block: &Block) {
world.set_block_state(pos, block.default_state.id, BlockFlags::NOTIFY_LISTENERS);
}
fn drop_previous_and_set_block(world: &Arc<World>, pos: &BlockPos, block: &Block) {
if world.get_block(pos) != block {
set_block(world, pos, block);
}
}
/// Place the podium structure centred on `origin` into `world`.
pub fn place(world: &Arc<World>, origin: BlockPos, active: bool) {
let ox = origin.0.x;
let oy = origin.0.y;
let oy = if origin.0.y < 50 { 65 } else { origin.0.y };
let oz = origin.0.z;
for y in (oy - 4)..=(oy + 32) {
for y in (oy - 1)..=(oy + 32) {
for x in (ox - 4)..=(ox + 4) {
for z in (oz - 4)..=(oz + 4) {
let dx = (x - ox) as f64;
@ -28,50 +53,42 @@ pub fn place(world: &Arc<World>, origin: BlockPos, active: bool) {
let dz = (z - oz) as f64;
let dist_sq = dx * dx + dy * dy + dz * dz;
let inside_rim = dist_sq < 2.5 * 2.5; // inner 2-block disc
let near = inside_rim || dist_sq < 3.5 * 3.5; // outer rim up to 3.5
let closer_than_2_5 = dist_sq < 2.5 * 2.5;
let closer_than_3_5 = dist_sq < 3.5 * 3.5;
if !near {
continue;
}
let pos = BlockPos::new(x, y, z);
let state_id = match y.cmp(&oy) {
std::cmp::Ordering::Less => {
if inside_rim {
Block::BEDROCK.default_state.id
} else {
Block::END_STONE.default_state.id
}
}
std::cmp::Ordering::Greater => Block::AIR.default_state.id,
std::cmp::Ordering::Equal => {
if !inside_rim {
Block::BEDROCK.default_state.id
if closer_than_2_5 || closer_than_3_5 {
let pos = BlockPos::new(x, y, z);
if y < oy {
if closer_than_2_5 {
set_block(world, &pos, &Block::BEDROCK);
} else if active {
Block::END_PORTAL.default_state.id
drop_previous_and_set_block(world, &pos, &Block::END_STONE);
} else {
Block::AIR.default_state.id
set_block(world, &pos, &Block::END_STONE);
}
} else if y > oy {
if active {
drop_previous_and_set_block(world, &pos, &Block::AIR);
} else {
set_block(world, &pos, &Block::AIR);
}
} else if !closer_than_2_5 {
set_block(world, &pos, &Block::BEDROCK);
} else if active {
drop_previous_and_set_block(world, &pos, &Block::END_PORTAL);
} else {
set_block(world, &pos, &Block::AIR);
}
};
world.set_block_state(&pos, state_id, BlockFlags::NOTIFY_ALL);
}
}
}
}
for y in oy..=(oy + 3) {
world.set_block_state(
&BlockPos::new(ox, y, oz),
Block::BEDROCK.default_state.id,
BlockFlags::NOTIFY_ALL,
);
for y in 0..4 {
set_block(world, &BlockPos::new(ox, oy + y, oz), &Block::BEDROCK);
}
// Wall torches on N/S/E/W faces at pillar height 2
let torch_y = oy + 2;
// Torch position relative to origin and facing direction: (dx, dz, facing)
let center_of_pillar_y = oy + 2;
for (dx, dz, facing) in [
(0i32, -1i32, HorizontalFacing::North),
(0, 1, HorizontalFacing::South),
@ -81,9 +98,9 @@ pub fn place(world: &Arc<World>, origin: BlockPos, active: bool) {
let props = WallTorchLikeProperties { facing };
let state_id = props.to_state_id(&Block::WALL_TORCH);
world.set_block_state(
&BlockPos::new(ox + dx, torch_y, oz + dz),
&BlockPos::new(ox + dx, center_of_pillar_y, oz + dz),
state_id,
BlockFlags::NOTIFY_ALL,
BlockFlags::NOTIFY_LISTENERS,
);
}
}

View File

@ -4995,12 +4995,17 @@ impl World {
}
}
#[expect(clippy::too_many_lines)]
pub fn set_block_state(
self: &Arc<Self>,
position: &BlockPos,
block_state_id: BlockStateId,
flags: BlockFlags,
) -> BlockStateId {
if !self.is_in_build_limit(*position) {
return Block::AIR.default_state.id;
}
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
let replaced_block_state_id = self
.level
@ -5023,41 +5028,106 @@ impl World {
return block_state_id;
}
self.unsent_block_changes
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.insert(*position, block_state_id);
let old_block = Block::from_state_id(replaced_block_state_id);
let new_block = Block::from_state_id(block_state_id);
self.villager_poi
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.update_block(*position, new_block);
let is_new_block = old_block != new_block;
if is_new_block {
let mut poi = self
.portal_poi
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if villager_poi::profession_for_block(old_block).is_some() {
poi.remove(position);
}
if let Some(poi_type) = villager_poi::poi_type_for_block(new_block) {
poi.add_with_free_tickets(*position, poi_type, 1);
}
}
let block_moved = flags.contains(BlockFlags::MOVED);
if is_new_block
&& old_block.default_state.block_entity_type != u16::MAX
&& self.get_block_entity(position).is_some()
&& let Some(entity) = self.get_block_entity(position)
{
if !flags.contains(BlockFlags::SKIP_BLOCK_ENTITY_REPLACED_CALLBACK) {
entity.on_block_replaced(self, position);
}
self.remove_block_entity(position);
}
if is_new_block && (flags.contains(BlockFlags::NOTIFY_NEIGHBORS) || block_moved) {
self.block_registry.on_state_replaced(
self,
old_block,
position,
replaced_block_state_id,
block_moved,
);
}
if !flags.contains(BlockFlags::SKIP_BLOCK_ADDED_CALLBACK) && is_new_block {
self.block_registry.on_placed(
self,
new_block,
block_state_id,
position,
replaced_block_state_id,
block_moved,
);
let new_fluid = self.get_fluid(position);
self.block_registry.on_placed_fluid(
self,
new_fluid,
block_state_id,
position,
replaced_block_state_id,
block_moved,
);
}
// Level.java setBlock
if self.get_block_state_id(position) == block_state_id {
if flags.contains(BlockFlags::NOTIFY_LISTENERS) {
self.unsent_block_changes
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.insert(*position, block_state_id);
}
if flags.contains(BlockFlags::NOTIFY_NEIGHBORS) {
self.update_neighbors(position, None);
// TODO: updateNeighbourForOutputSignal if blockState.hasAnalogOutputSignal()
}
if !flags.contains(BlockFlags::MOVED) {
let mut neighbour_update_flags = flags;
neighbour_update_flags.remove(BlockFlags::NOTIFY_NEIGHBORS);
neighbour_update_flags.remove(BlockFlags::SKIP_REDSTONE_WIRE_STATE_REPLACEMENT);
self.block_registry.prepare(
self,
position,
old_block,
replaced_block_state_id,
neighbour_update_flags,
);
self.block_registry
.update_neighbors(self, position, neighbour_update_flags);
self.block_registry.prepare(
self,
position,
new_block,
block_state_id,
neighbour_update_flags,
);
}
self.villager_poi
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.update_block(*position, new_block);
if is_new_block {
let mut poi = self
.portal_poi
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if villager_poi::profession_for_block(old_block).is_some() {
poi.remove(position);
}
if let Some(poi_type) = villager_poi::poi_type_for_block(new_block) {
poi.add_with_free_tickets(*position, poi_type, 1);
}
}
}
self.level
.light_engine
.update_lighting_at(&self.level, *position);

View File

@ -4,6 +4,7 @@ use pumpkin_data::Block;
use pumpkin_data::block_properties::HorizontalAxis;
use pumpkin_data::dimension::Dimension;
use pumpkin_util::math::position::BlockPos;
use pumpkin_util::math::vector2::Vector2;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::world::BlockFlags;
@ -88,9 +89,23 @@ impl PortalType {
.is_some_and(crate::entity::living::LivingEntity::is_player);
let y = if is_player { 49.0 } else { 50.0 };
// Ensure chunks covering the platform are loaded/generated
// Generate/regenerate the obsidian platform (5x5 obsidian at Y=48, and 5x5x3 air above it)
let platform_pos = BlockPos::new(100, 49, 0);
// Ensure chunks covering the platform are loaded/generated
if let Ok(handle) = tokio::runtime::Handle::try_current() {
tokio::task::block_in_place(|| {
handle.block_on(async {
let center_chunk =
Vector2::new(platform_pos.0.x >> 4, platform_pos.0.z >> 4);
dest_world
.level
.get_or_fetch_chunk(center_chunk, |_| ())
.await;
});
});
}
// Generate/regenerate the obsidian platform (5x5 obsidian at Y=48, and 5x5x3 air above it)
for dx in -2..=2 {
for dz in -2..=2 {
for dy in -1..3 {
@ -171,68 +186,89 @@ impl PortalType {
let scale_factor_new = dest_world.dimension.coordinate_scale;
let scale_factor_current = current_level.dimension.coordinate_scale;
let scale_factor = scale_factor_current / scale_factor_new;
let target_pos =
BlockPos::floored(pos.x * scale_factor, pos.y, pos.z * scale_factor);
let teleportation_scale = scale_factor_current / scale_factor_new;
let worldborder = dest_world
.worldborder
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let (clamped_x, clamped_z) = worldborder.clamp_block(
(pos.x * teleportation_scale).floor() as i32,
(pos.z * teleportation_scale).floor() as i32,
);
drop(worldborder);
let source_axis = source_portal.map(|p| p.axis);
let approximate_exit_pos =
BlockPos::new(clamped_x, pos.y.floor() as i32, clamped_z);
let source_portal_axis = source_portal.map_or(HorizontalAxis::X, |p| p.axis);
let (final_pos, yaw) = NetherPortal::search_for_portal(&dest_world, target_pos)
.map_or_else(
|| {
if let Some((build_pos, axis, is_fallback)) =
NetherPortal::find_safe_location(
&dest_world,
target_pos,
pumpkin_data::block_properties::HorizontalAxis::X,
)
{
NetherPortal::build_portal_frame(
&dest_world,
build_pos,
axis,
is_fallback,
let exit_portal = NetherPortal::search_for_portal(
&dest_world,
approximate_exit_pos,
)
.or_else(|| {
// Ensure the chunks around approximate_exit_pos are generated/loaded in dest_world
if let Ok(handle) = tokio::runtime::Handle::try_current() {
tokio::task::block_in_place(|| {
handle.block_on(async {
let center_chunk = Vector2::new(
approximate_exit_pos.0.x >> 4,
approximate_exit_pos.0.z >> 4,
);
let new_portal = PortalSearchResult {
lower_corner: build_pos,
axis,
width: 2,
height: 3,
for dx in -1..=1 {
for dz in -1..=1 {
let chunk_pos =
Vector2::new(center_chunk.x + dx, center_chunk.y + dz);
dest_world
.level
.get_or_fetch_chunk(chunk_pos, |_| ())
.await;
}
}
});
});
}
if let Some((build_pos, axis, is_fallback)) = NetherPortal::find_safe_location(
&dest_world,
approximate_exit_pos,
source_portal_axis,
) {
NetherPortal::build_portal_frame(&dest_world, build_pos, axis, is_fallback);
Some(PortalSearchResult {
lower_corner: build_pos,
axis,
width: 2,
height: 3,
})
} else {
None
}
});
let (final_pos, yaw) = exit_portal.map_or_else(
|| (approximate_exit_pos.0.to_f64(), None),
|exit_portal| {
let relative_offset = source_portal.map_or_else(
|| Vector3::new(0.5, 0.0, 0.0),
|source| {
let source_result = PortalSearchResult {
lower_corner: source.lower_corner,
axis: source.axis,
width: source.width,
height: source.height,
};
let center_pos = new_portal.get_teleport_position();
let final_pos = new_portal.find_open_position(
&dest_world,
center_pos,
&dimensions,
);
let yaw =
new_portal.calculate_teleport_yaw(current_yaw, source_axis);
(final_pos, Some(yaw))
} else {
(target_pos.0.to_f64(), None)
}
},
|dest_result| {
let base_pos = source_portal.map_or_else(
|| dest_result.get_teleport_position(),
|source| {
let source_result = PortalSearchResult {
lower_corner: source.lower_corner,
axis: source.axis,
width: source.width,
height: source.height,
};
let relative_pos =
source_result.entity_pos_in_portal(pos, &dimensions);
dest_result.calculate_exit_position(relative_pos, &dimensions)
},
);
let final_pos =
dest_result.find_open_position(&dest_world, base_pos, &dimensions);
let yaw = dest_result.calculate_teleport_yaw(current_yaw, source_axis);
(final_pos, Some(yaw))
},
);
source_result.entity_pos_in_portal(pos, &dimensions)
},
);
let target_pos =
exit_portal.calculate_exit_position(relative_offset, &dimensions);
let collision_free_pos =
exit_portal.find_open_position(&dest_world, target_pos, &dimensions);
let yaw = exit_portal
.calculate_teleport_yaw(current_yaw, source_portal.map(|p| p.axis));
(collision_free_pos, Some(yaw))
},
);
Some(TeleportTransition {
new_world: dest_world,

View File

@ -153,6 +153,11 @@ impl PortalSearchResult {
let half_height = f64::from(dimensions.height) / 2.0;
let check_pos = Vector3::new(fallback.x, fallback.y + half_height, fallback.z);
if Self::is_position_clear(world, check_pos, dimensions) {
return fallback;
}
let search_radius = 1.0;
let step = 0.5;
@ -311,18 +316,32 @@ impl NetherPortal {
}
pub fn get_on_axis(world: &World, pos: &BlockPos, axis: HorizontalAxis) -> Option<Self> {
let (block, state) = world.get_block_and_state(pos);
if block == &Block::NETHER_PORTAL {
let props = NetherPortalLikeProperties::from_state_id(state.id, block);
if props.axis != axis {
return None;
}
}
let direction = if axis == HorizontalAxis::X {
BlockDirection::West
BlockDirection::East
} else {
BlockDirection::South
};
let cornor = Self::get_lower_cornor(world, direction, pos)?;
let width = Self::get_width(world, &cornor, direction);
let cornor = Self::get_lower_cornor(world, direction, pos, axis)?;
let width = Self::get_width(world, &cornor, direction, axis);
if !(Self::MIN_WIDTH..=Self::MAX_WIDTH).contains(&width) {
return None;
}
let mut found_portal_blocks = 0;
let height = Self::get_height(world, &cornor, direction, width, &mut found_portal_blocks)?;
let height = Self::get_height(
world,
&cornor,
direction,
width,
&mut found_portal_blocks,
axis,
)?;
Some(Self {
axis,
found_portal_blocks,
@ -337,18 +356,19 @@ impl NetherPortal {
world: &World,
direction: BlockDirection,
pos: &BlockPos,
axis: HorizontalAxis,
) -> Option<BlockPos> {
let limit_y = pos.0.y - Self::MAX_HEIGHT as i32;
let mut pos = *pos;
while pos.0.y > limit_y {
let (block, state) = world.get_block_and_state(&pos.down());
if !Self::valid_state_inside_portal(block, state) {
if !Self::valid_state_inside_portal(block, state, axis) {
break;
}
pos = pos.down();
}
let neg_dir = direction.opposite();
let width = (Self::get_width(world, &pos, neg_dir) as i32) - 1;
let width = (Self::get_width(world, &pos, neg_dir, axis) as i32) - 1;
if width < 0 {
return None;
}
@ -359,12 +379,13 @@ impl NetherPortal {
world: &World,
original_lower_corner: &BlockPos,
negative_dir: BlockDirection,
axis: HorizontalAxis,
) -> u32 {
let mut lower_corner;
for i in 0..=Self::MAX_WIDTH {
lower_corner = original_lower_corner.offset_dir(negative_dir.to_offset(), i as i32);
let (block, block_state) = world.get_block_and_state(&lower_corner);
if !Self::valid_state_inside_portal(block, block_state) {
if !Self::valid_state_inside_portal(block, block_state, axis) {
if &Self::FRAME_BLOCK != block {
break;
}
@ -384,6 +405,7 @@ impl NetherPortal {
negative_dir: BlockDirection,
width: u32,
found_portal_blocks: &mut u32,
axis: HorizontalAxis,
) -> Option<u32> {
let height = Self::get_potential_height(
world,
@ -391,6 +413,7 @@ impl NetherPortal {
negative_dir,
width,
found_portal_blocks,
axis,
);
if !(Self::MIN_HEIGHT..=Self::MAX_HEIGHT).contains(&height)
|| !Self::is_horizontal_frame_valid(world, lower_corner, negative_dir, width, height)
@ -406,6 +429,7 @@ impl NetherPortal {
negative_dir: BlockDirection,
width: u32,
found_portal_blocks: &mut u32,
axis: HorizontalAxis,
) -> u32 {
for i in 0..Self::MAX_HEIGHT as i32 {
let mut pos = lower_corner
@ -427,7 +451,7 @@ impl NetherPortal {
.offset_dir(BlockDirection::Up.to_offset(), i)
.offset_dir(negative_dir.to_offset(), j as i32);
let (block, block_state) = world.get_block_and_state(&pos);
if !Self::valid_state_inside_portal(block, block_state) {
if !Self::valid_state_inside_portal(block, block_state, axis) {
return i as u32;
}
if block == &Block::NETHER_PORTAL {
@ -457,10 +481,13 @@ impl NetherPortal {
true
}
fn valid_state_inside_portal(block: &Block, state: &BlockState) -> bool {
state.is_air()
|| block.has_tag(&tag::Block::MINECRAFT_FIRE)
|| block == &Block::NETHER_PORTAL
fn valid_state_inside_portal(block: &Block, state: &BlockState, axis: HorizontalAxis) -> bool {
if block == &Block::NETHER_PORTAL {
let props = NetherPortalLikeProperties::from_state_id(state.id, block);
props.axis == axis
} else {
state.is_air() || block.has_tag(&tag::Block::MINECRAFT_FIRE)
}
}
pub fn search_for_portal(
@ -510,39 +537,39 @@ impl NetherPortal {
continue;
}
if world.get_block_state_id(&pos).to_block() != &Block::NETHER_PORTAL {
let (block, state) = world.get_block_and_state(&pos);
if block != &Block::NETHER_PORTAL {
continue;
}
let props = NetherPortalLikeProperties::from_state_id(state.id, block);
let axis = props.axis;
for axis in [HorizontalAxis::X, HorizontalAxis::Z] {
if let Some(portal) = Self::get_on_axis(world, &pos, axis)
&& portal.was_already_valid()
{
// Use POI position for distance calculation (matches vanilla behavior)
let dist =
f64::from(target_pos.0.squared_distance_to(pos.0.x, pos.0.y, pos.0.z));
let y = portal.lower_conor.0.y;
if let Some(portal) = Self::get_on_axis(world, &pos, axis)
&& portal.was_already_valid()
{
// Use POI position for distance calculation (matches vanilla behavior)
let dist = f64::from(target_pos.0.squared_distance_to(pos.0.x, pos.0.y, pos.0.z));
let y = portal.lower_conor.0.y;
let is_better = match &best {
None => true,
Some((_, best_dist, best_y)) => {
dist < *best_dist
|| ((dist - *best_dist).abs() < f64::EPSILON && y < *best_y)
}
};
if is_better {
best = Some((
PortalSearchResult {
lower_corner: portal.lower_conor,
axis: portal.axis,
width: portal.width,
height: portal.height,
},
dist,
y,
));
let is_better = match &best {
None => true,
Some((_, best_dist, best_y)) => {
dist < *best_dist
|| ((dist - *best_dist).abs() < f64::EPSILON && y < *best_y)
}
};
if is_better {
best = Some((
PortalSearchResult {
lower_corner: portal.lower_conor,
axis: portal.axis,
width: portal.width,
height: portal.height,
},
dist,
y,
));
}
}
}
@ -802,3 +829,133 @@ impl NetherPortal {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use pumpkin_util::math::boundingbox::EntityDimensions;
#[test]
fn portal_teleport_position_x_axis() {
let portal = PortalSearchResult {
lower_corner: BlockPos::new(10, 64, 5),
axis: HorizontalAxis::X,
width: 2,
height: 3,
};
let pos = portal.get_teleport_position();
// Width is 2 along X, so center X is 10 + 1.0 = 11.0, Y is 64.0, Z is 5.5
assert_eq!(pos, Vector3::new(11.0, 64.0, 5.5));
}
#[test]
fn portal_teleport_position_z_axis() {
let portal = PortalSearchResult {
lower_corner: BlockPos::new(5, 64, 10),
axis: HorizontalAxis::Z,
width: 2,
height: 3,
};
let pos = portal.get_teleport_position();
// Width is 2 along Z, so center X is 5.5, Y is 64.0, Z is 10 + 1.0 = 11.0
assert_eq!(pos, Vector3::new(5.5, 64.0, 11.0));
}
#[test]
fn portal_relative_exit_position() {
let src_portal = PortalSearchResult {
lower_corner: BlockPos::new(100, 64, 200),
axis: HorizontalAxis::X,
width: 2,
height: 3,
};
let dest_portal = PortalSearchResult {
lower_corner: BlockPos::new(12, 70, 25),
axis: HorizontalAxis::X,
width: 2,
height: 3,
};
let dimensions = EntityDimensions {
width: 0.6,
height: 1.8,
eye_height: 1.62,
};
// Player is at the center of the source portal
let player_pos = src_portal.get_teleport_position();
let rel_pos = src_portal.entity_pos_in_portal(player_pos, &dimensions);
let exit_pos = dest_portal.calculate_exit_position(rel_pos, &dimensions);
// Should exit near the center of the destination portal
assert!((exit_pos.x - 13.0).abs() < 0.01);
assert!((exit_pos.y - 70.0).abs() < 0.01);
assert!((exit_pos.z - 25.5).abs() < 0.01);
}
#[test]
fn portal_cross_axis_x_to_z() {
let src_portal = PortalSearchResult {
lower_corner: BlockPos::new(100, 64, 200),
axis: HorizontalAxis::X,
width: 2,
height: 3,
};
let dest_portal = PortalSearchResult {
lower_corner: BlockPos::new(12, 70, 25),
axis: HorizontalAxis::Z,
width: 2,
height: 3,
};
let dimensions = EntityDimensions {
width: 0.6,
height: 1.8,
eye_height: 1.62,
};
// Player is at the center of the source X portal
let player_pos = src_portal.get_teleport_position();
let rel_pos = src_portal.entity_pos_in_portal(player_pos, &dimensions);
let exit_pos = dest_portal.calculate_exit_position(rel_pos, &dimensions);
// In Z portal: X is perpendicular (12 + 0.5 = 12.5), Z is along portal (25 + 1.0 = 26.0)
assert!((exit_pos.x - 12.5).abs() < 0.01);
assert!((exit_pos.y - 70.0).abs() < 0.01);
assert!((exit_pos.z - 26.0).abs() < 0.01);
}
#[test]
fn portal_yaw_rotation() {
let x_portal = PortalSearchResult {
lower_corner: BlockPos::new(0, 64, 0),
axis: HorizontalAxis::X,
width: 2,
height: 3,
};
let z_portal = PortalSearchResult {
lower_corner: BlockPos::new(0, 64, 0),
axis: HorizontalAxis::Z,
width: 2,
height: 3,
};
// Same axis -> no rotation
assert_eq!(
x_portal.calculate_teleport_yaw(45.0, Some(HorizontalAxis::X)),
45.0
);
assert_eq!(
z_portal.calculate_teleport_yaw(45.0, Some(HorizontalAxis::Z)),
45.0
);
// Cross axis -> 90 degree rotation
assert_eq!(
z_portal.calculate_teleport_yaw(45.0, Some(HorizontalAxis::X)),
135.0
);
assert_eq!(
x_portal.calculate_teleport_yaw(45.0, Some(HorizontalAxis::Z)),
-45.0
);
}
}

View File

@ -691,6 +691,13 @@ pub fn value_to_configured_feature(v: &Value) -> TokenStream {
"minecraft:end_platform" => {
quote! { ConfiguredFeature::EndPlatform(crate::generation::feature::features::end_platform::EndPlatformFeature) }
}
"minecraft:end_podium" => {
let active = config
.get("active")
.and_then(|v| v.as_bool())
.unwrap_or(false);
quote! { ConfiguredFeature::EndPodium(crate::generation::feature::features::end_podium::EndPodiumFeature::new(#active)) }
}
"minecraft:end_island" => {
quote! { ConfiguredFeature::EndIsland(crate::generation::feature::features::end_island::EndIslandFeature {}) }
}
@ -809,7 +816,21 @@ pub fn value_to_configured_feature(v: &Value) -> TokenStream {
quote! { ConfiguredFeature::BlueIce(crate::generation::feature::features::blue_ice::BlueIceFeature {}) }
}
"minecraft:end_gateway" => {
quote! { ConfiguredFeature::EndGateway(crate::generation::feature::features::end_gateway::EndGatewayFeature {}) }
let exit = if let Some(exit_arr) = config["exit"].as_array() {
let x = exit_arr[0].as_i64().unwrap_or(0) as i32;
let y = exit_arr[1].as_i64().unwrap_or(0) as i32;
let z = exit_arr[2].as_i64().unwrap_or(0) as i32;
quote! { Some(pumpkin_util::math::position::BlockPos::new(#x, #y, #z)) }
} else {
quote! { None }
};
let exact = config["exact"].as_bool().unwrap_or(false);
quote! {
ConfiguredFeature::EndGateway(crate::generation::feature::features::end_gateway::EndGatewayFeature {
exit: #exit,
exact: #exact,
})
}
}
"minecraft:coral_tree" => {
quote! { ConfiguredFeature::CoralTree(crate::generation::feature::features::coral::coral_tree::CoralTreeFeature) }