feat(bedrock): implement Bedrock status effect packet and translation
This commit is contained in:
parent
be279fa274
commit
f49e29aa3f
@ -419,6 +419,25 @@ impl StatusEffect {
|
|||||||
attribute_modifiers: &[],
|
attribute_modifiers: &[],
|
||||||
};
|
};
|
||||||
#[must_use]
|
#[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> {
|
pub fn from_name(name: &str) -> Option<&'static Self> {
|
||||||
match name {
|
match name {
|
||||||
"absorption" => Some(&Self::ABSORPTION),
|
"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 item_stack_response;
|
||||||
pub mod level_chunk;
|
pub mod level_chunk;
|
||||||
pub mod level_event;
|
pub mod level_event;
|
||||||
|
pub mod mob_effect;
|
||||||
pub mod mob_equipment;
|
pub mod mob_equipment;
|
||||||
pub mod modal_form_request;
|
pub mod modal_form_request;
|
||||||
pub mod move_actor_absolute;
|
pub mod move_actor_absolute;
|
||||||
@ -76,6 +77,7 @@ pub use item_stack_response::*;
|
|||||||
pub use level_chunk::*;
|
pub use level_chunk::*;
|
||||||
pub use level_event::*;
|
pub use level_event::*;
|
||||||
pub use level_sound_event::*;
|
pub use level_sound_event::*;
|
||||||
|
pub use mob_effect::*;
|
||||||
pub use mob_equipment::*;
|
pub use mob_equipment::*;
|
||||||
pub use modal_form_request::*;
|
pub use modal_form_request::*;
|
||||||
pub use move_actor_absolute::*;
|
pub use move_actor_absolute::*;
|
||||||
|
|||||||
@ -527,6 +527,7 @@ impl LivingEntity {
|
|||||||
self.entity.entity_id
|
self.entity.entity_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::too_many_lines)]
|
||||||
pub async fn add_effect(&self, effect: Effect) {
|
pub async fn add_effect(&self, effect: Effect) {
|
||||||
// Apply instant effects immediately before storing
|
// Apply instant effects immediately before storing
|
||||||
if effect.effect_type == &StatusEffect::INSTANT_HEALTH {
|
if effect.effect_type == &StatusEffect::INSTANT_HEALTH {
|
||||||
@ -625,7 +626,7 @@ impl LivingEntity {
|
|||||||
flag |= 8;
|
flag |= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
let packet = CUpdateMobEffect::new(
|
let je_packet = CUpdateMobEffect::new(
|
||||||
self.entity.entity_id.into(),
|
self.entity.entity_id.into(),
|
||||||
VarInt(i32::from(effect.effect_type.id)),
|
VarInt(i32::from(effect.effect_type.id)),
|
||||||
effect.amplifier.into(),
|
effect.amplifier.into(),
|
||||||
@ -633,7 +634,22 @@ impl LivingEntity {
|
|||||||
flag,
|
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 {
|
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) {
|
pub fn send_remove_mob_effect(&self, entity: &Entity, effect_type: &'static StatusEffect) {
|
||||||
let chunk_pos = entity.chunk_pos.load();
|
let chunk_pos = entity.chunk_pos.load();
|
||||||
self.broadcast_to_chunk(
|
let je_packet =
|
||||||
chunk_pos,
|
CRemoveMobEffect::new(entity.entity_id.into(), VarInt(i32::from(effect_type.id)));
|
||||||
&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) {
|
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;
|
let mut flags: i8 = 0;
|
||||||
if effect.ambient {
|
if effect.ambient {
|
||||||
flags |= 0x01;
|
flags |= 0x01;
|
||||||
@ -485,13 +494,25 @@ impl World {
|
|||||||
flags |= 0x04;
|
flags |= 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.broadcast_packet_all(&CUpdateMobEffect::new(
|
let je_packet = CUpdateMobEffect::new(
|
||||||
VarInt(entity.entity_id),
|
VarInt(entity.entity_id),
|
||||||
VarInt(i32::from(effect.effect_type.id)),
|
VarInt(i32::from(effect.effect_type.id)),
|
||||||
VarInt(i32::from(effect.amplifier)),
|
VarInt(i32::from(effect.amplifier)),
|
||||||
VarInt(effect.duration),
|
VarInt(effect.duration),
|
||||||
flags,
|
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) {
|
pub fn set_difficulty(&self, difficulty: Difficulty) {
|
||||||
|
|||||||
@ -157,6 +157,26 @@ pub fn build() -> TokenStream {
|
|||||||
impl StatusEffect {
|
impl StatusEffect {
|
||||||
#variants
|
#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]
|
#[must_use]
|
||||||
pub fn from_name(name: &str) -> Option<&'static Self> {
|
pub fn from_name(name: &str) -> Option<&'static Self> {
|
||||||
match name {
|
match name {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user