105 lines
2.9 KiB
Rust
105 lines
2.9 KiB
Rust
use pumpkin_data::Block;
|
|
use pumpkin_data::BlockStateId;
|
|
use pumpkin_data::damage::DamageType;
|
|
use pumpkin_data::entity::EntityType;
|
|
use pumpkin_protocol::java::client::play::Metadata;
|
|
use pumpkin_util::math::position::BlockPos;
|
|
use pumpkin_world::world::BlockFlags;
|
|
use std::sync::{Arc, atomic::Ordering};
|
|
|
|
use crate::{
|
|
entity::{Entity, EntityBase, living::LivingEntity},
|
|
server::Server,
|
|
world::World,
|
|
};
|
|
|
|
pub struct FallingEntity {
|
|
entity: Entity,
|
|
block_state_id: BlockStateId,
|
|
}
|
|
|
|
impl FallingEntity {
|
|
pub const fn new(entity: Entity, block_state_id: BlockStateId) -> Self {
|
|
Self {
|
|
entity,
|
|
block_state_id,
|
|
}
|
|
}
|
|
|
|
/// Replaced the current Block and Spawns a new Falling one (synchronous)
|
|
pub fn replace_spawn(world: &Arc<World>, position: BlockPos, block_state: BlockStateId) {
|
|
// Replace the original block, TODO: use fluid state
|
|
world.set_block_state(
|
|
&position,
|
|
Block::AIR.default_state.id,
|
|
BlockFlags::NOTIFY_ALL,
|
|
);
|
|
|
|
let position = position.0.to_f64().add_raw(0.5, 0.0, 0.5);
|
|
let entity = Entity::new(world.clone(), position, &EntityType::FALLING_BLOCK);
|
|
entity
|
|
.data
|
|
.store(i32::from(block_state.as_u16()), Ordering::Relaxed);
|
|
let entity = Arc::new(Self::new(entity, block_state));
|
|
world.spawn_entity_non_save(entity);
|
|
}
|
|
}
|
|
|
|
impl EntityBase for FallingEntity {
|
|
fn tick(&self, caller: &dyn EntityBase, _server: &Server) {
|
|
let entity = &self.entity;
|
|
let mut velo = entity.velocity.load();
|
|
velo.y -= self.get_gravity();
|
|
|
|
entity.velocity.store(velo);
|
|
|
|
entity.move_entity(caller, velo);
|
|
entity.tick_block_collisions(caller);
|
|
if entity.on_ground.load(Ordering::Relaxed) {
|
|
entity.velocity.store(velo.multiply(0.7, -0.5, 0.7));
|
|
entity.world.load().set_block_state(
|
|
&self.entity.block_pos.load(),
|
|
self.block_state_id,
|
|
BlockFlags::NOTIFY_ALL,
|
|
);
|
|
self.entity.remove();
|
|
}
|
|
|
|
entity.velocity.store(velo.multiply(0.98, 0.98, 0.98));
|
|
|
|
if entity.velocity_dirty.swap(false, Ordering::SeqCst) {
|
|
entity.send_pos_rot();
|
|
entity.send_velocity();
|
|
}
|
|
}
|
|
|
|
fn init_data_tracker(&self) {
|
|
self.entity.send_meta_data(
|
|
&[Metadata::new(
|
|
pumpkin_data::tracked_data::falling_block::START_POS,
|
|
self.entity.block_pos.load(),
|
|
)],
|
|
None,
|
|
);
|
|
}
|
|
|
|
fn get_entity(&self) -> &Entity {
|
|
&self.entity
|
|
}
|
|
|
|
fn get_living_entity(&self) -> Option<&LivingEntity> {
|
|
None
|
|
}
|
|
fn damage(&self, _caller: &dyn EntityBase, _amount: f32, _damage_type: DamageType) -> bool {
|
|
false
|
|
}
|
|
|
|
fn get_gravity(&self) -> f64 {
|
|
0.04
|
|
}
|
|
|
|
fn cast_any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
}
|