Pumpkin/pumpkin/src/entity/tnt.rs
2025-06-22 21:28:14 +02:00

86 lines
2.2 KiB
Rust

use crate::server::Server;
use async_trait::async_trait;
use pumpkin_data::{Block, damage::DamageType};
use pumpkin_protocol::{
client::play::{MetaDataType, Metadata},
codec::var_int::VarInt,
};
use pumpkin_util::math::vector3::Vector3;
use std::{
f64::consts::TAU,
sync::{
Arc,
atomic::{AtomicU32, Ordering::Relaxed},
},
};
use super::{Entity, EntityBase, living::LivingEntity};
pub struct TNTEntity {
entity: Entity,
power: f32,
fuse: AtomicU32,
}
impl TNTEntity {
pub fn new(entity: Entity, power: f32, fuse: u32) -> Self {
Self {
entity,
power,
fuse: AtomicU32::new(fuse),
}
}
}
#[async_trait]
impl EntityBase for TNTEntity {
async fn tick(&self, _caller: Arc<dyn EntityBase>, server: &Server) {
let fuse = self.fuse.fetch_sub(1, Relaxed);
if fuse == 0 {
self.entity.remove().await;
self.entity
.world
.read()
.await
.explode(server, self.entity.pos.load(), self.power)
.await;
}
}
async fn init_data_tracker(&self) {
// TODO: Yes, this is the wrong function, but we need to send this after spawning the entity.
let pos: f64 = rand::random::<f64>() * TAU;
self.entity
.set_velocity(Vector3::new(-pos.sin() * 0.02, 0.2, -pos.cos() * 0.02))
.await;
// We can merge multiple `Metadata`s into one meta packet.
self.entity
.send_meta_data(&[
Metadata::new(
8,
MetaDataType::Integer,
VarInt(self.fuse.load(Relaxed) as i32),
),
Metadata::new(
9,
MetaDataType::BlockState,
VarInt(i32::from(Block::TNT.default_state.id)),
),
])
.await;
}
async fn damage(&self, _amount: f32, _damage_type: DamageType) -> bool {
false
}
fn get_entity(&self) -> &Entity {
&self.entity
}
fn get_living_entity(&self) -> Option<&LivingEntity> {
None
}
}