mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-31 20:32:34 +00:00
Cactus hurts now
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::block_properties::{
|
||||
BlockProperties, CactusLikeProperties, EnumVariants, Integer0To15,
|
||||
};
|
||||
use pumpkin_data::damage::DamageType;
|
||||
use pumpkin_data::tag::Tagable;
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_protocol::server::play::SUseItemOn;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
@@ -15,6 +16,7 @@ use pumpkin_world::chunk::TickPriority;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
use crate::block::pumpkin_block::PumpkinBlock;
|
||||
use crate::entity::EntityBase;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
@@ -59,6 +61,17 @@ impl PumpkinBlock for CactusBlock {
|
||||
}
|
||||
}
|
||||
|
||||
async fn on_entity_collision(
|
||||
&self,
|
||||
_world: &Arc<World>,
|
||||
entity: &dyn EntityBase,
|
||||
_pos: BlockPos,
|
||||
_block: Block,
|
||||
_state: BlockState,
|
||||
) {
|
||||
entity.damage(1.0, DamageType::CACTUS).await;
|
||||
}
|
||||
|
||||
async fn get_state_for_neighbor_update(
|
||||
&self,
|
||||
world: &World,
|
||||
|
||||
@@ -11,7 +11,7 @@ use pumpkin_world::{BlockStateId, block::BlockDirection};
|
||||
|
||||
use crate::{
|
||||
block::pumpkin_block::{BlockMetadata, PumpkinBlock},
|
||||
entity::Entity,
|
||||
entity::EntityBase,
|
||||
world::World,
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ impl PumpkinBlock for PressurePlateBlock {
|
||||
async fn on_entity_collision(
|
||||
&self,
|
||||
world: &Arc<World>,
|
||||
_entity: &Entity,
|
||||
_entity: &dyn EntityBase,
|
||||
pos: BlockPos,
|
||||
block: Block,
|
||||
state: BlockState,
|
||||
|
||||
@@ -10,7 +10,7 @@ use pumpkin_world::{BlockStateId, block::BlockDirection};
|
||||
|
||||
use crate::{
|
||||
block::pumpkin_block::{BlockMetadata, PumpkinBlock},
|
||||
entity::Entity,
|
||||
entity::EntityBase,
|
||||
world::World,
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ impl PumpkinBlock for WeightedPressurePlateBlock {
|
||||
async fn on_entity_collision(
|
||||
&self,
|
||||
world: &Arc<World>,
|
||||
_entity: &Entity,
|
||||
_entity: &dyn EntityBase,
|
||||
pos: BlockPos,
|
||||
block: Block,
|
||||
state: BlockState,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::entity::Entity;
|
||||
use crate::entity::EntityBase;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
@@ -53,7 +53,7 @@ pub trait PumpkinBlock: Send + Sync {
|
||||
async fn on_entity_collision(
|
||||
&self,
|
||||
_world: &Arc<World>,
|
||||
_entity: &Entity,
|
||||
_entity: &dyn EntityBase,
|
||||
_pos: BlockPos,
|
||||
_block: Block,
|
||||
_state: BlockState,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::block::pumpkin_block::{BlockMetadata, PumpkinBlock};
|
||||
use crate::entity::Entity;
|
||||
use crate::entity::EntityBase;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
@@ -60,7 +60,7 @@ impl BlockRegistry {
|
||||
&self,
|
||||
block: Block,
|
||||
world: &Arc<World>,
|
||||
entity: &Entity,
|
||||
entity: &dyn EntityBase,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
) {
|
||||
|
||||
@@ -64,8 +64,8 @@ impl ExperienceOrbEntity {
|
||||
|
||||
#[async_trait]
|
||||
impl EntityBase for ExperienceOrbEntity {
|
||||
async fn tick(&self, server: &Server) {
|
||||
self.entity.tick(server).await;
|
||||
async fn tick(&self, caller: &dyn EntityBase, server: &Server) {
|
||||
self.entity.tick(caller, server).await;
|
||||
|
||||
let age = self
|
||||
.orb_age
|
||||
@@ -79,7 +79,7 @@ impl EntityBase for ExperienceOrbEntity {
|
||||
&self.entity
|
||||
}
|
||||
|
||||
async fn on_player_collision(&self, player: Arc<Player>) {
|
||||
async fn on_player_collision(&self, player: &Arc<Player>) {
|
||||
let mut delay = player.experience_pick_up_delay.lock().await;
|
||||
if *delay == 0 {
|
||||
*delay = 2;
|
||||
|
||||
@@ -63,9 +63,9 @@ impl ItemEntity {
|
||||
|
||||
#[async_trait]
|
||||
impl EntityBase for ItemEntity {
|
||||
async fn tick(&self, server: &Server) {
|
||||
async fn tick(&self, caller: &dyn EntityBase, server: &Server) {
|
||||
let entity = &self.entity;
|
||||
entity.tick(server).await;
|
||||
entity.tick(caller, server).await;
|
||||
{
|
||||
let mut delay = self.pickup_delay.lock().await;
|
||||
*delay = delay.saturating_sub(1);
|
||||
@@ -91,7 +91,7 @@ impl EntityBase for ItemEntity {
|
||||
false
|
||||
}
|
||||
|
||||
async fn on_player_collision(&self, player: Arc<Player>) {
|
||||
async fn on_player_collision(&self, player: &Arc<Player>) {
|
||||
let can_pickup = {
|
||||
let delay = self.pickup_delay.lock().await;
|
||||
*delay == 0
|
||||
|
||||
@@ -262,7 +262,7 @@ impl LivingEntity {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn tick_move(&self) {
|
||||
async fn tick_move(&self, entity: &dyn EntityBase) {
|
||||
let velo = self.entity.velocity.load();
|
||||
let pos = self.entity.pos.load();
|
||||
self.entity
|
||||
@@ -272,7 +272,7 @@ impl LivingEntity {
|
||||
self.entity
|
||||
.velocity
|
||||
.store(velo.multiply(multiplier, 1.0, multiplier));
|
||||
self.entity.check_block_collision().await;
|
||||
Entity::check_block_collision(entity).await;
|
||||
}
|
||||
|
||||
async fn tick_effects(&self) {
|
||||
@@ -296,9 +296,9 @@ impl LivingEntity {
|
||||
|
||||
#[async_trait]
|
||||
impl EntityBase for LivingEntity {
|
||||
async fn tick(&self, server: &Server) {
|
||||
self.entity.tick(server).await;
|
||||
self.tick_move().await;
|
||||
async fn tick(&self, caller: &dyn EntityBase, server: &Server) {
|
||||
self.entity.tick(caller, server).await;
|
||||
self.tick_move(caller).await;
|
||||
self.tick_effects().await;
|
||||
if self.time_until_regen.load(Relaxed) > 0 {
|
||||
self.time_until_regen.fetch_sub(1, Relaxed);
|
||||
|
||||
@@ -24,8 +24,8 @@ pub struct MobEntity {
|
||||
|
||||
#[async_trait]
|
||||
impl EntityBase for MobEntity {
|
||||
async fn tick(&self, server: &Server) {
|
||||
self.living_entity.tick(server).await;
|
||||
async fn tick(&self, caller: &dyn EntityBase, server: &Server) {
|
||||
self.living_entity.tick(caller, server).await;
|
||||
let mut goals = self.goals.lock().await;
|
||||
for (goal, running) in goals.iter_mut() {
|
||||
if *running {
|
||||
|
||||
@@ -57,12 +57,18 @@ pub type EntityId = i32;
|
||||
|
||||
#[async_trait]
|
||||
pub trait EntityBase: Send + Sync {
|
||||
/// Gets Called every tick
|
||||
async fn tick(&self, server: &Server) {
|
||||
/// Called every tick for this entity.
|
||||
///
|
||||
/// The `caller` parameter is a reference to the entity that initiated the tick.
|
||||
/// This can be the same entity the method is being called on (`self`),
|
||||
/// but in some scenarios (e.g., interactions or events), it might be a different entity.
|
||||
///
|
||||
/// The `server` parameter provides access to the game server instance.
|
||||
async fn tick(&self, caller: &dyn EntityBase, server: &Server) {
|
||||
if let Some(living) = self.get_living_entity() {
|
||||
living.tick(server).await;
|
||||
living.tick(caller, server).await;
|
||||
} else {
|
||||
self.get_entity().tick(server).await;
|
||||
self.get_entity().tick(caller, server).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +84,7 @@ pub trait EntityBase: Send + Sync {
|
||||
}
|
||||
|
||||
/// Called when a player collides with a entity
|
||||
async fn on_player_collision(&self, _player: Arc<Player>) {}
|
||||
async fn on_player_collision(&self, _player: &Arc<Player>) {}
|
||||
fn get_entity(&self) -> &Entity;
|
||||
fn get_living_entity(&self) -> Option<&LivingEntity>;
|
||||
}
|
||||
@@ -485,8 +491,8 @@ impl Entity {
|
||||
// }
|
||||
}
|
||||
|
||||
pub async fn check_block_collision(&self) {
|
||||
let aabb = self.bounding_box.load();
|
||||
pub async fn check_block_collision(entity: &dyn EntityBase) {
|
||||
let aabb = entity.get_entity().bounding_box.load();
|
||||
let blockpos = BlockPos::new(
|
||||
(aabb.min.x + 0.001).floor() as i32,
|
||||
(aabb.min.y + 0.001).floor() as i32,
|
||||
@@ -497,7 +503,7 @@ impl Entity {
|
||||
(aabb.max.y - 0.001).floor() as i32,
|
||||
(aabb.max.z - 0.001).floor() as i32,
|
||||
);
|
||||
let world = self.world.read().await;
|
||||
let world = entity.get_entity().world.read().await;
|
||||
|
||||
for x in blockpos.0.x..=blockpos1.0.x {
|
||||
for y in blockpos.0.y..=blockpos1.0.y {
|
||||
@@ -506,7 +512,7 @@ impl Entity {
|
||||
let (block, state) = world.get_block_and_block_state(&pos).await.unwrap();
|
||||
world
|
||||
.block_registry
|
||||
.on_entity_collision(block, &world, self, pos, state)
|
||||
.on_entity_collision(block, &world, entity, pos, state)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -520,8 +526,8 @@ impl EntityBase for Entity {
|
||||
false
|
||||
}
|
||||
|
||||
async fn tick(&self, _: &Server) {
|
||||
//Todo! Tick
|
||||
async fn tick(&self, _caller: &dyn EntityBase, _: &Server) {
|
||||
// TODO: Tick
|
||||
}
|
||||
|
||||
fn get_entity(&self) -> &Entity {
|
||||
|
||||
@@ -663,7 +663,7 @@ impl Player {
|
||||
|
||||
self.last_attacked_ticks.fetch_add(1, Relaxed);
|
||||
|
||||
self.living_entity.tick(server).await;
|
||||
self.living_entity.tick(self, server).await;
|
||||
self.hunger_manager.tick(self).await;
|
||||
|
||||
// experience handling
|
||||
@@ -1797,6 +1797,9 @@ impl NBTStorage for PlayerInventory {
|
||||
#[async_trait]
|
||||
impl EntityBase for Player {
|
||||
async fn damage(&self, amount: f32, damage_type: DamageType) -> bool {
|
||||
if self.abilities.lock().await.invulnerable {
|
||||
return false;
|
||||
}
|
||||
self.world()
|
||||
.await
|
||||
.play_sound(
|
||||
|
||||
@@ -31,7 +31,7 @@ impl TNTEntity {
|
||||
|
||||
#[async_trait]
|
||||
impl EntityBase for TNTEntity {
|
||||
async fn tick(&self, server: &Server) {
|
||||
async fn tick(&self, _caller: &dyn EntityBase, server: &Server) {
|
||||
let fuse = self.fuse.fetch_sub(1, Relaxed);
|
||||
if fuse == 0 {
|
||||
self.entity.remove().await;
|
||||
|
||||
@@ -400,7 +400,7 @@ impl World {
|
||||
|
||||
// Entity ticks
|
||||
for entity in entities_to_tick {
|
||||
entity.tick(server).await;
|
||||
entity.tick(entity.as_ref(), server).await;
|
||||
for player in self.players.read().await.values() {
|
||||
if player
|
||||
.living_entity
|
||||
@@ -411,7 +411,7 @@ impl World {
|
||||
.expand(1.0, 0.5, 1.0)
|
||||
.intersects(&entity.get_entity().bounding_box.load())
|
||||
{
|
||||
entity.on_player_collision(player.clone()).await;
|
||||
entity.on_player_collision(player).await;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user