diff --git a/pumpkin/src/entity/tnt.rs b/pumpkin/src/entity/tnt.rs index 195f14fc5..492cd2823 100644 --- a/pumpkin/src/entity/tnt.rs +++ b/pumpkin/src/entity/tnt.rs @@ -49,19 +49,21 @@ impl EntityBase for TNTEntity { entity.move_entity(caller.clone(), velo).await; entity.tick_block_collisions(&caller, server).await; entity.velocity.store(velo.multiply(0.98, 0.98, 0.98)); + if entity.on_ground.load(Ordering::Relaxed) { entity.velocity.store(velo.multiply(0.7, -0.5, 0.7)); } - let velocity_dirty = entity.velocity_dirty.swap(false, Ordering::SeqCst); - if velocity_dirty { + if entity.velocity_dirty.swap(false, Ordering::SeqCst) { entity.send_pos_rot().await; - entity.send_velocity().await; } - let fuse = self.fuse.fetch_sub(1, Relaxed); - if fuse == 0 { + // FIX: Prevent fuse underflow (vanilla parity) + let fuse = self.fuse.load(Relaxed); + + if fuse <= 1 { + // TNT explodes now self.entity.remove().await; self.entity .world @@ -69,6 +71,8 @@ impl EntityBase for TNTEntity { .explode(self.entity.pos.load(), self.power) .await; } else { + // Safe decrement + self.fuse.store(fuse - 1, Relaxed); entity.update_fluid_state(&caller).await; } }) @@ -76,13 +80,12 @@ impl EntityBase for TNTEntity { fn init_data_tracker(&self) -> EntityBaseFuture<'_, ()> { Box::pin(async { - // TODO: Yes, this is the wrong function, but we need to send this after spawning the entity. let pos: f64 = rand::random::() * 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( diff --git a/pumpkin/src/world/explosion.rs b/pumpkin/src/world/explosion.rs index 731f7c27f..8abf2f4a1 100644 --- a/pumpkin/src/world/explosion.rs +++ b/pumpkin/src/world/explosion.rs @@ -16,11 +16,13 @@ pub struct Explosion { power: f32, pos: Vector3, } + impl Explosion { #[must_use] pub const fn new(power: f32, pos: Vector3) -> Self { Self { power, pos } } + async fn get_blocks_to_destroy( &self, world: &World, @@ -103,6 +105,12 @@ impl Explosion { if entity_base.is_immune_to_explosion() { continue; } + + // Skip spectators (no damage, no knockback) + if entity_base.is_spectator() { + continue; + } + let entity = entity_base.get_entity(); let distance = (entity.pos.load().squared_distance_to_vec(&self.pos)).sqrt() / radius;