mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
feat(bedrock): implement Bedrock status effect packet and translation
This commit is contained in:
@@ -419,6 +419,25 @@ impl StatusEffect {
|
||||
attribute_modifiers: &[],
|
||||
};
|
||||
#[must_use]
|
||||
pub const fn to_bedrock_id(&self) -> i32 {
|
||||
match self.id {
|
||||
0..=22 => self.id as i32 + 1,
|
||||
24 => 24,
|
||||
27 => 27,
|
||||
28 => 26,
|
||||
30 => 28,
|
||||
31 => 29,
|
||||
32 => 30,
|
||||
33 => 31,
|
||||
34 => 32,
|
||||
35 => 33,
|
||||
36 => 34,
|
||||
37 => 35,
|
||||
38 => 36,
|
||||
_ => self.id as i32 + 1,
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn from_name(name: &str) -> Option<&'static Self> {
|
||||
match name {
|
||||
"absorption" => Some(&Self::ABSORPTION),
|
||||
|
||||
49
crates/pumpkin-protocol/src/bedrock/client/mob_effect.rs
Normal file
49
crates/pumpkin-protocol/src/bedrock/client/mob_effect.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use pumpkin_macros::packet;
|
||||
|
||||
use crate::{
|
||||
codec::{var_int::VarInt, var_ulong::VarULong},
|
||||
serial::PacketWrite,
|
||||
};
|
||||
|
||||
#[derive(PacketWrite)]
|
||||
#[packet(28)]
|
||||
pub struct CMobEffect {
|
||||
pub runtime_entity_id: VarULong,
|
||||
pub event_id: u8,
|
||||
pub effect_id: VarInt,
|
||||
pub amplifier: VarInt,
|
||||
pub particles: bool,
|
||||
pub duration: VarInt,
|
||||
pub tick: VarULong,
|
||||
pub ambient: bool,
|
||||
}
|
||||
|
||||
impl CMobEffect {
|
||||
pub const EVENT_ADD: u8 = 1;
|
||||
pub const EVENT_MODIFY: u8 = 2;
|
||||
pub const EVENT_REMOVE: u8 = 3;
|
||||
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
#[must_use]
|
||||
pub const fn new(
|
||||
runtime_entity_id: VarULong,
|
||||
event_id: u8,
|
||||
effect_id: VarInt,
|
||||
amplifier: VarInt,
|
||||
particles: bool,
|
||||
duration: VarInt,
|
||||
tick: VarULong,
|
||||
ambient: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
runtime_entity_id,
|
||||
event_id,
|
||||
effect_id,
|
||||
amplifier,
|
||||
particles,
|
||||
duration,
|
||||
tick,
|
||||
ambient,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ pub mod item_registry;
|
||||
pub mod item_stack_response;
|
||||
pub mod level_chunk;
|
||||
pub mod level_event;
|
||||
pub mod mob_effect;
|
||||
pub mod mob_equipment;
|
||||
pub mod modal_form_request;
|
||||
pub mod move_actor_absolute;
|
||||
@@ -76,6 +77,7 @@ pub use item_stack_response::*;
|
||||
pub use level_chunk::*;
|
||||
pub use level_event::*;
|
||||
pub use level_sound_event::*;
|
||||
pub use mob_effect::*;
|
||||
pub use mob_equipment::*;
|
||||
pub use modal_form_request::*;
|
||||
pub use move_actor_absolute::*;
|
||||
|
||||
@@ -527,6 +527,7 @@ impl LivingEntity {
|
||||
self.entity.entity_id
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
pub async fn add_effect(&self, effect: Effect) {
|
||||
// Apply instant effects immediately before storing
|
||||
if effect.effect_type == &StatusEffect::INSTANT_HEALTH {
|
||||
@@ -625,7 +626,7 @@ impl LivingEntity {
|
||||
flag |= 8;
|
||||
}
|
||||
|
||||
let packet = CUpdateMobEffect::new(
|
||||
let je_packet = CUpdateMobEffect::new(
|
||||
self.entity.entity_id.into(),
|
||||
VarInt(i32::from(effect.effect_type.id)),
|
||||
effect.amplifier.into(),
|
||||
@@ -633,7 +634,22 @@ impl LivingEntity {
|
||||
flag,
|
||||
);
|
||||
|
||||
self.entity.world.load().broadcast_packet_all(&packet);
|
||||
let be_packet = pumpkin_protocol::bedrock::client::CMobEffect::new(
|
||||
VarULong(self.entity.entity_id as u64),
|
||||
pumpkin_protocol::bedrock::client::CMobEffect::EVENT_ADD,
|
||||
VarInt(effect.effect_type.to_bedrock_id()),
|
||||
VarInt(i32::from(effect.amplifier)),
|
||||
effect.show_particles,
|
||||
VarInt(effect.duration),
|
||||
VarULong(0),
|
||||
effect.ambient,
|
||||
);
|
||||
|
||||
let chunk_pos = self.entity.chunk_pos.load();
|
||||
self.entity
|
||||
.world
|
||||
.load()
|
||||
.broadcast_to_chunk_editioned_sync(chunk_pos, &je_packet, &be_packet);
|
||||
}
|
||||
|
||||
pub async fn remove_effect(&self, effect_type: &'static StatusEffect) -> bool {
|
||||
|
||||
@@ -466,14 +466,23 @@ impl World {
|
||||
|
||||
pub fn send_remove_mob_effect(&self, entity: &Entity, effect_type: &'static StatusEffect) {
|
||||
let chunk_pos = entity.chunk_pos.load();
|
||||
self.broadcast_to_chunk(
|
||||
chunk_pos,
|
||||
&CRemoveMobEffect::new(entity.entity_id.into(), VarInt(i32::from(effect_type.id))),
|
||||
let je_packet =
|
||||
CRemoveMobEffect::new(entity.entity_id.into(), VarInt(i32::from(effect_type.id)));
|
||||
let be_packet = pumpkin_protocol::bedrock::client::CMobEffect::new(
|
||||
VarULong(entity.entity_id as u64),
|
||||
pumpkin_protocol::bedrock::client::CMobEffect::EVENT_REMOVE,
|
||||
VarInt(effect_type.to_bedrock_id()),
|
||||
VarInt(0),
|
||||
false,
|
||||
VarInt(0),
|
||||
VarULong(0),
|
||||
false,
|
||||
);
|
||||
self.broadcast_to_chunk_editioned_sync(chunk_pos, &je_packet, &be_packet);
|
||||
}
|
||||
|
||||
pub fn send_add_mob_effect(&self, entity: &Entity, effect: &pumpkin_data::potion::Effect) {
|
||||
// TODO: only nearby
|
||||
let chunk_pos = entity.chunk_pos.load();
|
||||
let mut flags: i8 = 0;
|
||||
if effect.ambient {
|
||||
flags |= 0x01;
|
||||
@@ -485,13 +494,25 @@ impl World {
|
||||
flags |= 0x04;
|
||||
}
|
||||
|
||||
self.broadcast_packet_all(&CUpdateMobEffect::new(
|
||||
let je_packet = CUpdateMobEffect::new(
|
||||
VarInt(entity.entity_id),
|
||||
VarInt(i32::from(effect.effect_type.id)),
|
||||
VarInt(i32::from(effect.amplifier)),
|
||||
VarInt(effect.duration),
|
||||
flags,
|
||||
));
|
||||
);
|
||||
let be_packet = pumpkin_protocol::bedrock::client::CMobEffect::new(
|
||||
VarULong(entity.entity_id as u64),
|
||||
pumpkin_protocol::bedrock::client::CMobEffect::EVENT_ADD,
|
||||
VarInt(effect.effect_type.to_bedrock_id()),
|
||||
VarInt(i32::from(effect.amplifier)),
|
||||
effect.show_particles,
|
||||
VarInt(effect.duration),
|
||||
VarULong(0),
|
||||
effect.ambient,
|
||||
);
|
||||
|
||||
self.broadcast_to_chunk_editioned_sync(chunk_pos, &je_packet, &be_packet);
|
||||
}
|
||||
|
||||
pub fn set_difficulty(&self, difficulty: Difficulty) {
|
||||
|
||||
@@ -157,6 +157,26 @@ pub fn build() -> TokenStream {
|
||||
impl StatusEffect {
|
||||
#variants
|
||||
|
||||
#[must_use]
|
||||
pub const fn to_bedrock_id(&self) -> i32 {
|
||||
match self.id {
|
||||
0..=22 => self.id as i32 + 1,
|
||||
24 => 24,
|
||||
27 => 27,
|
||||
28 => 26,
|
||||
30 => 28,
|
||||
31 => 29,
|
||||
32 => 30,
|
||||
33 => 31,
|
||||
34 => 32,
|
||||
35 => 33,
|
||||
36 => 34,
|
||||
37 => 35,
|
||||
38 => 36,
|
||||
_ => self.id as i32 + 1,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn from_name(name: &str) -> Option<&'static Self> {
|
||||
match name {
|
||||
|
||||
Reference in New Issue
Block a user