fix: bedrock SActorEvent packet

This commit is contained in:
Alexander Medvedev 2026-06-28 13:26:32 +02:00
parent 28e8187f23
commit 8c5d6dc405
19 changed files with 100 additions and 103 deletions

View File

@ -1,4 +1,4 @@
use crate::serial::PacketWrite; use crate::{codec::var_long::VarLong, serial::PacketWrite};
use std::io::{Error, Write}; use std::io::{Error, Write};
use pumpkin_macros::packet; use pumpkin_macros::packet;
@ -9,7 +9,7 @@ use crate::codec::var_int::VarInt;
#[derive(Debug, PacketWrite)] #[derive(Debug, PacketWrite)]
#[packet(27)] #[packet(27)]
pub struct SActorEvent { pub struct SActorEvent {
pub entity_runtime_id: VarInt, pub entity_runtime_id: VarLong,
pub event_type: ActorEventType, pub event_type: ActorEventType,
pub event_data: VarInt, pub event_data: VarInt,
pub fire_at_position: Option<Vector3<f32>>, pub fire_at_position: Option<Vector3<f32>>,

View File

@ -5,19 +5,19 @@ use crate::{
codec::var_int::VarInt, codec::var_int::VarInt,
ser::{NetworkWriteExt, WritingError}, ser::{NetworkWriteExt, WritingError},
}; };
use pumpkin_data::packet::clientbound::CONFIG_REGISTRY_DATA; use pumpkin_data::{packet::clientbound::CONFIG_REGISTRY_DATA, registry::RegistryEntryData};
use pumpkin_macros::java_packet; use pumpkin_macros::java_packet;
use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion}; use pumpkin_util::{resource_location::ResourceLocation, version::JavaMinecraftVersion};
#[java_packet(CONFIG_REGISTRY_DATA)] #[java_packet(CONFIG_REGISTRY_DATA)]
pub struct CRegistryData<'a> { pub struct CRegistryData<'a> {
pub registry_id: &'a ResourceLocation, pub registry_id: &'a ResourceLocation,
pub entries: &'a [RegistryEntry], pub entries: &'a [RegistryEntryData],
} }
impl<'a> CRegistryData<'a> { impl<'a> CRegistryData<'a> {
#[must_use] #[must_use]
pub const fn new(registry_id: &'a ResourceLocation, entries: &'a [RegistryEntry]) -> Self { pub const fn new(registry_id: &'a ResourceLocation, entries: &'a [RegistryEntryData]) -> Self {
Self { Self {
registry_id, registry_id,
entries, entries,
@ -25,18 +25,6 @@ impl<'a> CRegistryData<'a> {
} }
} }
pub struct RegistryEntry {
pub entry_id: ResourceLocation,
pub data: Option<Box<[u8]>>,
}
impl RegistryEntry {
#[must_use]
pub const fn new(entry_id: ResourceLocation, data: Option<Box<[u8]>>) -> Self {
Self { entry_id, data }
}
}
impl ClientPacket for CRegistryData<'_> { impl ClientPacket for CRegistryData<'_> {
fn write_packet_data( fn write_packet_data(
&self, &self,

View File

@ -15,22 +15,28 @@ impl Pool {
/// ///
/// # Returns /// # Returns
/// An `Option<E>` representing the selected element, or `None` if the distribution is empty. /// An `Option<E>` representing the selected element, or `None` if the distribution is empty.
pub fn get<E: Clone>(distribution: &[Weighted<E>], random: &mut RandomGenerator) -> Option<E> { pub fn get<'a, E>(
distribution: &'a [Weighted<E>],
random: &mut RandomGenerator,
) -> Option<&'a E> {
let mut total_weight = 0; let mut total_weight = 0;
for dist in distribution { for dist in distribution {
total_weight += dist.weight; total_weight += dist.weight;
} }
let mut index = random.next_bounded_i32(total_weight); let mut index = random.next_bounded_i32(total_weight);
if total_weight < 64 { if total_weight < 64 {
return Some(FlattenedContent::get(index, distribution, total_weight)); return Some(FlattenedContent::get(index, distribution, total_weight));
} }
// WrappedContent // WrappedContent
for dist in distribution { for dist in distribution {
index -= dist.weight; index -= dist.weight;
if index >= 0 { if index >= 0 {
continue; continue;
} }
return Some(dist.data.clone()); return Some(&dist.data);
} }
None None
} }
@ -58,16 +64,17 @@ impl FlattenedContent {
/// ///
/// # Returns /// # Returns
/// The element corresponding to the given index. /// The element corresponding to the given index.
pub fn get<E: Clone>(index: i32, entries: &[Weighted<E>], total_weight: i32) -> E { pub fn get<E>(index: i32, entries: &[Weighted<E>], _total_weight: i32) -> &E {
let mut final_entries = Vec::with_capacity(total_weight as usize);
let mut cur_index = 0; let mut cur_index = 0;
for entry in entries { for entry in entries {
let weight = entry.weight; let weight = entry.weight;
for i in cur_index..cur_index + weight { if index >= cur_index && index < cur_index + weight {
final_entries.insert(i as usize, entry.data.clone()); return &entry.data;
} }
cur_index += weight; cur_index += weight;
} }
final_entries[index as usize].clone()
&entries[0].data
} }
} }

View File

@ -21,11 +21,10 @@ fn main() {
for (pool_id, elements) in pools { for (pool_id, elements) in pools {
pool_code.push_str(&format!( pool_code.push_str(&format!(
" \"minecraft:{}\" | \"{}\" => Some(&[\n", " \"minecraft:{pool_id}\" | \"{pool_id}\" => Some(&[\n"
pool_id, pool_id
)); ));
for element in elements { for element in elements {
pool_code.push_str(&format!(" \"{}\",\n", element)); pool_code.push_str(&format!(" \"{element}\",\n"));
} }
pool_code.push_str(" ]),\n"); pool_code.push_str(" ]),\n");
} }
@ -37,7 +36,7 @@ fn main() {
pool_code.push_str(" _ => None,\n"); pool_code.push_str(" _ => None,\n");
pool_code.push_str(" }\n}\n"); pool_code.push_str(" }\n}\n");
fs::write(&dest_path, format!("{}\n{}", code, pool_code)).unwrap(); fs::write(&dest_path, format!("{code}\n{pool_code}")).unwrap();
println!("cargo:rerun-if-changed=assets/structures"); println!("cargo:rerun-if-changed=assets/structures");
} }
@ -56,7 +55,7 @@ fn process_dir(
let new_prefix = if prefix.is_empty() { let new_prefix = if prefix.is_empty() {
name name
} else { } else {
format!("{}/{}", prefix, name) format!("{prefix}/{name}")
}; };
process_dir(&path, &new_prefix, code, pools); process_dir(&path, &new_prefix, code, pools);
} else if name.ends_with(".nbt") { } else if name.ends_with(".nbt") {

View File

@ -11,19 +11,19 @@ impl RawBlockState {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn to_state(&self) -> &'static BlockState { pub const fn to_state(&self) -> &'static BlockState {
BlockState::from_id(self.0) BlockState::from_id(self.0)
} }
#[inline] #[inline]
#[must_use] #[must_use]
pub fn to_block(&self) -> &'static Block { pub const fn to_block(&self) -> &'static Block {
Block::from_state_id(self.0) Block::from_state_id(self.0)
} }
#[inline] #[inline]
#[must_use] #[must_use]
pub fn to_block_id(&self) -> u16 { pub const fn to_block_id(&self) -> u16 {
Block::get_raw_id_from_state_id(self.0) Block::get_raw_id_from_state_id(self.0)
} }
} }

View File

@ -161,7 +161,7 @@ pub struct ChunkNoiseFunctionBuilderOptions {
impl ChunkNoiseFunctionBuilderOptions { impl ChunkNoiseFunctionBuilderOptions {
#[must_use] #[must_use]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub const fn new(
horizontal_cell_block_count: usize, horizontal_cell_block_count: usize,
vertical_cell_block_count: usize, vertical_cell_block_count: usize,
vertical_cell_count: usize, vertical_cell_count: usize,

View File

@ -114,7 +114,7 @@ pub struct Beardifier {
} }
impl Beardifier { impl Beardifier {
pub fn new( pub const fn new(
structures: Vec<BeardifierStructure>, structures: Vec<BeardifierStructure>,
junctions: Vec<BeardifierJunction>, junctions: Vec<BeardifierJunction>,
affected_box: Option<BlockBox>, affected_box: Option<BlockBox>,

View File

@ -34,17 +34,17 @@ impl FindTopSurface {
} }
#[must_use] #[must_use]
pub fn density_index(&self) -> usize { pub const fn density_index(&self) -> usize {
self.density_index self.density_index
} }
#[must_use] #[must_use]
pub fn upper_bound_index(&self) -> usize { pub const fn upper_bound_index(&self) -> usize {
self.upper_bound_index self.upper_bound_index
} }
#[must_use] #[must_use]
pub fn cell_height(&self) -> i32 { pub const fn cell_height(&self) -> i32 {
self.data.cell_height self.data.cell_height
} }
} }

View File

@ -458,7 +458,7 @@ impl ProtoNoiseRouters {
} => { } => {
let mut min_value = f64::INFINITY; let mut min_value = f64::INFINITY;
let mut max_value = f64::NEG_INFINITY; let mut max_value = f64::NEG_INFINITY;
for &idx in functions_indices.iter() { for &idx in *functions_indices {
let min = stack[idx].min(); let min = stack[idx].min();
let max = stack[idx].max(); let max = stack[idx].max();
if min < min_value { if min < min_value {

View File

@ -348,7 +348,7 @@ impl ProtoChunk {
} }
#[must_use] #[must_use]
pub fn get_top_y(&self, heightmap: &HeightMap, x: i32, z: i32) -> i32 { pub const fn get_top_y(&self, heightmap: &HeightMap, x: i32, z: i32) -> i32 {
match heightmap { match heightmap {
HeightMap::WorldSurfaceWg => self.top_block_height_exclusive(x, z), HeightMap::WorldSurfaceWg => self.top_block_height_exclusive(x, z),
HeightMap::WorldSurface => self.top_block_height_exclusive(x, z), HeightMap::WorldSurface => self.top_block_height_exclusive(x, z),
@ -395,7 +395,7 @@ impl ProtoChunk {
} }
#[inline] #[inline]
fn local_pos_to_block_index(&self, x: i32, y: i32, z: i32) -> usize { const fn local_pos_to_block_index(&self, x: i32, y: i32, z: i32) -> usize {
self.height() as usize * CHUNK_DIM as usize * x as usize self.height() as usize * CHUNK_DIM as usize * x as usize
+ CHUNK_DIM as usize * y as usize + CHUNK_DIM as usize * y as usize
+ z as usize + z as usize
@ -403,7 +403,7 @@ impl ProtoChunk {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn local_biome_pos_to_biome_index(&self, x: i32, y: i32, z: i32) -> usize { pub const fn local_biome_pos_to_biome_index(&self, x: i32, y: i32, z: i32) -> usize {
let biome_height = self.height() as usize >> 2; let biome_height = self.height() as usize >> 2;
biome_height * biome_coords::from_block(CHUNK_DIM as i32) as usize * x as usize biome_height * biome_coords::from_block(CHUNK_DIM as i32) as usize * x as usize
+ biome_coords::from_block(CHUNK_DIM as i32) as usize * y as usize + biome_coords::from_block(CHUNK_DIM as i32) as usize * y as usize

View File

@ -150,7 +150,7 @@ impl StructurePieceBase for IglooPiece {
_block_registry: &dyn WorldPortalExt, _block_registry: &dyn WorldPortalExt,
_random: &mut RandomGenerator, _random: &mut RandomGenerator,
_seed: i64, _seed: i64,
_chunk_box: &BlockBox, chunk_box: &BlockBox,
) { ) {
let origin = self.shiftable_structure_piece.piece.bounding_box.min; let origin = self.shiftable_structure_piece.piece.bounding_box.min;
@ -179,7 +179,7 @@ impl StructurePieceBase for IglooPiece {
self.rotation, self.rotation,
false, false,
&[], &[],
Some(_chunk_box), Some(chunk_box),
); );
// Place basement components if present // Place basement components if present
@ -210,7 +210,7 @@ impl StructurePieceBase for IglooPiece {
self.rotation, self.rotation,
false, false,
&[], &[],
Some(_chunk_box), Some(chunk_box),
); );
} }
} }
@ -228,7 +228,7 @@ impl StructurePieceBase for IglooPiece {
self.rotation, self.rotation,
false, false,
&[], &[],
Some(_chunk_box), Some(chunk_box),
); );
} }
} }

View File

@ -51,6 +51,7 @@ impl TemplatePool {
} }
/// Discovers a pool from the filesystem/embedded assets. /// Discovers a pool from the filesystem/embedded assets.
#[must_use]
pub fn discover(id: &str) -> Option<Self> { pub fn discover(id: &str) -> Option<Self> {
let elements = crate::generation::structure::template::get_pool_elements(id)?; let elements = crate::generation::structure::template::get_pool_elements(id)?;
@ -84,6 +85,7 @@ pub enum JigsawJointType {
impl JigsawJointType { impl JigsawJointType {
#[allow(clippy::should_implement_trait)] #[allow(clippy::should_implement_trait)]
#[must_use]
pub fn from_str(s: &str) -> Self { pub fn from_str(s: &str) -> Self {
match s { match s {
"aligned" => Self::Aligned, "aligned" => Self::Aligned,
@ -107,6 +109,7 @@ pub struct JigsawBlock {
} }
impl JigsawBlock { impl JigsawBlock {
#[must_use]
pub fn from_template_block( pub fn from_template_block(
block: &crate::generation::structure::template::TemplateBlock, block: &crate::generation::structure::template::TemplateBlock,
palette: &PaletteEntry, palette: &PaletteEntry,
@ -122,8 +125,7 @@ impl JigsawBlock {
.properties .properties
.iter() .iter()
.find(|(k, _)| *k == "orientation") .find(|(k, _)| *k == "orientation")
.map(|(_, v)| v.clone()) .map_or_else(|| "north_up".to_string(), |(_, v)| v.clone());
.unwrap_or_else(|| "north_up".to_string());
let mut parts = facing_str.split('_'); let mut parts = facing_str.split('_');
let facing_part = parts.next().unwrap_or("north"); let facing_part = parts.next().unwrap_or("north");
@ -166,6 +168,7 @@ impl JigsawBlock {
}) })
} }
#[must_use]
pub fn can_attach( pub fn can_attach(
source: &Self, source: &Self,
target_facing: pumpkin_util::BlockDirection, target_facing: pumpkin_util::BlockDirection,
@ -217,7 +220,7 @@ impl StructurePieceBase for PoolElementStructurePiece {
_block_registry: &dyn crate::world::WorldPortalExt, _block_registry: &dyn crate::world::WorldPortalExt,
_random: &mut pumpkin_util::random::RandomGenerator, _random: &mut pumpkin_util::random::RandomGenerator,
_seed: i64, _seed: i64,
_chunk_box: &pumpkin_util::math::block_box::BlockBox, chunk_box: &pumpkin_util::math::block_box::BlockBox,
) { ) {
let origin = let origin =
pumpkin_util::math::vector3::Vector3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z); pumpkin_util::math::vector3::Vector3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z);
@ -238,7 +241,7 @@ impl StructurePieceBase for PoolElementStructurePiece {
self.rotation, self.rotation,
false, false,
&processors, &processors,
Some(_chunk_box), Some(chunk_box),
); );
// Post-process: replace jigsaw blocks with their final_state // Post-process: replace jigsaw blocks with their final_state
@ -246,12 +249,12 @@ impl StructurePieceBase for PoolElementStructurePiece {
let wx = jigsaw.pos.0.x; let wx = jigsaw.pos.0.x;
let wy = jigsaw.pos.0.y; let wy = jigsaw.pos.0.y;
let wz = jigsaw.pos.0.z; let wz = jigsaw.pos.0.z;
if wx < _chunk_box.min.x if wx < chunk_box.min.x
|| wx > _chunk_box.max.x || wx > chunk_box.max.x
|| wy < _chunk_box.min.y || wy < chunk_box.min.y
|| wy > _chunk_box.max.y || wy > chunk_box.max.y
|| wz < _chunk_box.min.z || wz < chunk_box.min.z
|| wz > _chunk_box.max.z || wz > chunk_box.max.z
{ {
continue; continue;
} }
@ -282,6 +285,7 @@ pub struct JigsawGenerator {
} }
impl JigsawGenerator { impl JigsawGenerator {
#[must_use]
pub fn new(start_pool: &str, size: i32) -> Self { pub fn new(start_pool: &str, size: i32) -> Self {
Self { Self {
start_pool: start_pool.to_string(), start_pool: start_pool.to_string(),
@ -291,12 +295,14 @@ impl JigsawGenerator {
} }
} }
#[must_use]
pub fn with_start_jigsaw(mut self, name: &str) -> Self { pub fn with_start_jigsaw(mut self, name: &str) -> Self {
self.start_jigsaw_name = Some(name.to_string()); self.start_jigsaw_name = Some(name.to_string());
self self
} }
pub fn with_expansion_hack(mut self, use_hack: bool) -> Self { #[must_use]
pub const fn with_expansion_hack(mut self, use_hack: bool) -> Self {
self.use_expansion_hack = use_hack; self.use_expansion_hack = use_hack;
self self
} }
@ -332,22 +338,22 @@ impl StructureGenerator for JigsawGenerator {
.and_then(|s| s.max_distance_from_center) .and_then(|s| s.max_distance_from_center)
.unwrap_or(80); // Vanilla default is 80 .unwrap_or(80); // Vanilla default is 80
let liquid_settings = structure let liquid_settings =
.and_then(|s| s.liquid_settings) structure
.map(|ls| match ls { .and_then(|s| s.liquid_settings)
"apply_waterlogging" => LiquidSettings::ApplyWaterlog, .map_or(LiquidSettings::ApplyWaterlog, |ls| match ls {
"ignore_waterlogging" => LiquidSettings::IgnoreWaterlogDone, "apply_waterlogging" => LiquidSettings::ApplyWaterlog,
_ => LiquidSettings::ApplyWaterlog, "ignore_waterlogging" => LiquidSettings::IgnoreWaterlogDone,
}) _ => LiquidSettings::ApplyWaterlog,
.unwrap_or(LiquidSettings::ApplyWaterlog); });
let dimension_padding = structure let dimension_padding =
.and_then(|s| s.dimension_padding) structure
.map(|dp| DimensionPadding { .and_then(|s| s.dimension_padding)
top: dp, .map_or(DimensionPadding::ZERO, |dp| DimensionPadding {
bottom: dp, top: dp,
}) bottom: dp,
.unwrap_or(DimensionPadding::ZERO); });
JigsawPlacement::add_pieces( JigsawPlacement::add_pieces(
&mut context, &mut context,

View File

@ -38,7 +38,8 @@ pub struct MaxDistance {
} }
impl MaxDistance { impl MaxDistance {
pub fn new(horizontal: i32) -> Self { #[must_use]
pub const fn new(horizontal: i32) -> Self {
Self { Self {
horizontal, horizontal,
vertical: 384, // Default Y_SIZE (min_y to max_y) vertical: 384, // Default Y_SIZE (min_y to max_y)
@ -54,7 +55,8 @@ pub const MAX_DEPTH: i32 = 20;
pub struct PoolAliasLookup; pub struct PoolAliasLookup;
impl PoolAliasLookup { impl PoolAliasLookup {
pub fn lookup<'a>(&self, id: &'a str) -> &'a str { #[must_use]
pub const fn lookup<'a>(&self, id: &'a str) -> &'a str {
// In a complete implementation, this would look up the alias in the context/registry. // In a complete implementation, this would look up the alias in the context/registry.
// Returning the ID directly acts as a fallback/default behavior. // Returning the ID directly acts as a fallback/default behavior.
id id
@ -121,8 +123,8 @@ impl JigsawPlacement {
adjusted_position.0.z + rotated_size.z - 1, adjusted_position.0.z + rotated_size.z - 1,
); );
let center_x = (box_.max.x + box_.min.x) / 2; let center_x = i32::midpoint(box_.max.x, box_.min.x);
let center_z = (box_.max.z + box_.min.z) / 2; let center_z = i32::midpoint(box_.max.z, box_.min.z);
let bottom_y = if project_start_to_heightmap { let bottom_y = if project_start_to_heightmap {
if let Some(sampler) = &mut context.height_sampler { if let Some(sampler) = &mut context.height_sampler {
@ -227,7 +229,7 @@ impl JigsawPlacement {
let source_projection = piece_projections[source_piece_idx]; let source_projection = piece_projections[source_piece_idx];
let source_rigid = source_projection == JigsawProjection::Rigid; let source_rigid = source_projection == JigsawProjection::Rigid;
'jigsaw_loop: for source_jigsaw in source_jigsaws.iter() { 'jigsaw_loop: for source_jigsaw in &source_jigsaws {
let raw_pool_id = &source_jigsaw.pool; let raw_pool_id = &source_jigsaw.pool;
if raw_pool_id == "minecraft:empty" || raw_pool_id.is_empty() { if raw_pool_id == "minecraft:empty" || raw_pool_id.is_empty() {
continue; continue;
@ -544,9 +546,8 @@ impl JigsawPlacement {
// Helper to determine the max Y height of a pool for the expansion hack // Helper to determine the max Y height of a pool for the expansion hack
fn get_pool_max_y_size(pool_id: &str) -> i32 { fn get_pool_max_y_size(pool_id: &str) -> i32 {
let pool = match TemplatePool::discover(pool_id) { let Some(pool) = TemplatePool::discover(pool_id) else {
Some(p) => p, return 0;
None => return 0,
}; };
let mut max_y = 0; let mut max_y = 0;
@ -561,7 +562,7 @@ fn get_pool_max_y_size(pool_id: &str) -> i32 {
max_y max_y
} }
fn is_box_inside(outer: &BlockBox, inner: &BlockBox) -> bool { const fn is_box_inside(outer: &BlockBox, inner: &BlockBox) -> bool {
inner.min.x >= outer.min.x inner.min.x >= outer.min.x
&& inner.max.x <= outer.max.x && inner.max.x <= outer.max.x
&& inner.min.y >= outer.min.y && inner.min.y >= outer.min.y
@ -570,7 +571,7 @@ fn is_box_inside(outer: &BlockBox, inner: &BlockBox) -> bool {
&& inner.max.z <= outer.max.z && inner.max.z <= outer.max.z
} }
fn intersects_exclusive(a: &BlockBox, b: &BlockBox) -> bool { const fn intersects_exclusive(a: &BlockBox, b: &BlockBox) -> bool {
// Strictly greater/less than checks perfectly emulate Vanilla's AABB deflate(0.25) // Strictly greater/less than checks perfectly emulate Vanilla's AABB deflate(0.25)
// by completely ignoring touching boundaries where coords are equal. // by completely ignoring touching boundaries where coords are equal.
a.max.x > b.min.x a.max.x > b.min.x
@ -649,7 +650,7 @@ fn can_attach(source: &JigsawBlock, target: &JigsawBlock, target_rotation: Rotat
true true
} }
fn rotate_direction( const fn rotate_direction(
dir: pumpkin_util::BlockDirection, dir: pumpkin_util::BlockDirection,
rotation: Rotation, rotation: Rotation,
) -> pumpkin_util::BlockDirection { ) -> pumpkin_util::BlockDirection {

View File

@ -73,7 +73,8 @@ impl PaletteEntry {
Self { name, properties } Self { name, properties }
} }
/// Parses a block state string (e.g. "minecraft:oak_log[axis=x]") into a palette entry. /// Parses a block state string (e.g. "`minecraft:oak_log`[axis=x]") into a palette entry.
#[must_use]
pub fn from_string(s: &str) -> Self { pub fn from_string(s: &str) -> Self {
if let Some(bracket_pos) = s.find('[') { if let Some(bracket_pos) = s.find('[') {
let name = s[..bracket_pos].to_string(); let name = s[..bracket_pos].to_string();

View File

@ -8,6 +8,7 @@ use pumpkin_inventory::player::player_inventory::PlayerInventory;
use pumpkin_inventory::screen_handler::InventoryPlayer; use pumpkin_inventory::screen_handler::InventoryPlayer;
use pumpkin_protocol::bedrock::client::take_item_actor::CTakeItemActor; use pumpkin_protocol::bedrock::client::take_item_actor::CTakeItemActor;
use pumpkin_protocol::bedrock::server::actor_event::{ActorEventType, SActorEvent}; use pumpkin_protocol::bedrock::server::actor_event::{ActorEventType, SActorEvent};
use pumpkin_protocol::codec::var_long::VarLong;
use pumpkin_protocol::codec::var_ulong::VarULong; use pumpkin_protocol::codec::var_ulong::VarULong;
use pumpkin_util::GameMode; use pumpkin_util::GameMode;
use pumpkin_util::Hand; use pumpkin_util::Hand;
@ -2172,7 +2173,7 @@ impl EntityBase for LivingEntity {
let config = &world.server.upgrade().unwrap().advanced_config.pvp; let config = &world.server.upgrade().unwrap().advanced_config.pvp;
if config.hurt_animation { if config.hurt_animation {
let entity_id = VarInt(self.entity.entity_id); let entity_id = self.entity.entity_id;
let hurt_yaw = source.map_or(0.0, |source| { let hurt_yaw = source.map_or(0.0, |source| {
let src = source.get_entity().pos.load(); let src = source.get_entity().pos.load();
let tgt = self.entity.pos.load(); let tgt = self.entity.pos.load();
@ -2180,13 +2181,16 @@ impl EntityBase for LivingEntity {
- self.entity.yaw.load() - self.entity.yaw.load()
}); });
let hurt_event = SActorEvent { let hurt_event = SActorEvent {
entity_runtime_id: entity_id, entity_runtime_id: VarLong(entity_id as i64),
event_type: ActorEventType::Hurt, event_type: ActorEventType::Hurt,
event_data: VarInt(0), event_data: VarInt(0),
fire_at_position: None, fire_at_position: None,
}; };
world world
.broadcast_editioned(&CHurtAnimation::new(entity_id, hurt_yaw), &hurt_event) .broadcast_editioned(
&CHurtAnimation::new(VarInt(entity_id), hurt_yaw),
&hurt_event,
)
.await; .await;
} }

View File

@ -16,7 +16,7 @@ use pumpkin_data::{registry::Registry, translation};
use pumpkin_protocol::{ use pumpkin_protocol::{
ConnectionState, ConnectionState,
java::{ java::{
client::config::{CFinishConfig, CRegistryData, CUpdateTags, RegistryEntry}, client::config::{CFinishConfig, CRegistryData, CUpdateTags},
server::config::{ server::config::{
ResourcePackResponseResult, SClientInformationConfig, SConfigCookieResponse, ResourcePackResponseResult, SClientInformationConfig, SConfigCookieResponse,
SConfigResourcePack, SKeepAlive, SKnownPacks, SPluginMessage, SConfigResourcePack, SKeepAlive, SKnownPacks, SPluginMessage,
@ -164,13 +164,11 @@ impl JavaClient {
let version = self.version.load(); let version = self.version.load();
let registry = Registry::get_synced(version); let registry = Registry::get_synced(version);
for registry in registry { for registry in registry {
let entries: Vec<RegistryEntry> = registry self.send_packet_now(&CRegistryData::new(
.registry_entries &registry.registry_id,
.iter() &registry.registry_entries,
.map(|r| RegistryEntry::new(r.entry_id.clone(), r.data.clone())) ))
.collect(); .await;
self.send_packet_now(&CRegistryData::new(&registry.registry_id, &entries))
.await;
// if let Some(tag) = RegistryKey::from_string(&registry.registry_id.path) // if let Some(tag) = RegistryKey::from_string(&registry.registry_id.path)
// && pumpkin_data::tag::get_registry_key_tags(self.version.load(), tag).is_some() // && pumpkin_data::tag::get_registry_key_tags(self.version.load(), tag).is_some()
// { // {

View File

@ -57,10 +57,7 @@ impl PluginLoader for NativePluginLoader {
} }
fn can_load(&self, path: &Path) -> bool { fn can_load(&self, path: &Path) -> bool {
let ext = path let ext = path.extension().unwrap_or_default();
.extension()
.and_then(|s| s.to_str())
.unwrap_or_default();
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
ext.eq_ignore_ascii_case("dll") ext.eq_ignore_ascii_case("dll")

View File

@ -47,10 +47,7 @@ impl PluginLoader for WasmPluginLoader {
} }
fn can_load(&self, path: &Path) -> bool { fn can_load(&self, path: &Path) -> bool {
let ext = path let ext = path.extension().unwrap_or_default();
.extension()
.and_then(|s| s.to_str())
.unwrap_or_default();
ext.eq_ignore_ascii_case("wasm") ext.eq_ignore_ascii_case("wasm")
} }

View File

@ -687,7 +687,6 @@ impl PluginManager {
if path if path
.extension() .extension()
.and_then(|ext| ext.to_str())
.is_some_and(|ext| ext.eq_ignore_ascii_case("deactivated")) .is_some_and(|ext| ext.eq_ignore_ascii_case("deactivated"))
{ {
continue; continue;