feat(bedrock): death animation
This commit is contained in:
parent
33e11088b2
commit
92658f5853
@ -15,7 +15,7 @@ pub struct SActorEvent {
|
|||||||
pub fire_at_position: Option<Vector3<f32>>,
|
pub fire_at_position: Option<Vector3<f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ActorEventType {
|
pub enum ActorEventType {
|
||||||
Jump = 1,
|
Jump = 1,
|
||||||
|
|||||||
@ -13,6 +13,8 @@ use crate::{
|
|||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::net::ClientPlatform;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum AttackType {
|
pub enum AttackType {
|
||||||
Knockback,
|
Knockback,
|
||||||
@ -38,6 +40,7 @@ impl AttackType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let sword = held_item.is_sword();
|
let sword = held_item.is_sword();
|
||||||
|
let is_bedrock = matches!(player.client.as_ref(), ClientPlatform::Bedrock(_));
|
||||||
|
|
||||||
let is_strong = attack_cooldown_progress > 0.9;
|
let is_strong = attack_cooldown_progress > 0.9;
|
||||||
if sprinting && is_strong {
|
if sprinting && is_strong {
|
||||||
@ -48,7 +51,7 @@ impl AttackType {
|
|||||||
return Self::Critical;
|
return Self::Critical;
|
||||||
}
|
}
|
||||||
|
|
||||||
if sword && is_strong {
|
if sword && is_strong && !is_bedrock {
|
||||||
return Self::Sweeping;
|
return Self::Sweeping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -411,7 +411,7 @@ impl EntityBase for ArmorStandEntity {
|
|||||||
let time = world.level_time.lock().await.query_gametime();
|
let time = world.level_time.lock().await.query_gametime();
|
||||||
|
|
||||||
if time - self.last_hit_time.load(Ordering::Relaxed) > 5 && !always_kills {
|
if time - self.last_hit_time.load(Ordering::Relaxed) > 5 && !always_kills {
|
||||||
world.send_entity_status(entity, EntityStatus::ArmorstandWobble);
|
world.send_entity_status(entity, EntityStatus::ArmorstandWobble, None);
|
||||||
world.play_sound(
|
world.play_sound(
|
||||||
Sound::EntityArmorStandHit,
|
Sound::EntityArmorStandHit,
|
||||||
SoundCategory::Neutral,
|
SoundCategory::Neutral,
|
||||||
|
|||||||
@ -279,7 +279,23 @@ impl LivingEntity {
|
|||||||
&& item.get_data_component::<BlocksAttacksImpl>().is_some()
|
&& item.get_data_component::<BlocksAttacksImpl>().is_some()
|
||||||
{
|
{
|
||||||
let use_time = self.item_use_time.load(Ordering::Relaxed);
|
let use_time = self.item_use_time.load(Ordering::Relaxed);
|
||||||
return item.get_max_use_time() - use_time >= 5;
|
let required_time = if let Some(dyn_self) = self
|
||||||
|
.entity
|
||||||
|
.world
|
||||||
|
.load()
|
||||||
|
.get_entity_by_id(self.entity.entity_id)
|
||||||
|
&& let Some(player) = dyn_self
|
||||||
|
.cast_any()
|
||||||
|
.downcast_ref::<crate::entity::player::Player>()
|
||||||
|
&& matches!(
|
||||||
|
player.client.as_ref(),
|
||||||
|
crate::net::ClientPlatform::Bedrock(_)
|
||||||
|
) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
5
|
||||||
|
};
|
||||||
|
return item.get_max_use_time() - use_time >= required_time;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -1355,7 +1371,11 @@ impl LivingEntity {
|
|||||||
self.update_death_stats(&*dyn_self, cause).await;
|
self.update_death_stats(&*dyn_self, cause).await;
|
||||||
|
|
||||||
// Plays the death sound
|
// Plays the death sound
|
||||||
world.send_entity_status(&self.entity, EntityStatus::Death);
|
world.send_entity_status(
|
||||||
|
&self.entity,
|
||||||
|
EntityStatus::Death,
|
||||||
|
Some(ActorEventType::Death),
|
||||||
|
);
|
||||||
let looting_level;
|
let looting_level;
|
||||||
let tool = if let Some(cause_ent) = cause {
|
let tool = if let Some(cause_ent) = cause {
|
||||||
if let Some(player) = cause_ent
|
if let Some(player) = cause_ent
|
||||||
@ -1747,10 +1767,11 @@ impl LivingEntity {
|
|||||||
.insert(slot, stack);
|
.insert(slot, stack);
|
||||||
}
|
}
|
||||||
self.set_health(1.0);
|
self.set_health(1.0);
|
||||||
self.entity
|
self.entity.world.load().send_entity_status(
|
||||||
.world
|
&self.entity,
|
||||||
.load()
|
EntityStatus::ProtectedFromDeath,
|
||||||
.send_entity_status(&self.entity, EntityStatus::ProtectedFromDeath);
|
Some(ActorEventType::InstantDeath),
|
||||||
|
);
|
||||||
|
|
||||||
// Set Absorption, Regeneration, and Fire Resistance effects
|
// Set Absorption, Regeneration, and Fire Resistance effects
|
||||||
self.add_effect(Effect {
|
self.add_effect(Effect {
|
||||||
@ -1828,8 +1849,11 @@ impl LivingEntity {
|
|||||||
if slot_result != pumpkin_data::item_stack::DamageResult::Untouched {
|
if slot_result != pumpkin_data::item_stack::DamageResult::Untouched {
|
||||||
if slot_result == pumpkin_data::item_stack::DamageResult::Broken {
|
if slot_result == pumpkin_data::item_stack::DamageResult::Broken {
|
||||||
let world = self.entity.world.load();
|
let world = self.entity.world.load();
|
||||||
world
|
world.send_entity_status(
|
||||||
.send_entity_status(&self.entity, super::equipment_break_status(&slot));
|
&self.entity,
|
||||||
|
super::equipment_break_status(&slot),
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
equipment_updates.push((slot.clone(), stack.clone()));
|
equipment_updates.push((slot.clone(), stack.clone()));
|
||||||
if let Some(player) = caller.get_player() {
|
if let Some(player) = caller.get_player() {
|
||||||
@ -2358,6 +2382,7 @@ impl EntityBase for LivingEntity {
|
|||||||
world.send_entity_status(
|
world.send_entity_status(
|
||||||
&self.entity,
|
&self.entity,
|
||||||
crate::entity::equipment_break_status(&slot),
|
crate::entity::equipment_break_status(&slot),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
*stack = ItemStack::EMPTY.clone();
|
*stack = ItemStack::EMPTY.clone();
|
||||||
let broken_stack = stack.clone();
|
let broken_stack = stack.clone();
|
||||||
@ -2759,10 +2784,11 @@ impl EntityBase for LivingEntity {
|
|||||||
// Only send death particles once (on the exact tick death_time reaches 20)
|
// Only send death particles once (on the exact tick death_time reaches 20)
|
||||||
// and then remove the entity, preventing entity_event spam.
|
// and then remove the entity, preventing entity_event spam.
|
||||||
if time == 20 && !self.entity.removed.swap(true, Ordering::Relaxed) {
|
if time == 20 && !self.entity.removed.swap(true, Ordering::Relaxed) {
|
||||||
self.entity
|
self.entity.world.load().send_entity_status(
|
||||||
.world
|
&self.entity,
|
||||||
.load()
|
EntityStatus::Death,
|
||||||
.send_entity_status(&self.entity, EntityStatus::Death);
|
Some(ActorEventType::Death),
|
||||||
|
);
|
||||||
self.entity.remove().await;
|
self.entity.remove().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use pumpkin_data::particle::Particle;
|
|||||||
use pumpkin_data::sound::{Sound, SoundCategory};
|
use pumpkin_data::sound::{Sound, SoundCategory};
|
||||||
|
|
||||||
use crate::entity::{EntityBaseFuture, mob::Mob, player::Player};
|
use crate::entity::{EntityBaseFuture, mob::Mob, player::Player};
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
|
|
||||||
pub trait Animal: Mob {
|
pub trait Animal: Mob {
|
||||||
@ -61,6 +62,7 @@ pub trait Animal: Mob {
|
|||||||
world.send_entity_status(
|
world.send_entity_status(
|
||||||
entity,
|
entity,
|
||||||
pumpkin_data::entity::EntityStatus::InLoveHearts,
|
pumpkin_data::entity::EntityStatus::InLoveHearts,
|
||||||
|
Some(ActorEventType::InLoveHearts),
|
||||||
);
|
);
|
||||||
|
|
||||||
world.spawn_particle(
|
world.spawn_particle(
|
||||||
|
|||||||
@ -18,6 +18,7 @@ use pumpkin_inventory::screen_handler::{
|
|||||||
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
||||||
};
|
};
|
||||||
use pumpkin_nbt::compound::NbtCompound;
|
use pumpkin_nbt::compound::NbtCompound;
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
|
||||||
use pumpkin_protocol::codec::var_int::VarInt;
|
use pumpkin_protocol::codec::var_int::VarInt;
|
||||||
use pumpkin_protocol::java::client::play::{CMerchantOffers, Metadata};
|
use pumpkin_protocol::java::client::play::{CMerchantOffers, Metadata};
|
||||||
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos, vector3::Vector3};
|
use pumpkin_util::math::{boundingbox::BoundingBox, position::BlockPos, vector3::Vector3};
|
||||||
@ -282,10 +283,11 @@ impl VillagerEntity {
|
|||||||
|
|
||||||
pub fn set_unhappy(&self) {
|
pub fn set_unhappy(&self) {
|
||||||
let entity = self.get_entity();
|
let entity = self.get_entity();
|
||||||
entity
|
entity.world.load().send_entity_status(
|
||||||
.world
|
entity,
|
||||||
.load()
|
pumpkin_data::entity::EntityStatus::VillagerAngry,
|
||||||
.send_entity_status(entity, pumpkin_data::entity::EntityStatus::VillagerAngry);
|
Some(ActorEventType::VillagerAngry),
|
||||||
|
);
|
||||||
entity.play_sound(pumpkin_data::sound::Sound::EntityVillagerNo);
|
entity.play_sound(pumpkin_data::sound::Sound::EntityVillagerNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,6 +381,7 @@ impl ScreenHandlerFactory for VillagerEntity {
|
|||||||
entity.world.load().send_entity_status(
|
entity.world.load().send_entity_status(
|
||||||
entity,
|
entity,
|
||||||
pumpkin_data::entity::EntityStatus::VillagerHappy,
|
pumpkin_data::entity::EntityStatus::VillagerHappy,
|
||||||
|
Some(ActorEventType::VillagerHappy),
|
||||||
);
|
);
|
||||||
entity.play_sound(
|
entity.play_sound(
|
||||||
pumpkin_data::sound::Sound::EntityVillagerCelebrate,
|
pumpkin_data::sound::Sound::EntityVillagerCelebrate,
|
||||||
|
|||||||
@ -59,8 +59,10 @@ use pumpkin_nbt::tag::NbtTag;
|
|||||||
use pumpkin_protocol::IdOr;
|
use pumpkin_protocol::IdOr;
|
||||||
use pumpkin_protocol::SoundEvent;
|
use pumpkin_protocol::SoundEvent;
|
||||||
use pumpkin_protocol::bedrock::client::container_open::CContainerOpen;
|
use pumpkin_protocol::bedrock::client::container_open::CContainerOpen;
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::{ActorEventType, SActorEvent};
|
||||||
use pumpkin_protocol::codec::var_int::VarInt;
|
use pumpkin_protocol::codec::var_int::VarInt;
|
||||||
use pumpkin_protocol::codec::var_long::VarLong;
|
use pumpkin_protocol::codec::var_long::VarLong;
|
||||||
|
use pumpkin_protocol::codec::var_ulong::VarULong;
|
||||||
use pumpkin_protocol::java::client::play::{
|
use pumpkin_protocol::java::client::play::{
|
||||||
Animation, CActionBar, CAwardStats, CChangeDifficulty, CCloseContainer, CCombatDeath,
|
Animation, CActionBar, CAwardStats, CChangeDifficulty, CCloseContainer, CCombatDeath,
|
||||||
CCustomPayload, CDisguisedChatMessage, CEntityAnimation, CEntityPositionSync, CGameEvent,
|
CCustomPayload, CDisguisedChatMessage, CEntityAnimation, CEntityPositionSync, CGameEvent,
|
||||||
@ -1085,11 +1087,12 @@ impl Player {
|
|||||||
|
|
||||||
let attack_speed = base_attack_speed + add_speed;
|
let attack_speed = base_attack_speed + add_speed;
|
||||||
|
|
||||||
let attack_cooldown_progress = self.get_attack_cooldown_progress(
|
let is_bedrock = matches!(self.client.as_ref(), ClientPlatform::Bedrock(_));
|
||||||
f64::from(server.basic_config.tps),
|
let attack_cooldown_progress = if is_bedrock {
|
||||||
0.5,
|
1.0
|
||||||
attack_speed,
|
} else {
|
||||||
);
|
self.get_attack_cooldown_progress(f64::from(server.basic_config.tps), 0.5, attack_speed)
|
||||||
|
};
|
||||||
self.last_attacked_ticks.store(0, Ordering::Relaxed);
|
self.last_attacked_ticks.store(0, Ordering::Relaxed);
|
||||||
|
|
||||||
// Only reduce attack damage if in cooldown
|
// Only reduce attack damage if in cooldown
|
||||||
@ -1349,6 +1352,7 @@ impl Player {
|
|||||||
self.world().send_entity_status(
|
self.world().send_entity_status(
|
||||||
&self.living_entity.entity,
|
&self.living_entity.entity,
|
||||||
super::equipment_break_status(slot),
|
super::equipment_break_status(slot),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2589,7 +2593,7 @@ impl Player {
|
|||||||
PermissionLvl::Four => EntityStatus::PermissionLevelOwners,
|
PermissionLvl::Four => EntityStatus::PermissionLevelOwners,
|
||||||
};
|
};
|
||||||
self.world()
|
self.world()
|
||||||
.send_entity_status(&self.living_entity.entity, status);
|
.send_entity_status(&self.living_entity.entity, status, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the player's difficulty level.
|
/// Sets the player's difficulty level.
|
||||||
@ -3250,8 +3254,17 @@ impl Player {
|
|||||||
self.breath_manager.reset(self);
|
self.breath_manager.reset(self);
|
||||||
|
|
||||||
self.client
|
self.client
|
||||||
.send_packet_now(&CCombatDeath::new(self.entity_id().into(), &death_msg))
|
.send_packet_now_editioned(
|
||||||
|
&CCombatDeath::new(self.entity_id().into(), &death_msg),
|
||||||
|
&SActorEvent {
|
||||||
|
entity_runtime_id: VarULong(self.entity_id() as u64),
|
||||||
|
event_type: ActorEventType::Death,
|
||||||
|
event_data: VarInt(0),
|
||||||
|
fire_at_position: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
|
self.send_health().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_gamemode(self: &Arc<Self>, gamemode: GameMode) -> bool {
|
pub async fn set_gamemode(self: &Arc<Self>, gamemode: GameMode) -> bool {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ use pumpkin_data::item::Item;
|
|||||||
use pumpkin_data::item_stack::ItemStack;
|
use pumpkin_data::item_stack::ItemStack;
|
||||||
use pumpkin_data::meta_data_type::MetaDataType;
|
use pumpkin_data::meta_data_type::MetaDataType;
|
||||||
use pumpkin_data::tracked_data::TrackedData;
|
use pumpkin_data::tracked_data::TrackedData;
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
|
||||||
use pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer;
|
use pumpkin_protocol::codec::item_stack_seralizer::ItemStackSerializer;
|
||||||
use pumpkin_protocol::java::client::play::Metadata;
|
use pumpkin_protocol::java::client::play::Metadata;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
@ -114,7 +115,11 @@ impl EntityBase for EggEntity {
|
|||||||
let spawn_pos = hit_pos.add(&normal.multiply(0.5, 0.5, 0.5));
|
let spawn_pos = hit_pos.add(&normal.multiply(0.5, 0.5, 0.5));
|
||||||
|
|
||||||
// Play egg break particles
|
// Play egg break particles
|
||||||
world.send_entity_status(self.get_entity(), EntityStatus::Death);
|
world.send_entity_status(
|
||||||
|
self.get_entity(),
|
||||||
|
EntityStatus::Death,
|
||||||
|
Some(ActorEventType::Death),
|
||||||
|
);
|
||||||
|
|
||||||
// Decide spawn count per probabilities:
|
// Decide spawn count per probabilities:
|
||||||
// r == 0 -> spawn 4 (1/256)
|
// r == 0 -> spawn 4 (1/256)
|
||||||
|
|||||||
@ -13,6 +13,7 @@ use pumpkin_data::damage::DamageType;
|
|||||||
use pumpkin_data::entity::{EntityPose, EntityStatus};
|
use pumpkin_data::entity::{EntityPose, EntityStatus};
|
||||||
use pumpkin_data::particle::Particle;
|
use pumpkin_data::particle::Particle;
|
||||||
use pumpkin_data::sound::{Sound, SoundCategory};
|
use pumpkin_data::sound::{Sound, SoundCategory};
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
|
|
||||||
const GRAVITY: f64 = 0.03;
|
const GRAVITY: f64 = 0.03;
|
||||||
@ -177,7 +178,7 @@ impl EntityBase for EnderPearlEntity {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
world.send_entity_status(entity, EntityStatus::Death);
|
world.send_entity_status(entity, EntityStatus::Death, Some(ActorEventType::Death));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use crate::{
|
|||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
use pumpkin_data::{entity::EntityStatus, meta_data_type::MetaDataType, tracked_data::TrackedData};
|
use pumpkin_data::{entity::EntityStatus, meta_data_type::MetaDataType, tracked_data::TrackedData};
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
|
||||||
use pumpkin_protocol::{codec::optional_int::OptionalInt, java::client::play::Metadata};
|
use pumpkin_protocol::{codec::optional_int::OptionalInt, java::client::play::Metadata};
|
||||||
use pumpkin_util::{
|
use pumpkin_util::{
|
||||||
math::vector3::Vector3,
|
math::vector3::Vector3,
|
||||||
@ -82,7 +83,11 @@ impl FireworkRocketEntity {
|
|||||||
|
|
||||||
pub async fn explode_and_remove(&self, world: &World) {
|
pub async fn explode_and_remove(&self, world: &World) {
|
||||||
let entity = self.get_entity();
|
let entity = self.get_entity();
|
||||||
world.send_entity_status(entity, EntityStatus::FireworksExplode);
|
world.send_entity_status(
|
||||||
|
entity,
|
||||||
|
EntityStatus::FireworksExplode,
|
||||||
|
Some(ActorEventType::FireworksExplode),
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Explode/colors
|
// TODO: Explode/colors
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use pumpkin_data::entity::EntityStatus;
|
use pumpkin_data::entity::EntityStatus;
|
||||||
use pumpkin_data::item_stack::ItemStack;
|
use pumpkin_data::item_stack::ItemStack;
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
|
||||||
use pumpkin_protocol::java::client::play::CWorldEvent;
|
use pumpkin_protocol::java::client::play::CWorldEvent;
|
||||||
use pumpkin_util::math::position::BlockPos;
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::math::vector2::{Vector2, to_chunk_pos};
|
use pumpkin_util::math::vector2::{Vector2, to_chunk_pos};
|
||||||
@ -116,7 +117,11 @@ impl EntityBase for LingeringPotionEntity {
|
|||||||
extinguish_fire_if_water_potion(&world, hit_pos, &stack).await;
|
extinguish_fire_if_water_potion(&world, hit_pos, &stack).await;
|
||||||
|
|
||||||
// Play impact particles
|
// Play impact particles
|
||||||
world.send_entity_status(self.get_entity(), EntityStatus::Death);
|
world.send_entity_status(
|
||||||
|
self.get_entity(),
|
||||||
|
EntityStatus::Death,
|
||||||
|
Some(ActorEventType::Death),
|
||||||
|
);
|
||||||
|
|
||||||
// Read stored item stack and compute potion effects
|
// Read stored item stack and compute potion effects
|
||||||
let stack = self.item_stack.read().await.clone();
|
let stack = self.item_stack.read().await.clone();
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use pumpkin_data::damage::DamageType;
|
use pumpkin_data::damage::DamageType;
|
||||||
use pumpkin_data::entity::{EntityStatus, EntityType};
|
use pumpkin_data::entity::{EntityStatus, EntityType};
|
||||||
|
use pumpkin_protocol::bedrock::server::actor_event::ActorEventType;
|
||||||
use pumpkin_util::math::vector3::Vector3;
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
|
|
||||||
const GRAVITY: f64 = 0.03;
|
const GRAVITY: f64 = 0.03;
|
||||||
@ -72,7 +73,11 @@ impl EntityBase for SnowballEntity {
|
|||||||
let world = self.get_entity().world.load();
|
let world = self.get_entity().world.load();
|
||||||
|
|
||||||
// Always send particle status regardless of what was hit
|
// Always send particle status regardless of what was hit
|
||||||
world.send_entity_status(self.get_entity(), EntityStatus::Death);
|
world.send_entity_status(
|
||||||
|
self.get_entity(),
|
||||||
|
EntityStatus::Death,
|
||||||
|
Some(ActorEventType::Death),
|
||||||
|
);
|
||||||
|
|
||||||
// Handle entity-specific damage
|
// Handle entity-specific damage
|
||||||
if let ProjectileHit::Entity { ref entity, .. } = hit {
|
if let ProjectileHit::Entity { ref entity, .. } = hit {
|
||||||
|
|||||||
@ -2411,9 +2411,11 @@ impl JavaClient {
|
|||||||
} else {
|
} else {
|
||||||
&EquipmentSlot::OFF_HAND
|
&EquipmentSlot::OFF_HAND
|
||||||
};
|
};
|
||||||
player
|
player.world().send_entity_status(
|
||||||
.world()
|
player.get_entity(),
|
||||||
.send_entity_status(player.get_entity(), equipment_break_status(slot));
|
equipment_break_status(slot),
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !after.are_equal(&before) {
|
if !after.are_equal(&before) {
|
||||||
|
|||||||
@ -98,7 +98,10 @@ use pumpkin_protocol::{
|
|||||||
start_game::{Experiments, GamePublishSetting, LevelSettings},
|
start_game::{Experiments, GamePublishSetting, LevelSettings},
|
||||||
update_attributes::{Attribute, CUpdateAttributes},
|
update_attributes::{Attribute, CUpdateAttributes},
|
||||||
},
|
},
|
||||||
server::text::SText,
|
server::{
|
||||||
|
actor_event::{ActorEventType, SActorEvent},
|
||||||
|
text::SText,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
codec::{var_int::VarInt, var_long::VarLong, var_uint::VarUInt, var_ulong::VarULong},
|
codec::{var_int::VarInt, var_long::VarLong, var_uint::VarUInt, var_ulong::VarULong},
|
||||||
java::{
|
java::{
|
||||||
@ -406,12 +409,25 @@ impl World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sends an entity status update to all players tracking the specified entity.
|
/// Sends an entity status update to all players tracking the specified entity.
|
||||||
pub fn send_entity_status(&self, entity: &Entity, status: EntityStatus) {
|
pub fn send_entity_status(
|
||||||
|
&self,
|
||||||
|
entity: &Entity,
|
||||||
|
java_status: EntityStatus,
|
||||||
|
bedrock_status: Option<ActorEventType>,
|
||||||
|
) {
|
||||||
let chunk_pos = entity.chunk_pos.load();
|
let chunk_pos = entity.chunk_pos.load();
|
||||||
self.broadcast_to_chunk(
|
let je_packet = CEntityStatus::new(entity.entity_id, java_status as i8);
|
||||||
chunk_pos,
|
if let Some(be_event) = bedrock_status {
|
||||||
&CEntityStatus::new(entity.entity_id, status as i8),
|
let be_packet = SActorEvent {
|
||||||
);
|
entity_runtime_id: VarULong(entity.entity_id as u64),
|
||||||
|
event_type: be_event,
|
||||||
|
event_data: VarInt(0),
|
||||||
|
fire_at_position: None,
|
||||||
|
};
|
||||||
|
self.broadcast_to_chunk_editioned_sync(chunk_pos, &je_packet, &be_packet);
|
||||||
|
} else {
|
||||||
|
self.broadcast_to_chunk(chunk_pos, &je_packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user