Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions pumpkin/src/entity/item.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::{entity::EntityBaseFuture, server::Server};
use crate::{
entity::EntityBaseFuture, plugin::player::pickup_arrow::PlayerPickupArrowEvent,
server::Server,
};
use core::f32;
use pumpkin_data::data_component_impl::DamageResistantImpl;
use pumpkin_data::data_component_impl::DamageResistantType;
use pumpkin_data::data_component_impl::{DamageResistantImpl, DamageResistantType};
use pumpkin_data::item::Item;
use pumpkin_data::{damage::DamageType, meta_data_type::MetaDataType, tracked_data::TrackedData};
use pumpkin_protocol::{
codec::item_stack_seralizer::ItemStackSerializer,
Expand All @@ -12,6 +15,7 @@ use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::item::ItemStack;
use std::sync::atomic::Ordering::{AcqRel, Relaxed};

use super::{Entity, EntityBase, NBTStorage, living::LivingEntity, player::Player};
use std::sync::{
Arc,
atomic::{
Expand All @@ -21,8 +25,6 @@ use std::sync::{
};
use tokio::sync::Mutex;

use super::{Entity, EntityBase, NBTStorage, living::LivingEntity, player::Player};

pub struct ItemEntity {
entity: Entity,
item_age: AtomicU32,
Expand Down Expand Up @@ -445,6 +447,29 @@ impl EntityBase for ItemEntity {
return;
}

let (item_stack_snapshot, item_id, item_count) = {
let stack = self.item_stack.lock().await;
(stack.clone(), stack.item.id, stack.item_count)
};

if (item_id == Item::ARROW.id
|| item_id == Item::SPECTRAL_ARROW.id
|| item_id == Item::TIPPED_ARROW.id)
&& let Some(server) = player.world().server.upgrade()
{
let event = PlayerPickupArrowEvent::new(
player.clone(),
self.entity.entity_uuid,
self.entity.entity_uuid,
item_stack_snapshot.clone(),
item_count as i32,
);
let event = server.plugin_manager.fire(event).await;
if event.cancelled {
return;
}
}

if player
.inventory
.insert_stack_anywhere(&mut *self.item_stack.lock().await)
Expand Down
64 changes: 62 additions & 2 deletions pumpkin/src/entity/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::entity::item::ItemEntity;
use crate::net::ClientPlatform;
use crate::plugin::player::portal::PlayerPortalEvent;
use crate::plugin::player::velocity::PlayerVelocityEvent;
use crate::world::World;
use crate::{
server::Server,
Expand Down Expand Up @@ -526,6 +528,18 @@ impl Entity {
}

pub async fn set_velocity(&self, velocity: Vector3<f64>) {
let mut velocity = velocity;
let world = self.world.load();
if let Some(player) = world.get_player_by_id(self.entity_id)
&& let Some(server) = world.server.upgrade()
{
let event = PlayerVelocityEvent::new(player, velocity);
let event = server.plugin_manager.fire(event).await;
if event.cancelled {
return;
}
velocity = event.velocity;
}
self.velocity.store(velocity);
self.send_velocity().await;
}
Expand Down Expand Up @@ -1429,6 +1443,7 @@ impl Entity {
self.velocity.store(velo);
}

#[allow(clippy::too_many_lines)]
async fn tick_portal(&self, caller: &Arc<dyn EntityBase>) {
if self.portal_cooldown.load(Ordering::Relaxed) > 0 {
self.portal_cooldown.fetch_sub(1, Ordering::Relaxed);
Expand All @@ -1450,12 +1465,12 @@ impl Entity {
let target_pos =
BlockPos::floored(pos.x * scale_factor, pos.y, pos.z * scale_factor);

let dest_world = portal_manager.portal_world.clone();
let mut dest_world = portal_manager.portal_world.clone();
let source_portal = portal_manager.source_portal.clone();
let source_axis = source_portal.as_ref().map(|p| p.axis);
drop(portal_manager);

let (teleport_pos, new_yaw) = if let Some(dest_result) =
let (mut teleport_pos, new_yaw) = if let Some(dest_result) =
NetherPortal::search_for_portal(&dest_world, target_pos).await
{
let base_pos = source_portal.as_ref().map_or_else(
Expand Down Expand Up @@ -1502,6 +1517,51 @@ impl Entity {
(target_pos.0.to_f64(), None)
};

let current_world = self.world.load();
if let Some(server) = current_world.server.upgrade()
&& let Some(player) = current_world.get_player_by_id(self.entity_id)
{
let from_position = player.position();
let cause = if dest_world.dimension == Dimension::THE_END
|| current_world.dimension == Dimension::THE_END
{
"END_PORTAL"
} else if dest_world.dimension == Dimension::THE_NETHER
|| current_world.dimension == Dimension::THE_NETHER
{
"NETHER_PORTAL"
} else {
"UNKNOWN"
};

let event = PlayerPortalEvent::new(
player,
from_position,
current_world.uuid,
teleport_pos,
dest_world.uuid,
cause.to_string(),
128,
true,
16,
);
let event = server.plugin_manager.fire(event).await;
if event.cancelled {
return;
}

teleport_pos = event.to_position;
if event.to_world_uuid != dest_world.uuid
&& let Some(found) = server
.worlds
.load()
.iter()
.find(|w| w.uuid == event.to_world_uuid)
{
dest_world = found.clone();
}
}

// Teleport the main entity
caller
.clone()
Expand Down
8 changes: 8 additions & 0 deletions pumpkin/src/plugin/api/events/player/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ pub mod player_join;
pub mod player_leave;
pub mod player_login;
pub mod player_move;
pub mod pickup_arrow;
pub mod portal;
pub mod recipe_discover;
pub mod riptide;
pub mod shear_entity;
pub mod spawn_location;
pub mod statistic_increment;
pub mod player_teleport;
pub mod velocity;

use std::sync::Arc;

Expand Down
53 changes: 53 additions & 0 deletions pumpkin/src/plugin/api/events/player/pickup_arrow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use pumpkin_macros::{Event, cancellable};
use pumpkin_world::item::ItemStack;
use std::sync::Arc;

use crate::entity::player::Player;

use super::PlayerEvent;

/// An event that occurs when a player picks up an arrow.
#[cancellable]
#[derive(Event, Clone)]
pub struct PlayerPickupArrowEvent {
/// The player picking up the arrow.
pub player: Arc<Player>,

/// The arrow entity UUID.
pub arrow_uuid: uuid::Uuid,

/// The item entity UUID.
pub item_uuid: uuid::Uuid,

/// The item stack being picked up.
pub item_stack: ItemStack,

/// Remaining items in the pickup.
pub remaining: i32,
}

impl PlayerPickupArrowEvent {
/// Creates a new instance of `PlayerPickupArrowEvent`.
pub const fn new(
player: Arc<Player>,
arrow_uuid: uuid::Uuid,
item_uuid: uuid::Uuid,
item_stack: ItemStack,
remaining: i32,
) -> Self {
Self {
player,
arrow_uuid,
item_uuid,
item_stack,
remaining,
cancelled: false,
}
}
}

impl PlayerEvent for PlayerPickupArrowEvent {
fn get_player(&self) -> &Arc<Player> {
&self.player
}
}
74 changes: 74 additions & 0 deletions pumpkin/src/plugin/api/events/player/portal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use pumpkin_macros::{Event, cancellable};
use pumpkin_util::math::vector3::Vector3;
use std::sync::Arc;

use crate::entity::player::Player;

use super::PlayerEvent;

/// An event that occurs when a player uses a portal.
#[cancellable]
#[derive(Event, Clone)]
pub struct PlayerPortalEvent {
/// The player using the portal.
pub player: Arc<Player>,

/// The origin position.
pub from_position: Vector3<f64>,

/// The origin world UUID.
pub from_world_uuid: uuid::Uuid,

/// The target position.
pub to_position: Vector3<f64>,

/// The target world UUID.
pub to_world_uuid: uuid::Uuid,

/// The portal cause.
pub cause: String,

/// The search radius for destination portals.
pub search_radius: i32,

/// Whether a new portal can be created.
pub can_create_portal: bool,

/// The portal creation radius.
pub creation_radius: i32,
}

impl PlayerPortalEvent {
/// Creates a new instance of `PlayerPortalEvent`.
#[allow(clippy::too_many_arguments)]
pub const fn new(
player: Arc<Player>,
from_position: Vector3<f64>,
from_world_uuid: uuid::Uuid,
to_position: Vector3<f64>,
to_world_uuid: uuid::Uuid,
cause: String,
search_radius: i32,
can_create_portal: bool,
creation_radius: i32,
) -> Self {
Self {
player,
from_position,
from_world_uuid,
to_position,
to_world_uuid,
cause,
search_radius,
can_create_portal,
creation_radius,
cancelled: false,
}
}
}

impl PlayerEvent for PlayerPortalEvent {
fn get_player(&self) -> &Arc<Player> {
&self.player
}
}
34 changes: 34 additions & 0 deletions pumpkin/src/plugin/api/events/player/recipe_discover.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use pumpkin_macros::{Event, cancellable};
use std::sync::Arc;

use crate::entity::player::Player;

use super::PlayerEvent;

/// An event that occurs when a player discovers a recipe.
#[cancellable]
#[derive(Event, Clone)]
pub struct PlayerRecipeDiscoverEvent {
/// The player discovering the recipe.
pub player: Arc<Player>,

/// The recipe key (namespace:id).
pub recipe_key: String,
}

impl PlayerRecipeDiscoverEvent {
/// Creates a new instance of `PlayerRecipeDiscoverEvent`.
pub const fn new(player: Arc<Player>, recipe_key: String) -> Self {
Self {
player,
recipe_key,
cancelled: false,
}
}
}

impl PlayerEvent for PlayerRecipeDiscoverEvent {
fn get_player(&self) -> &Arc<Player> {
&self.player
}
}
38 changes: 38 additions & 0 deletions pumpkin/src/plugin/api/events/player/riptide.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use pumpkin_macros::Event;
use pumpkin_util::math::vector3::Vector3;
use pumpkin_world::item::ItemStack;
use std::sync::Arc;

use crate::entity::player::Player;

use super::PlayerEvent;

/// An event that occurs when a player uses riptide.
#[derive(Event, Clone)]
pub struct PlayerRiptideEvent {
/// The player using riptide.
pub player: Arc<Player>,

/// The item used.
pub item_stack: ItemStack,

/// The riptide velocity.
pub velocity: Vector3<f64>,
}

impl PlayerRiptideEvent {
/// Creates a new instance of `PlayerRiptideEvent`.
pub const fn new(player: Arc<Player>, item_stack: ItemStack, velocity: Vector3<f64>) -> Self {
Self {
player,
item_stack,
velocity,
}
}
}

impl PlayerEvent for PlayerRiptideEvent {
fn get_player(&self) -> &Arc<Player> {
&self.player
}
}
Loading