mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-31 08:22:33 +00:00
chore: move to crates folder
This commit is contained in:
45
crates/pumpkin-plugin-api/src/ai.rs
Normal file
45
crates/pumpkin-plugin-api/src/ai.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use crate::wit::pumpkin::plugin::context::Server;
|
||||
use crate::wit::pumpkin::plugin::world::Entity;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// Represents a custom entity AI goal for mobs.
|
||||
#[allow(unused_variables)]
|
||||
pub trait AiGoal: Send + Sync {
|
||||
/// Returns `true` if the goal should start executing.
|
||||
fn can_start(&mut self, server: Server, entity: Entity) -> bool {
|
||||
false
|
||||
}
|
||||
/// Returns `true` if the goal should continue executing on subsequent ticks.
|
||||
fn should_continue(&mut self, server: Server, entity: Entity) -> bool {
|
||||
false
|
||||
}
|
||||
/// Executed when the goal starts.
|
||||
fn start(&mut self, server: Server, entity: Entity) {}
|
||||
/// Executed on every server tick while the goal is active.
|
||||
fn tick(&mut self, server: Server, entity: Entity) {}
|
||||
/// Executed when the goal stops executing.
|
||||
fn stop(&mut self, server: Server, entity: Entity) {}
|
||||
}
|
||||
|
||||
pub(crate) static AI_GOAL_HANDLERS: Mutex<LazyAiGoalHandlers> = Mutex::new(LazyAiGoalHandlers {
|
||||
handlers: BTreeMap::new(),
|
||||
next_id: 0,
|
||||
});
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) struct LazyAiGoalHandlers {
|
||||
pub handlers: BTreeMap<u32, Box<dyn AiGoal>>,
|
||||
pub next_id: u32,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl LazyAiGoalHandlers {
|
||||
#[must_use]
|
||||
pub fn register(&mut self, goal: Box<dyn AiGoal>) -> u32 {
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
self.handlers.insert(id, goal);
|
||||
id
|
||||
}
|
||||
}
|
||||
77
crates/pumpkin-plugin-api/src/commands.rs
Normal file
77
crates/pumpkin-plugin-api/src/commands.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
sync::{
|
||||
Mutex,
|
||||
atomic::{AtomicU32, Ordering},
|
||||
},
|
||||
};
|
||||
|
||||
pub use crate::wit::pumpkin::plugin::command::Command;
|
||||
use crate::{
|
||||
Result, Server,
|
||||
command::CommandNode,
|
||||
wit::pumpkin::plugin::command::{CommandError, CommandSender, ConsumedArgs},
|
||||
};
|
||||
|
||||
pub(crate) static NEXT_COMMAND_ID: AtomicU32 = AtomicU32::new(0);
|
||||
pub(crate) static COMMAND_HANDLERS: Mutex<BTreeMap<u32, Box<dyn CommandHandler>>> =
|
||||
Mutex::new(BTreeMap::new());
|
||||
|
||||
/// Handles the execution of a registered command.
|
||||
///
|
||||
/// Implement this trait to define the logic that runs when a command is invoked.
|
||||
/// The return value is the exit code passed back to the server; return `Ok(0)` for
|
||||
/// success or an [`Err`] variant to report a failure message to the sender.
|
||||
pub trait CommandHandler: Send + Sync {
|
||||
/// Executes the command.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `sender` — who invoked the command (player or console).
|
||||
/// - `server` — handle to the server.
|
||||
/// - `args` — the parsed argument map for this command invocation.
|
||||
fn handle(
|
||||
&self,
|
||||
sender: CommandSender,
|
||||
server: Server,
|
||||
args: ConsumedArgs,
|
||||
) -> Result<i32, CommandError>;
|
||||
}
|
||||
|
||||
impl Command {
|
||||
/// Attaches an execution handler to this command.
|
||||
///
|
||||
/// Registers `handler` so that it is called whenever this command is invoked.
|
||||
/// Returns `self` to allow builder-style chaining.
|
||||
pub fn execute<H: CommandHandler + Send + Sync + 'static>(self, handler: H) -> Self {
|
||||
let id = NEXT_COMMAND_ID.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
COMMAND_HANDLERS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(id, Box::new(handler));
|
||||
|
||||
self.execute_with_handler_id(id);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl CommandNode {
|
||||
/// Attaches an execution handler to this command node.
|
||||
///
|
||||
/// Registers `handler` so that it is called when this specific node (subcommand
|
||||
/// or argument branch) is the final node matched during command dispatch.
|
||||
/// Returns `self` to allow builder-style chaining.
|
||||
pub fn execute<H: CommandHandler + Send + Sync + 'static>(self, handler: H) -> Self {
|
||||
let id = NEXT_COMMAND_ID.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
COMMAND_HANDLERS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(id, Box::new(handler));
|
||||
|
||||
self.execute_with_handler_id(id);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
25
crates/pumpkin-plugin-api/src/events/block/block_break.rs
Normal file
25
crates/pumpkin-plugin-api/src/events/block/block_break.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{BlockBreakEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a block is broken.
|
||||
///
|
||||
/// The associated [`BlockBreakEventData`] contains the player (if any), the block
|
||||
/// identifier, its position, the experience to drop, and whether the block should
|
||||
/// drop items. This event is cancellable.
|
||||
pub struct BlockBreakEvent;
|
||||
impl FromIntoEvent for BlockBreakEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockBreakEvent;
|
||||
type Data = BlockBreakEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockBreakEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockBreakEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/block/block_burn.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/block/block_burn.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{BlockBurnEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a block is destroyed by fire.
|
||||
///
|
||||
/// The associated [`BlockBurnEventData`] contains the block that caught fire and
|
||||
/// the igniting block that caused it to burn. This event is cancellable.
|
||||
pub struct BlockBurnEvent;
|
||||
impl FromIntoEvent for BlockBurnEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockBurnEvent;
|
||||
type Data = BlockBurnEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockBurnEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockBurnEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{BlockCanBuildEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player attempts to place a block, checking if it can be built.
|
||||
///
|
||||
/// The associated [`BlockCanBuildEventData`] contains the player, the block being
|
||||
/// placed, the block it is being placed against, and a `buildable` flag that can be
|
||||
/// overridden. This event is cancellable.
|
||||
pub struct BlockCanBuildEvent;
|
||||
impl FromIntoEvent for BlockCanBuildEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockCanBuildEvent;
|
||||
type Data = BlockCanBuildEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockCanBuildEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockCanBuildEvent(data)
|
||||
}
|
||||
}
|
||||
20
crates/pumpkin-plugin-api/src/events/block/block_damage.rs
Normal file
20
crates/pumpkin-plugin-api/src/events/block/block_damage.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{BlockDamageEventData, Event, EventType};
|
||||
|
||||
/// Event triggered when a block is damaged by a player.
|
||||
pub struct BlockDamageEvent;
|
||||
impl FromIntoEvent for BlockDamageEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockDamageEvent;
|
||||
type Data = BlockDamageEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockDamageEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockDamageEvent(data)
|
||||
}
|
||||
}
|
||||
20
crates/pumpkin-plugin-api/src/events/block/block_fade.rs
Normal file
20
crates/pumpkin-plugin-api/src/events/block/block_fade.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{BlockFadeEventData, Event, EventType};
|
||||
|
||||
/// Event triggered when a block fades or melts away.
|
||||
pub struct BlockFadeEvent;
|
||||
impl FromIntoEvent for BlockFadeEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockFadeEvent;
|
||||
type Data = BlockFadeEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockFadeEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockFadeEvent(data)
|
||||
}
|
||||
}
|
||||
20
crates/pumpkin-plugin-api/src/events/block/block_form.rs
Normal file
20
crates/pumpkin-plugin-api/src/events/block/block_form.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{BlockFormEventData, Event, EventType};
|
||||
|
||||
/// Event triggered when a block is formed.
|
||||
pub struct BlockFormEvent;
|
||||
impl FromIntoEvent for BlockFormEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockFormEvent;
|
||||
type Data = BlockFormEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockFormEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockFormEvent(data)
|
||||
}
|
||||
}
|
||||
20
crates/pumpkin-plugin-api/src/events/block/block_from_to.rs
Normal file
20
crates/pumpkin-plugin-api/src/events/block/block_from_to.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{BlockFromToEventData, Event, EventType};
|
||||
|
||||
/// Event triggered when a fluid flows from one block position to another.
|
||||
pub struct BlockFromToEvent;
|
||||
impl FromIntoEvent for BlockFromToEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockFromToEvent;
|
||||
type Data = BlockFromToEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockFromToEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockFromToEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/block/block_grow.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/block/block_grow.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{BlockGrowEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a block grows or changes state naturally (e.g. crops, saplings).
|
||||
///
|
||||
/// The associated [`BlockGrowEventData`] contains the world, the old and new block
|
||||
/// identifiers with their state IDs, and the block position. This event is cancellable.
|
||||
pub struct BlockGrowEvent;
|
||||
impl FromIntoEvent for BlockGrowEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockGrowEvent;
|
||||
type Data = BlockGrowEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockGrowEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockGrowEvent(data)
|
||||
}
|
||||
}
|
||||
20
crates/pumpkin-plugin-api/src/events/block/block_ignite.rs
Normal file
20
crates/pumpkin-plugin-api/src/events/block/block_ignite.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{BlockIgniteEventData, Event, EventType};
|
||||
|
||||
/// Event triggered when a block is ignited.
|
||||
pub struct BlockIgniteEvent;
|
||||
impl FromIntoEvent for BlockIgniteEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockIgniteEvent;
|
||||
type Data = BlockIgniteEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockIgniteEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockIgniteEvent(data)
|
||||
}
|
||||
}
|
||||
25
crates/pumpkin-plugin-api/src/events/block/block_place.rs
Normal file
25
crates/pumpkin-plugin-api/src/events/block/block_place.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{BlockPlaceEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player places a block.
|
||||
///
|
||||
/// The associated [`BlockPlaceEventData`] contains the player, the block being placed,
|
||||
/// the block it is placed against, the position, and a `can-build` flag. This event
|
||||
/// is cancellable.
|
||||
pub struct BlockPlaceEvent;
|
||||
impl FromIntoEvent for BlockPlaceEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockPlaceEvent;
|
||||
type Data = BlockPlaceEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockPlaceEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockPlaceEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/block/block_redstone.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/block/block_redstone.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{BlockRedstoneEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a redstone component changes its power level.
|
||||
///
|
||||
/// The associated [`BlockRedstoneEventData`] contains the world, the block state ID,
|
||||
/// the block position, and the old and new current values. This event is cancellable.
|
||||
pub struct BlockRedstoneEvent;
|
||||
impl FromIntoEvent for BlockRedstoneEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BlockRedstoneEvent;
|
||||
type Data = BlockRedstoneEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BlockRedstoneEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BlockRedstoneEvent(data)
|
||||
}
|
||||
}
|
||||
34
crates/pumpkin-plugin-api/src/events/block/mod.rs
Normal file
34
crates/pumpkin-plugin-api/src/events/block/mod.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
/// Block break event.
|
||||
pub mod block_break;
|
||||
/// Block burn event.
|
||||
pub mod block_burn;
|
||||
/// Block can build check event.
|
||||
pub mod block_can_build;
|
||||
/// Block damage event.
|
||||
pub mod block_damage;
|
||||
/// Block fade event.
|
||||
pub mod block_fade;
|
||||
/// Block form event.
|
||||
pub mod block_form;
|
||||
/// Block fluid flow event.
|
||||
pub mod block_from_to;
|
||||
/// Block growth event.
|
||||
pub mod block_grow;
|
||||
/// Block ignite event.
|
||||
pub mod block_ignite;
|
||||
/// Block place event.
|
||||
pub mod block_place;
|
||||
/// Block redstone signal event.
|
||||
pub mod block_redstone;
|
||||
|
||||
pub use block_break::*;
|
||||
pub use block_burn::*;
|
||||
pub use block_can_build::*;
|
||||
pub use block_damage::*;
|
||||
pub use block_fade::*;
|
||||
pub use block_form::*;
|
||||
pub use block_from_to::*;
|
||||
pub use block_grow::*;
|
||||
pub use block_ignite::*;
|
||||
pub use block_place::*;
|
||||
pub use block_redstone::*;
|
||||
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{EntityCombustEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// Event triggered when an entity catches fire.
|
||||
pub struct EntityCombustEvent;
|
||||
impl FromIntoEvent for EntityCombustEvent {
|
||||
const EVENT_TYPE: EventType = EventType::EntityCombustEvent;
|
||||
type Data = EntityCombustEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::EntityCombustEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::EntityCombustEvent(data)
|
||||
}
|
||||
}
|
||||
21
crates/pumpkin-plugin-api/src/events/entity/entity_damage.rs
Normal file
21
crates/pumpkin-plugin-api/src/events/entity/entity_damage.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{EntityDamageEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// Event triggered when an entity receives damage.
|
||||
pub struct EntityDamageEvent;
|
||||
impl FromIntoEvent for EntityDamageEvent {
|
||||
const EVENT_TYPE: EventType = EventType::EntityDamageEvent;
|
||||
type Data = EntityDamageEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::EntityDamageEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::EntityDamageEvent(data)
|
||||
}
|
||||
}
|
||||
41
crates/pumpkin-plugin-api/src/events/entity/entity_death.rs
Normal file
41
crates/pumpkin-plugin-api/src/events/entity/entity_death.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use crate::wit::pumpkin::plugin::event::{
|
||||
EntityDeathEventData, Event, EventType, PlayerDeathEventData,
|
||||
};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// Event triggered when an entity dies.
|
||||
pub struct EntityDeathEvent;
|
||||
impl FromIntoEvent for EntityDeathEvent {
|
||||
const EVENT_TYPE: EventType = EventType::EntityDeathEvent;
|
||||
type Data = EntityDeathEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::EntityDeathEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::EntityDeathEvent(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Event triggered when a player dies.
|
||||
pub struct PlayerDeathEvent;
|
||||
impl FromIntoEvent for PlayerDeathEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerDeathEvent;
|
||||
type Data = PlayerDeathEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerDeathEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerDeathEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{EntityRegainHealthEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// Event triggered when an entity regains health.
|
||||
pub struct EntityRegainHealthEvent;
|
||||
impl FromIntoEvent for EntityRegainHealthEvent {
|
||||
const EVENT_TYPE: EventType = EventType::EntityRegainHealthEvent;
|
||||
type Data = EntityRegainHealthEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::EntityRegainHealthEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::EntityRegainHealthEvent(data)
|
||||
}
|
||||
}
|
||||
21
crates/pumpkin-plugin-api/src/events/entity/entity_spawn.rs
Normal file
21
crates/pumpkin-plugin-api/src/events/entity/entity_spawn.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{EntitySpawnEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// Event triggered when an entity spawns in the world.
|
||||
pub struct EntitySpawnEvent;
|
||||
impl FromIntoEvent for EntitySpawnEvent {
|
||||
const EVENT_TYPE: EventType = EventType::EntitySpawnEvent;
|
||||
type Data = EntitySpawnEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::EntitySpawnEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::EntitySpawnEvent(data)
|
||||
}
|
||||
}
|
||||
16
crates/pumpkin-plugin-api/src/events/entity/mod.rs
Normal file
16
crates/pumpkin-plugin-api/src/events/entity/mod.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
/// Entity combust (catch fire) event.
|
||||
pub mod entity_combust;
|
||||
/// Entity damage event.
|
||||
pub mod entity_damage;
|
||||
/// Entity death and player death events.
|
||||
pub mod entity_death;
|
||||
/// Entity health regeneration event.
|
||||
pub mod entity_regain_health;
|
||||
/// Entity spawn event.
|
||||
pub mod entity_spawn;
|
||||
|
||||
pub use entity_combust::*;
|
||||
pub use entity_damage::*;
|
||||
pub use entity_death::*;
|
||||
pub use entity_regain_health::*;
|
||||
pub use entity_spawn::*;
|
||||
20
crates/pumpkin-plugin-api/src/events/inventory/craft_item.rs
Normal file
20
crates/pumpkin-plugin-api/src/events/inventory/craft_item.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{CraftItemEventData, Event, EventType};
|
||||
|
||||
/// Event triggered when an item is crafted.
|
||||
pub struct CraftItemEvent;
|
||||
impl FromIntoEvent for CraftItemEvent {
|
||||
const EVENT_TYPE: EventType = EventType::CraftItemEvent;
|
||||
type Data = CraftItemEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::CraftItemEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::CraftItemEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, FurnaceSmeltEventData};
|
||||
|
||||
/// Event triggered when an item is smelted in a furnace.
|
||||
pub struct FurnaceSmeltEvent;
|
||||
impl FromIntoEvent for FurnaceSmeltEvent {
|
||||
const EVENT_TYPE: EventType = EventType::FurnaceSmeltEvent;
|
||||
type Data = FurnaceSmeltEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::FurnaceSmeltEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::FurnaceSmeltEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryDragEventData};
|
||||
|
||||
/// Event triggered when items are dragged in an inventory.
|
||||
pub struct InventoryDragEvent;
|
||||
impl FromIntoEvent for InventoryDragEvent {
|
||||
const EVENT_TYPE: EventType = EventType::InventoryDragEvent;
|
||||
type Data = InventoryDragEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::InventoryDragEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::InventoryDragEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryOpenEventData};
|
||||
|
||||
/// Event triggered when an inventory container is opened.
|
||||
pub struct InventoryOpenEvent;
|
||||
impl FromIntoEvent for InventoryOpenEvent {
|
||||
const EVENT_TYPE: EventType = EventType::InventoryOpenEvent;
|
||||
type Data = InventoryOpenEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::InventoryOpenEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::InventoryOpenEvent(data)
|
||||
}
|
||||
}
|
||||
13
crates/pumpkin-plugin-api/src/events/inventory/mod.rs
Normal file
13
crates/pumpkin-plugin-api/src/events/inventory/mod.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
/// Craft item event.
|
||||
pub mod craft_item;
|
||||
/// Furnace smelt event.
|
||||
pub mod furnace_smelt;
|
||||
/// Inventory drag event.
|
||||
pub mod inventory_drag;
|
||||
/// Inventory open event.
|
||||
pub mod inventory_open;
|
||||
|
||||
pub use craft_item::*;
|
||||
pub use furnace_smelt::*;
|
||||
pub use inventory_drag::*;
|
||||
pub use inventory_open::*;
|
||||
127
crates/pumpkin-plugin-api/src/events/mod.rs
Normal file
127
crates/pumpkin-plugin-api/src/events/mod.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
marker::PhantomData,
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Mutex,
|
||||
atomic::{AtomicU32, Ordering},
|
||||
},
|
||||
};
|
||||
|
||||
pub use crate::wit::pumpkin::plugin::event::{
|
||||
BedrockClientboundPacket, BedrockServerboundPacket, ClientboundPacket, Event, EventPriority,
|
||||
InteractAction, JavaClientboundPacket, JavaServerboundPacket, ServerboundPacket,
|
||||
};
|
||||
use crate::{Context, Result, Server, wit::pumpkin::plugin::event::EventType};
|
||||
|
||||
/// Block events.
|
||||
pub mod block;
|
||||
/// Entity events.
|
||||
pub mod entity;
|
||||
/// Inventory events.
|
||||
pub mod inventory;
|
||||
/// Network packet events.
|
||||
pub mod packet;
|
||||
/// Player events.
|
||||
pub mod player;
|
||||
/// Server lifecycle events.
|
||||
pub mod server;
|
||||
/// World events.
|
||||
pub mod world;
|
||||
|
||||
pub use block::*;
|
||||
pub use entity::*;
|
||||
pub use inventory::*;
|
||||
pub use packet::*;
|
||||
pub use player::*;
|
||||
pub use server::*;
|
||||
pub use world::*;
|
||||
|
||||
pub(crate) static NEXT_HANDLER_ID: AtomicU32 = AtomicU32::new(0);
|
||||
pub(crate) static EVENT_HANDLERS: Mutex<BTreeMap<u32, Box<dyn ErasedEventHandler>>> =
|
||||
Mutex::new(BTreeMap::new());
|
||||
|
||||
/// Connects an event marker type to its WIT-generated data type and [`EventType`] discriminant.
|
||||
///
|
||||
/// Implement this trait for a unit struct to define a new event. The [`EventType`] constant
|
||||
/// tells the host which event to subscribe to, while `data_from_event` and `data_into_event`
|
||||
/// provide the conversions between the opaque [`Event`] variant and the concrete data type.
|
||||
pub trait FromIntoEvent: Sized {
|
||||
/// The discriminant used by the host to identify this event.
|
||||
const EVENT_TYPE: EventType;
|
||||
|
||||
/// The WIT-generated data record carried by this event.
|
||||
type Data;
|
||||
|
||||
/// Extracts the event data from an [`Event`] variant.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if the [`Event`] variant does not match [`Self::EVENT_TYPE`].
|
||||
fn data_from_event(event: Event) -> Self::Data;
|
||||
|
||||
/// Wraps event data back into the corresponding [`Event`] variant.
|
||||
fn data_into_event(data: Self::Data) -> Event;
|
||||
}
|
||||
|
||||
/// A convenience alias for the data type associated with an event.
|
||||
pub type EventData<E> = <E as FromIntoEvent>::Data;
|
||||
|
||||
/// A type alias for a pinned, boxed, dynamically-dispatched future.
|
||||
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
|
||||
/// A handler for a specific event type.
|
||||
///
|
||||
/// Implement this trait to process an event. The `handle` method receives the server
|
||||
/// handle and the event data, and returns the (potentially modified) event data.
|
||||
pub trait EventHandler<E: FromIntoEvent> {
|
||||
/// Processes the event and returns the (potentially modified) data.
|
||||
fn handle(&self, server: Server, event: E::Data) -> E::Data;
|
||||
}
|
||||
|
||||
pub(crate) trait ErasedEventHandler: Send + Sync {
|
||||
fn handle_erased(&self, server: Server, event: Event) -> Event;
|
||||
}
|
||||
|
||||
struct HandlerWrapper<E: FromIntoEvent, H> {
|
||||
handler: H,
|
||||
_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E: FromIntoEvent + Send + Sync, H: EventHandler<E> + Send + Sync> ErasedEventHandler
|
||||
for HandlerWrapper<E, H>
|
||||
{
|
||||
fn handle_erased(&self, server: Server, event: Event) -> Event {
|
||||
let data = E::data_from_event(event);
|
||||
let result = self.handler.handle(server, data);
|
||||
E::data_into_event(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Registers an event handler with the plugin.
|
||||
///
|
||||
/// The handler must implement the [`EventHandler`] trait.
|
||||
/// If the event is blocking, returning an event from the handler will modify the event.
|
||||
pub fn register_event_handler<
|
||||
E: FromIntoEvent + Send + Sync + 'static,
|
||||
H: EventHandler<E> + Send + Sync + 'static,
|
||||
>(
|
||||
&self,
|
||||
handler: H,
|
||||
event_priority: EventPriority,
|
||||
blocking: bool,
|
||||
) -> Result<u32> {
|
||||
let id = NEXT_HANDLER_ID.fetch_add(1, Ordering::Relaxed);
|
||||
let wrapped = HandlerWrapper {
|
||||
handler,
|
||||
_phantom: PhantomData::<E>,
|
||||
};
|
||||
EVENT_HANDLERS
|
||||
.lock()
|
||||
.map_err(|e| e.to_string())?
|
||||
.insert(id, Box::new(wrapped));
|
||||
|
||||
self.register_event(id, E::EVENT_TYPE, event_priority, blocking);
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
42
crates/pumpkin-plugin-api/src/events/packet.rs
Normal file
42
crates/pumpkin-plugin-api/src/events/packet.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{
|
||||
Event, EventType, PacketReceivedEventData, PacketSentEventData,
|
||||
};
|
||||
|
||||
/// An event fired when a packet is received from a client
|
||||
pub struct PacketReceivedEvent;
|
||||
|
||||
impl FromIntoEvent for PacketReceivedEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PacketReceivedEvent;
|
||||
type Data = PacketReceivedEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PacketReceivedEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PacketReceivedEvent(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// An event fired when a packet is sent to a client
|
||||
pub struct PacketSentEvent;
|
||||
|
||||
impl FromIntoEvent for PacketSentEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PacketSentEvent;
|
||||
type Data = PacketSentEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PacketSentEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PacketSentEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{BedrockFormResponseEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player responds to a Bedrock custom form.
|
||||
pub struct BedrockFormResponseEvent;
|
||||
impl FromIntoEvent for BedrockFormResponseEvent {
|
||||
const EVENT_TYPE: EventType = EventType::BedrockFormResponseEvent;
|
||||
type Data = BedrockFormResponseEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::BedrockFormResponseEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::BedrockFormResponseEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerChangedMainHandEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player changes their main hand in the settings.
|
||||
///
|
||||
/// The associated [`PlayerChangedMainHandEventData`] contains the player and their
|
||||
/// newly selected main hand.
|
||||
pub struct PlayerChangedMainHandEvent;
|
||||
impl FromIntoEvent for PlayerChangedMainHandEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerChangedMainHandEvent;
|
||||
type Data = PlayerChangedMainHandEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerChangedMainHandEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerChangedMainHandEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::wit::pumpkin::plugin::event::{CustomClickActionEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player clicks a custom dialog button.
|
||||
pub struct CustomClickActionEvent;
|
||||
|
||||
impl FromIntoEvent for CustomClickActionEvent {
|
||||
const EVENT_TYPE: EventType = EventType::CustomClickActionEvent;
|
||||
type Data = CustomClickActionEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::CustomClickActionEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::CustomClickActionEvent(data)
|
||||
}
|
||||
}
|
||||
25
crates/pumpkin-plugin-api/src/events/player/egg_throw.rs
Normal file
25
crates/pumpkin-plugin-api/src/events/player/egg_throw.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerEggThrowEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a thrown egg resolves.
|
||||
///
|
||||
/// The associated [`PlayerEggThrowEventData`] contains the player, the egg entity UUID,
|
||||
/// whether the egg hatched, how many entities hatched, and the entity type to hatch.
|
||||
/// This event is cancellable.
|
||||
pub struct PlayerEggThrowEvent;
|
||||
impl FromIntoEvent for PlayerEggThrowEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerEggThrowEvent;
|
||||
type Data = PlayerEggThrowEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerEggThrowEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerEggThrowEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/player/exp_change.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/player/exp_change.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerExpChangeEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player's experience changes.
|
||||
///
|
||||
/// The associated [`PlayerExpChangeEventData`] contains the player and the amount of
|
||||
/// experience being added (can be negative).
|
||||
pub struct PlayerExpChangeEvent;
|
||||
impl FromIntoEvent for PlayerExpChangeEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerExpChangeEvent;
|
||||
type Data = PlayerExpChangeEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerExpChangeEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerExpChangeEvent(data)
|
||||
}
|
||||
}
|
||||
25
crates/pumpkin-plugin-api/src/events/player/fish.rs
Normal file
25
crates/pumpkin-plugin-api/src/events/player/fish.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerFishEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs during a fishing action.
|
||||
///
|
||||
/// The associated [`PlayerFishEventData`] contains the player, the fishing state,
|
||||
/// the hand used, the hook entity, optionally the caught entity, and the experience
|
||||
/// to drop. This event is cancellable.
|
||||
pub struct PlayerFishEvent;
|
||||
impl FromIntoEvent for PlayerFishEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerFishEvent;
|
||||
type Data = PlayerFishEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerFishEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerFishEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryClickEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player clicks a slot in an inventory.
|
||||
pub struct InventoryClickEvent;
|
||||
|
||||
impl FromIntoEvent for InventoryClickEvent {
|
||||
const EVENT_TYPE: EventType = EventType::InventoryClickEvent;
|
||||
type Data = InventoryClickEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::InventoryClickEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::InventoryClickEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryCloseEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player closes an inventory.
|
||||
pub struct InventoryCloseEvent;
|
||||
|
||||
impl FromIntoEvent for InventoryCloseEvent {
|
||||
const EVENT_TYPE: EventType = EventType::InventoryCloseEvent;
|
||||
type Data = InventoryCloseEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::InventoryCloseEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::InventoryCloseEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/player/item_held.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/player/item_held.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerItemHeldEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player changes the selected hotbar slot.
|
||||
///
|
||||
/// The associated [`PlayerItemHeldEventData`] contains the player, the previous slot index,
|
||||
/// and the new slot index. This event is cancellable.
|
||||
pub struct PlayerItemHeldEvent;
|
||||
impl FromIntoEvent for PlayerItemHeldEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerItemHeldEvent;
|
||||
type Data = PlayerItemHeldEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerItemHeldEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerItemHeldEvent(data)
|
||||
}
|
||||
}
|
||||
97
crates/pumpkin-plugin-api/src/events/player/mod.rs
Normal file
97
crates/pumpkin-plugin-api/src/events/player/mod.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
/// Bedrock form response event.
|
||||
pub mod bedrock_form_response;
|
||||
/// Player main hand change event.
|
||||
pub mod changed_main_hand;
|
||||
/// Custom inventory click action event.
|
||||
pub mod custom_click_action;
|
||||
/// Egg throw event.
|
||||
pub mod egg_throw;
|
||||
/// Experience change event.
|
||||
pub mod exp_change;
|
||||
/// Player fish event.
|
||||
pub mod fish;
|
||||
/// Inventory click event.
|
||||
pub mod inventory_click;
|
||||
/// Inventory close event.
|
||||
pub mod inventory_close;
|
||||
/// Item held slot change event.
|
||||
pub mod item_held;
|
||||
/// Player bed enter and leave events.
|
||||
pub mod player_bed;
|
||||
/// Player bucket empty and fill events.
|
||||
pub mod player_bucket;
|
||||
/// Player world change event.
|
||||
pub mod player_change_world;
|
||||
/// Player chat event.
|
||||
pub mod player_chat;
|
||||
/// Player command send event.
|
||||
pub mod player_command_send;
|
||||
/// Player custom payload event.
|
||||
pub mod player_custom_payload;
|
||||
/// Player drop item event.
|
||||
pub mod player_drop_item;
|
||||
/// Player gamemode change event.
|
||||
pub mod player_gamemode_change;
|
||||
/// Player interact block event.
|
||||
pub mod player_interact;
|
||||
/// Player interact entity event.
|
||||
pub mod player_interact_entity;
|
||||
/// Player interact unknown entity event.
|
||||
pub mod player_interact_unknown_entity;
|
||||
/// Player item consume event.
|
||||
pub mod player_item_consume;
|
||||
/// Player item damage event.
|
||||
pub mod player_item_damage;
|
||||
/// Player join event.
|
||||
pub mod player_join;
|
||||
/// Player leave event.
|
||||
pub mod player_leave;
|
||||
/// Player login event.
|
||||
pub mod player_login;
|
||||
/// Player move event.
|
||||
pub mod player_move;
|
||||
/// Player permission check event.
|
||||
pub mod player_permission_check;
|
||||
/// Player respawn event.
|
||||
pub mod player_respawn;
|
||||
/// Player teleport event.
|
||||
pub mod player_teleport;
|
||||
/// Player toggle flight event.
|
||||
pub mod player_toggle_flight;
|
||||
/// Player toggle sneak event.
|
||||
pub mod player_toggle_sneak;
|
||||
/// Player toggle sprint event.
|
||||
pub mod player_toggle_sprint;
|
||||
|
||||
pub use bedrock_form_response::*;
|
||||
pub use changed_main_hand::*;
|
||||
pub use custom_click_action::*;
|
||||
pub use egg_throw::*;
|
||||
pub use exp_change::*;
|
||||
pub use fish::*;
|
||||
pub use inventory_click::*;
|
||||
pub use inventory_close::*;
|
||||
pub use item_held::*;
|
||||
pub use player_bed::*;
|
||||
pub use player_bucket::*;
|
||||
pub use player_change_world::*;
|
||||
pub use player_chat::*;
|
||||
pub use player_command_send::*;
|
||||
pub use player_custom_payload::*;
|
||||
pub use player_drop_item::*;
|
||||
pub use player_gamemode_change::*;
|
||||
pub use player_interact::*;
|
||||
pub use player_interact_entity::*;
|
||||
pub use player_interact_unknown_entity::*;
|
||||
pub use player_item_consume::*;
|
||||
pub use player_item_damage::*;
|
||||
pub use player_join::*;
|
||||
pub use player_leave::*;
|
||||
pub use player_login::*;
|
||||
pub use player_move::*;
|
||||
pub use player_permission_check::*;
|
||||
pub use player_respawn::*;
|
||||
pub use player_teleport::*;
|
||||
pub use player_toggle_flight::*;
|
||||
pub use player_toggle_sneak::*;
|
||||
pub use player_toggle_sprint::*;
|
||||
40
crates/pumpkin-plugin-api/src/events/player/player_bed.rs
Normal file
40
crates/pumpkin-plugin-api/src/events/player/player_bed.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{
|
||||
Event, EventType, PlayerBedEnterEventData, PlayerBedLeaveEventData,
|
||||
};
|
||||
|
||||
/// Event triggered when a player enters a bed.
|
||||
pub struct PlayerBedEnterEvent;
|
||||
impl FromIntoEvent for PlayerBedEnterEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerBedEnterEvent;
|
||||
type Data = PlayerBedEnterEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerBedEnterEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerBedEnterEvent(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Event triggered when a player leaves a bed.
|
||||
pub struct PlayerBedLeaveEvent;
|
||||
impl FromIntoEvent for PlayerBedLeaveEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerBedLeaveEvent;
|
||||
type Data = PlayerBedLeaveEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerBedLeaveEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerBedLeaveEvent(data)
|
||||
}
|
||||
}
|
||||
40
crates/pumpkin-plugin-api/src/events/player/player_bucket.rs
Normal file
40
crates/pumpkin-plugin-api/src/events/player/player_bucket.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{
|
||||
Event, EventType, PlayerBucketEmptyEventData, PlayerBucketFillEventData,
|
||||
};
|
||||
|
||||
/// Event triggered when a player empties a bucket.
|
||||
pub struct PlayerBucketEmptyEvent;
|
||||
impl FromIntoEvent for PlayerBucketEmptyEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerBucketEmptyEvent;
|
||||
type Data = PlayerBucketEmptyEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerBucketEmptyEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerBucketEmptyEvent(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Event triggered when a player fills a bucket.
|
||||
pub struct PlayerBucketFillEvent;
|
||||
impl FromIntoEvent for PlayerBucketFillEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerBucketFillEvent;
|
||||
type Data = PlayerBucketFillEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerBucketFillEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerBucketFillEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerChangeWorldEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player changes worlds.
|
||||
///
|
||||
/// The associated [`PlayerChangeWorldEventData`] contains the player, the previous world,
|
||||
/// the new world, and the destination position, yaw, and pitch. This event is cancellable.
|
||||
pub struct PlayerChangeWorldEvent;
|
||||
impl FromIntoEvent for PlayerChangeWorldEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerChangeWorldEvent;
|
||||
type Data = PlayerChangeWorldEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerChangeWorldEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerChangeWorldEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/player/player_chat.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/player/player_chat.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerChatEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player sends a chat message.
|
||||
///
|
||||
/// The associated [`PlayerChatEventData`] contains the player, the message, and
|
||||
/// the list of recipients. The message can be modified. This event is cancellable.
|
||||
pub struct PlayerChatEvent;
|
||||
impl FromIntoEvent for PlayerChatEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerChatEvent;
|
||||
type Data = PlayerChatEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerChatEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerChatEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerCommandSendEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player sends a command.
|
||||
///
|
||||
/// The associated [`PlayerCommandSendEventData`] contains the player and the command
|
||||
/// string (without the leading `/`). This event is cancellable.
|
||||
pub struct PlayerCommandSendEvent;
|
||||
impl FromIntoEvent for PlayerCommandSendEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerCommandSendEvent;
|
||||
type Data = PlayerCommandSendEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerCommandSendEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerCommandSendEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerCustomPayloadEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player sends a custom plugin channel payload.
|
||||
///
|
||||
/// The associated [`PlayerCustomPayloadEventData`] contains the player, the channel
|
||||
/// identifier, and the raw payload bytes.
|
||||
pub struct PlayerCustomPayloadEvent;
|
||||
impl FromIntoEvent for PlayerCustomPayloadEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerCustomPayloadEvent;
|
||||
type Data = PlayerCustomPayloadEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerCustomPayloadEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerCustomPayloadEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerDropItemEventData};
|
||||
|
||||
/// Event triggered when a player drops an item.
|
||||
pub struct PlayerDropItemEvent;
|
||||
impl FromIntoEvent for PlayerDropItemEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerDropItemEvent;
|
||||
type Data = PlayerDropItemEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerDropItemEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerDropItemEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerGamemodeChangeEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player's game mode changes.
|
||||
///
|
||||
/// The associated [`PlayerGamemodeChangeEventData`] contains the player, the previous
|
||||
/// game mode, and the new game mode. This event is cancellable.
|
||||
pub struct PlayerGamemodeChangeEvent;
|
||||
impl FromIntoEvent for PlayerGamemodeChangeEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerGamemodeChangeEvent;
|
||||
type Data = PlayerGamemodeChangeEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerGamemodeChangeEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerGamemodeChangeEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerInteractEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player interacts.
|
||||
pub struct PlayerInteractEvent;
|
||||
impl FromIntoEvent for PlayerInteractEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerInteractEvent;
|
||||
type Data = PlayerInteractEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerInteractEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerInteractEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerInteractEntityEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player interacts with an entity.
|
||||
pub struct PlayerInteractEntityEvent;
|
||||
|
||||
impl FromIntoEvent for PlayerInteractEntityEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerInteractEntityEvent;
|
||||
type Data = PlayerInteractEntityEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerInteractEntityEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerInteractEntityEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerInteractUnknownEntityEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player interacts with an entity ID that the server cannot resolve.
|
||||
///
|
||||
/// The associated [`PlayerInteractUnknownEntityEventData`] contains the player, the unknown
|
||||
/// entity ID, and the attempted interaction action. This event is cancellable.
|
||||
pub struct PlayerInteractUnknownEntityEvent;
|
||||
|
||||
impl FromIntoEvent for PlayerInteractUnknownEntityEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerInteractUnknownEntityEvent;
|
||||
type Data = PlayerInteractUnknownEntityEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerInteractUnknownEntityEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerInteractUnknownEntityEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerItemConsumeEventData};
|
||||
|
||||
/// Event triggered when a player consumes an item.
|
||||
pub struct PlayerItemConsumeEvent;
|
||||
impl FromIntoEvent for PlayerItemConsumeEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerItemConsumeEvent;
|
||||
type Data = PlayerItemConsumeEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerItemConsumeEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerItemConsumeEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerItemDamageEventData};
|
||||
|
||||
/// Event triggered when a player's held item receives damage.
|
||||
pub struct PlayerItemDamageEvent;
|
||||
impl FromIntoEvent for PlayerItemDamageEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerItemDamageEvent;
|
||||
type Data = PlayerItemDamageEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerItemDamageEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerItemDamageEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/player/player_join.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/player/player_join.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerJoinEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player joins the server.
|
||||
///
|
||||
/// The associated [`PlayerJoinEventData`] contains the player and a join message
|
||||
/// that can be modified or suppressed. This event is cancellable.
|
||||
pub struct PlayerJoinEvent;
|
||||
impl FromIntoEvent for PlayerJoinEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerJoinEvent;
|
||||
type Data = PlayerJoinEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerJoinEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerJoinEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/player/player_leave.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/player/player_leave.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerLeaveEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player leaves the server.
|
||||
///
|
||||
/// The associated [`PlayerLeaveEventData`] contains the player and a leave message
|
||||
/// that can be modified or suppressed. This event is cancellable.
|
||||
pub struct PlayerLeaveEvent;
|
||||
impl FromIntoEvent for PlayerLeaveEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerLeaveEvent;
|
||||
type Data = PlayerLeaveEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerLeaveEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerLeaveEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/player/player_login.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/player/player_login.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerLoginEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player attempts to log in to the server.
|
||||
///
|
||||
/// The associated [`PlayerLoginEventData`] contains the player and a kick message
|
||||
/// used if the login is cancelled. This event is cancellable.
|
||||
pub struct PlayerLoginEvent;
|
||||
impl FromIntoEvent for PlayerLoginEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerLoginEvent;
|
||||
type Data = PlayerLoginEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerLoginEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerLoginEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/player/player_move.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/player/player_move.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerMoveEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player moves.
|
||||
///
|
||||
/// The associated [`PlayerMoveEventData`] contains the player, the position moved from,
|
||||
/// and the position moved to. This event is cancellable.
|
||||
pub struct PlayerMoveEvent;
|
||||
impl FromIntoEvent for PlayerMoveEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerMoveEvent;
|
||||
type Data = PlayerMoveEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerMoveEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerMoveEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerPermissionCheckEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a permission check is performed for a player.
|
||||
///
|
||||
/// The associated [`PlayerPermissionCheckEventData`] contains the player, the permission
|
||||
/// node being checked, and the current result which can be overridden.
|
||||
pub struct PlayerPermissionCheckEvent;
|
||||
impl FromIntoEvent for PlayerPermissionCheckEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerPermissionCheckEvent;
|
||||
type Data = PlayerPermissionCheckEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerPermissionCheckEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerPermissionCheckEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerRespawnEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player respawns.
|
||||
///
|
||||
/// The associated [`PlayerRespawnEventData`] contains the player, the world they
|
||||
/// respawned from, the world they respawned into, and the destination position,
|
||||
/// yaw and pitch. This event is not cancellable.
|
||||
pub struct PlayerRespawnEvent;
|
||||
impl FromIntoEvent for PlayerRespawnEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerRespawnEvent;
|
||||
type Data = PlayerRespawnEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerRespawnEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerRespawnEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerTeleportEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player is teleported.
|
||||
///
|
||||
/// The associated [`PlayerTeleportEventData`] contains the player, the origin position,
|
||||
/// and the destination position. This event is cancellable.
|
||||
pub struct PlayerTeleportEvent;
|
||||
impl FromIntoEvent for PlayerTeleportEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerTeleportEvent;
|
||||
type Data = PlayerTeleportEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerTeleportEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerTeleportEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerToggleFlightEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player toggles flight.
|
||||
pub struct PlayerToggleFlightEvent;
|
||||
impl FromIntoEvent for PlayerToggleFlightEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerToggleFlightEvent;
|
||||
type Data = PlayerToggleFlightEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerToggleFlightEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerToggleFlightEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerToggleSneakEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player toggles sneak.
|
||||
pub struct PlayerToggleSneakEvent;
|
||||
impl FromIntoEvent for PlayerToggleSneakEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerToggleSneakEvent;
|
||||
type Data = PlayerToggleSneakEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerToggleSneakEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerToggleSneakEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerToggleSprintEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a player toggles sprint.
|
||||
pub struct PlayerToggleSprintEvent;
|
||||
impl FromIntoEvent for PlayerToggleSprintEvent {
|
||||
const EVENT_TYPE: EventType = EventType::PlayerToggleSprintEvent;
|
||||
type Data = PlayerToggleSprintEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::PlayerToggleSprintEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::PlayerToggleSprintEvent(data)
|
||||
}
|
||||
}
|
||||
19
crates/pumpkin-plugin-api/src/events/server/mod.rs
Normal file
19
crates/pumpkin-plugin-api/src/events/server/mod.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
/// Server broadcast event.
|
||||
pub mod server_broadcast;
|
||||
/// Server command execution event.
|
||||
pub mod server_command;
|
||||
/// Server initialization load event.
|
||||
pub mod server_load;
|
||||
/// Server tick completion event.
|
||||
pub mod server_tick_end;
|
||||
/// Server tick start event.
|
||||
pub mod server_tick_start;
|
||||
/// Server spawn point change event.
|
||||
pub mod spawn_change;
|
||||
|
||||
pub use server_broadcast::*;
|
||||
pub use server_command::*;
|
||||
pub use server_load::*;
|
||||
pub use server_tick_end::*;
|
||||
pub use server_tick_start::*;
|
||||
pub use spawn_change::*;
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, ServerBroadcastEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a message is broadcast to all players on the server.
|
||||
///
|
||||
/// The associated [`ServerBroadcastEventData`] contains the message and the sender.
|
||||
/// This event is cancellable.
|
||||
pub struct ServerBroadcastEvent;
|
||||
impl FromIntoEvent for ServerBroadcastEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ServerBroadcastEvent;
|
||||
type Data = ServerBroadcastEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ServerBroadcastEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ServerBroadcastEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, ServerCommandEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a command is executed from the server console.
|
||||
///
|
||||
/// The associated [`ServerCommandEventData`] contains the command string.
|
||||
/// This event is cancellable.
|
||||
pub struct ServerCommandEvent;
|
||||
impl FromIntoEvent for ServerCommandEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ServerCommandEvent;
|
||||
type Data = ServerCommandEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ServerCommandEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ServerCommandEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/server/server_load.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/server/server_load.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, ServerLoadEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that fires once the server has finished loading.
|
||||
///
|
||||
/// The associated [`ServerLoadEventData`] contains the load reason:
|
||||
/// startup or a full server reload.
|
||||
pub struct ServerLoadEvent;
|
||||
impl FromIntoEvent for ServerLoadEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ServerLoadEvent;
|
||||
type Data = ServerLoadEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ServerLoadEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ServerLoadEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, ServerTickEndEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that fires at the end of every server tick.
|
||||
///
|
||||
/// The associated [`ServerTickEndEventData`] carries:
|
||||
/// - `tick`: the 0-indexed number of the tick that just finished.
|
||||
/// - `duration_nanos`: how long the tick took, measured from the start of
|
||||
/// the ticker iteration to just after `Server::tick` returned.
|
||||
///
|
||||
/// This event is non-cancellable.
|
||||
pub struct ServerTickEndEvent;
|
||||
impl FromIntoEvent for ServerTickEndEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ServerTickEndEvent;
|
||||
type Data = ServerTickEndEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ServerTickEndEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ServerTickEndEvent(data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, ServerTickStartEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that fires at the start of every server tick (~20 Hz under the
|
||||
/// default tick rate).
|
||||
///
|
||||
/// The associated [`ServerTickStartEventData`] carries the 0-indexed `tick`
|
||||
/// number of the tick about to run. This event is non-cancellable.
|
||||
pub struct ServerTickStartEvent;
|
||||
impl FromIntoEvent for ServerTickStartEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ServerTickStartEvent;
|
||||
type Data = ServerTickStartEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ServerTickStartEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ServerTickStartEvent(data)
|
||||
}
|
||||
}
|
||||
24
crates/pumpkin-plugin-api/src/events/server/spawn_change.rs
Normal file
24
crates/pumpkin-plugin-api/src/events/server/spawn_change.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::wit::pumpkin::plugin::event::{Event, EventType, SpawnChangeEventData};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when the world spawn point changes.
|
||||
///
|
||||
/// The associated [`SpawnChangeEventData`] contains the world, the previous spawn
|
||||
/// position, yaw and pitch, and the new spawn position, yaw and pitch.
|
||||
pub struct SpawnChangeEvent;
|
||||
impl FromIntoEvent for SpawnChangeEvent {
|
||||
const EVENT_TYPE: EventType = EventType::SpawnChangeEvent;
|
||||
type Data = SpawnChangeEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::SpawnChangeEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::SpawnChangeEvent(data)
|
||||
}
|
||||
}
|
||||
22
crates/pumpkin-plugin-api/src/events/world/chunk_load.rs
Normal file
22
crates/pumpkin-plugin-api/src/events/world/chunk_load.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use crate::wit::pumpkin::plugin::event::{ChunkLoadEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a chunk is loaded in a world.
|
||||
pub struct ChunkLoadEvent;
|
||||
|
||||
impl FromIntoEvent for ChunkLoadEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ChunkLoadEvent;
|
||||
type Data = ChunkLoadEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ChunkLoadEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ChunkLoadEvent(data)
|
||||
}
|
||||
}
|
||||
22
crates/pumpkin-plugin-api/src/events/world/chunk_save.rs
Normal file
22
crates/pumpkin-plugin-api/src/events/world/chunk_save.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use crate::wit::pumpkin::plugin::event::{ChunkSaveEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a chunk is saved in a world.
|
||||
pub struct ChunkSaveEvent;
|
||||
|
||||
impl FromIntoEvent for ChunkSaveEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ChunkSaveEvent;
|
||||
type Data = ChunkSaveEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ChunkSaveEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ChunkSaveEvent(data)
|
||||
}
|
||||
}
|
||||
22
crates/pumpkin-plugin-api/src/events/world/chunk_send.rs
Normal file
22
crates/pumpkin-plugin-api/src/events/world/chunk_send.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use crate::wit::pumpkin::plugin::event::{ChunkSendEventData, Event, EventType};
|
||||
|
||||
use super::super::FromIntoEvent;
|
||||
|
||||
/// An event that occurs when a chunk is sent to a client.
|
||||
pub struct ChunkSendEvent;
|
||||
|
||||
impl FromIntoEvent for ChunkSendEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ChunkSendEvent;
|
||||
type Data = ChunkSendEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ChunkSendEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ChunkSendEvent(data)
|
||||
}
|
||||
}
|
||||
16
crates/pumpkin-plugin-api/src/events/world/mod.rs
Normal file
16
crates/pumpkin-plugin-api/src/events/world/mod.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
/// Chunk load event.
|
||||
pub mod chunk_load;
|
||||
/// Chunk save event.
|
||||
pub mod chunk_save;
|
||||
/// Chunk send packet event.
|
||||
pub mod chunk_send;
|
||||
/// Weather and thunder change events.
|
||||
pub mod weather_change;
|
||||
/// World load and unload events.
|
||||
pub mod world_load;
|
||||
|
||||
pub use chunk_load::*;
|
||||
pub use chunk_save::*;
|
||||
pub use chunk_send::*;
|
||||
pub use weather_change::*;
|
||||
pub use world_load::*;
|
||||
40
crates/pumpkin-plugin-api/src/events/world/weather_change.rs
Normal file
40
crates/pumpkin-plugin-api/src/events/world/weather_change.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{
|
||||
Event, EventType, ThunderChangeEventData, WeatherChangeEventData,
|
||||
};
|
||||
|
||||
/// Event triggered when world weather changes.
|
||||
pub struct WeatherChangeEvent;
|
||||
impl FromIntoEvent for WeatherChangeEvent {
|
||||
const EVENT_TYPE: EventType = EventType::WeatherChangeEvent;
|
||||
type Data = WeatherChangeEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::WeatherChangeEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::WeatherChangeEvent(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Event triggered when thunderstorm state changes.
|
||||
pub struct ThunderChangeEvent;
|
||||
impl FromIntoEvent for ThunderChangeEvent {
|
||||
const EVENT_TYPE: EventType = EventType::ThunderChangeEvent;
|
||||
type Data = ThunderChangeEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::ThunderChangeEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::ThunderChangeEvent(data)
|
||||
}
|
||||
}
|
||||
40
crates/pumpkin-plugin-api/src/events/world/world_load.rs
Normal file
40
crates/pumpkin-plugin-api/src/events/world/world_load.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use super::super::FromIntoEvent;
|
||||
use crate::wit::pumpkin::plugin::event::{
|
||||
Event, EventType, WorldLoadEventData, WorldUnloadEventData,
|
||||
};
|
||||
|
||||
/// Event triggered when a world is loaded.
|
||||
pub struct WorldLoadEvent;
|
||||
impl FromIntoEvent for WorldLoadEvent {
|
||||
const EVENT_TYPE: EventType = EventType::WorldLoadEvent;
|
||||
type Data = WorldLoadEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::WorldLoadEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::WorldLoadEvent(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Event triggered when a world is unloaded.
|
||||
pub struct WorldUnloadEvent;
|
||||
impl FromIntoEvent for WorldUnloadEvent {
|
||||
const EVENT_TYPE: EventType = EventType::WorldUnloadEvent;
|
||||
type Data = WorldUnloadEventData;
|
||||
|
||||
fn data_from_event(event: Event) -> Self::Data {
|
||||
match event {
|
||||
Event::WorldUnloadEvent(data) => data,
|
||||
_ => panic!("unexpected event"),
|
||||
}
|
||||
}
|
||||
|
||||
fn data_into_event(data: Self::Data) -> Event {
|
||||
Event::WorldUnloadEvent(data)
|
||||
}
|
||||
}
|
||||
3
crates/pumpkin-plugin-api/src/ext/mod.rs
Normal file
3
crates/pumpkin-plugin-api/src/ext/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
//! WIT-generated plugin type extensions belong in here. For example [Display](std::fmt::Display) implementations.
|
||||
|
||||
mod uuid;
|
||||
32
crates/pumpkin-plugin-api/src/ext/uuid.rs
Normal file
32
crates/pumpkin-plugin-api/src/ext/uuid.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::wit::pumpkin::plugin::uuid::Uuid;
|
||||
|
||||
impl fmt::Display for Uuid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
|
||||
(self.high >> 32) as u32,
|
||||
((self.high >> 16) & 0xffff) as u16,
|
||||
(self.high & 0xffff) as u16,
|
||||
(self.low >> 48) as u16,
|
||||
self.low & 0x0000_ffff_ffff_ffff,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn formats_uuid_correctly() {
|
||||
let uuid = Uuid {
|
||||
high: 0x0011223344556677,
|
||||
low: 0x8899aabbccddeeff,
|
||||
};
|
||||
|
||||
assert_eq!(uuid.to_string(), "00112233-4455-6677-8899-aabbccddeeff");
|
||||
}
|
||||
}
|
||||
240
crates/pumpkin-plugin-api/src/forms.rs
Normal file
240
crates/pumpkin-plugin-api/src/forms.rs
Normal file
@@ -0,0 +1,240 @@
|
||||
use crate::text::TextComponent;
|
||||
use crate::wit::pumpkin::plugin::forms::{
|
||||
CustomForm, CustomFormElement, Form, FormImage, ImageType, ModalForm, SimpleForm,
|
||||
SimpleFormButton,
|
||||
};
|
||||
|
||||
/// Builder for creating a Bedrock simple form.
|
||||
pub struct SimpleFormBuilder {
|
||||
title: TextComponent,
|
||||
content: TextComponent,
|
||||
buttons: Vec<SimpleFormButton>,
|
||||
}
|
||||
|
||||
impl SimpleFormBuilder {
|
||||
/// Creates a new simple form builder with a title and main content text.
|
||||
pub fn new(title: impl Into<TextComponent>, content: impl Into<TextComponent>) -> Self {
|
||||
Self {
|
||||
title: title.into(),
|
||||
content: content.into(),
|
||||
buttons: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a button to the simple form.
|
||||
pub fn button(mut self, text: impl Into<TextComponent>, image: Option<FormImage>) -> Self {
|
||||
self.buttons.push(SimpleFormButton {
|
||||
text: text.into(),
|
||||
image,
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds the final simple form instance.
|
||||
pub fn build(self) -> Form {
|
||||
Form::Simple(SimpleForm {
|
||||
title: self.title,
|
||||
content: self.content,
|
||||
buttons: self.buttons,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Builder for creating a Bedrock modal form (two-button dialog).
|
||||
pub struct ModalFormBuilder {
|
||||
title: TextComponent,
|
||||
content: TextComponent,
|
||||
button1: TextComponent,
|
||||
button2: TextComponent,
|
||||
}
|
||||
|
||||
impl ModalFormBuilder {
|
||||
/// Creates a new modal form builder with a title and main content text.
|
||||
pub fn new(title: impl Into<TextComponent>, content: impl Into<TextComponent>) -> Self {
|
||||
Self {
|
||||
title: title.into(),
|
||||
content: content.into(),
|
||||
button1: TextComponent::translate("gui.yes", vec![]),
|
||||
button2: TextComponent::translate("gui.no", vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the label for the first button (confirm).
|
||||
pub fn button1(mut self, text: impl Into<TextComponent>) -> Self {
|
||||
self.button1 = text.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the label for the second button (cancel).
|
||||
pub fn button2(mut self, text: impl Into<TextComponent>) -> Self {
|
||||
self.button2 = text.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds the final modal form instance.
|
||||
pub fn build(self) -> Form {
|
||||
Form::Modal(ModalForm {
|
||||
title: self.title,
|
||||
content: self.content,
|
||||
button1: self.button1,
|
||||
button2: self.button2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Builder for creating a Bedrock custom form with multiple input elements.
|
||||
pub struct CustomFormBuilder {
|
||||
title: TextComponent,
|
||||
elements: Vec<CustomFormElement>,
|
||||
}
|
||||
|
||||
impl CustomFormBuilder {
|
||||
/// Creates a new custom form builder with a title.
|
||||
pub fn new(title: impl Into<TextComponent>) -> Self {
|
||||
Self {
|
||||
title: title.into(),
|
||||
elements: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a text label element to the form.
|
||||
pub fn label(mut self, text: impl Into<TextComponent>) -> Self {
|
||||
self.elements.push(CustomFormElement::Label(text.into()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a toggle (switch) element to the form.
|
||||
pub fn toggle(mut self, text: impl Into<TextComponent>, default: bool) -> Self {
|
||||
self.elements
|
||||
.push(CustomFormElement::Toggle((text.into(), default)));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a numeric slider element to the form.
|
||||
pub fn slider(
|
||||
mut self,
|
||||
text: impl Into<TextComponent>,
|
||||
min: f32,
|
||||
max: f32,
|
||||
step: f32,
|
||||
default: f32,
|
||||
) -> Self {
|
||||
self.elements.push(CustomFormElement::Slider((
|
||||
text.into(),
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
default,
|
||||
)));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a step slider element to the form.
|
||||
pub fn step_slider(
|
||||
mut self,
|
||||
text: impl Into<TextComponent>,
|
||||
steps: Vec<String>,
|
||||
default: u32,
|
||||
) -> Self {
|
||||
self.elements
|
||||
.push(CustomFormElement::StepSlider((text.into(), steps, default)));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a dropdown selector element to the form.
|
||||
pub fn dropdown(
|
||||
mut self,
|
||||
text: impl Into<TextComponent>,
|
||||
options: Vec<String>,
|
||||
default: u32,
|
||||
) -> Self {
|
||||
self.elements
|
||||
.push(CustomFormElement::Dropdown((text.into(), options, default)));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a text input field element to the form.
|
||||
pub fn input(
|
||||
mut self,
|
||||
text: impl Into<TextComponent>,
|
||||
placeholder: impl Into<String>,
|
||||
default: impl Into<String>,
|
||||
) -> Self {
|
||||
self.elements.push(CustomFormElement::Input((
|
||||
text.into(),
|
||||
placeholder.into(),
|
||||
default.into(),
|
||||
)));
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds the final custom form instance.
|
||||
pub fn build(self) -> Form {
|
||||
Form::Custom(CustomForm {
|
||||
title: self.title,
|
||||
elements: self.elements,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `FormImage` pointing to an HTTP(S) URL.
|
||||
pub fn url_image(url: impl Into<String>) -> FormImage {
|
||||
FormImage {
|
||||
type_: ImageType::Url,
|
||||
data: url.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `FormImage` pointing to a local file path.
|
||||
pub fn path_image(path: impl Into<String>) -> FormImage {
|
||||
FormImage {
|
||||
type_: ImageType::Path,
|
||||
data: path.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the response received from a submitted UI form.
|
||||
pub enum FormResponse {
|
||||
/// Response from a simple button form containing selected button index.
|
||||
Simple(u32),
|
||||
/// Response from a modal dialog containing boolean outcome.
|
||||
Modal(bool),
|
||||
/// Response from a custom form containing element values.
|
||||
Custom(Vec<serde_json::Value>),
|
||||
/// Form was closed by player without submission.
|
||||
Closed,
|
||||
}
|
||||
|
||||
impl FormResponse {
|
||||
/// Parses a JSON response payload string into a `FormResponse`.
|
||||
#[must_use]
|
||||
pub fn parse(data: Option<String>) -> Self {
|
||||
match data {
|
||||
None => Self::Closed,
|
||||
Some(s) => {
|
||||
if let Ok(val) = serde_json::from_str::<serde_json::Value>(&s) {
|
||||
if val.is_u64() {
|
||||
Self::Simple(val.as_u64().unwrap() as u32)
|
||||
} else if val.is_boolean() {
|
||||
Self::Modal(val.as_bool().unwrap())
|
||||
} else if val.is_array() {
|
||||
Self::Custom(val.as_array().unwrap().clone())
|
||||
} else {
|
||||
Self::Closed // Or some error state
|
||||
}
|
||||
} else {
|
||||
// Fallback for some clients that might send raw strings for simple/modal
|
||||
if s == "true" {
|
||||
Self::Modal(true)
|
||||
} else if s == "false" {
|
||||
Self::Modal(false)
|
||||
} else if let Ok(idx) = s.parse::<u32>() {
|
||||
Self::Simple(idx)
|
||||
} else {
|
||||
Self::Closed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
292
crates/pumpkin-plugin-api/src/lib.rs
Normal file
292
crates/pumpkin-plugin-api/src/lib.rs
Normal file
@@ -0,0 +1,292 @@
|
||||
//! Pumpkin plugin API.
|
||||
#![warn(missing_docs)]
|
||||
//!
|
||||
//! This crate provides everything needed to write a Pumpkin server plugin compiled
|
||||
//! to WebAssembly. A plugin consists of a type that implements [`Plugin`], registered
|
||||
//! with the [`register_plugin!`] macro.
|
||||
//!
|
||||
//! # Quick start
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! use pumpkin_plugin_api::{Plugin, PluginMetadata, Context, register_plugin, permissions::permissions};
|
||||
//!
|
||||
//! struct MyPlugin;
|
||||
//!
|
||||
//! impl Plugin for MyPlugin {
|
||||
//! fn new() -> Self { MyPlugin }
|
||||
//! fn metadata(&self) -> PluginMetadata {
|
||||
//! PluginMetadata {
|
||||
//! name: "my-plugin".into(),
|
||||
//! version: "0.1.0".into(),
|
||||
//! authors: vec!["you".into()],
|
||||
//! description: "An example plugin.".into(),
|
||||
//! dependencies: vec![],
|
||||
//! permissions: vec![permissions::NETWORK_DNS.into()],
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! register_plugin!(MyPlugin);
|
||||
//! ```
|
||||
|
||||
use crate::{
|
||||
commands::COMMAND_HANDLERS, events::EVENT_HANDLERS, logging::WitSubscriber,
|
||||
scheduler::TASK_HANDLERS, text::TextComponent,
|
||||
};
|
||||
|
||||
/// Plugin command registration and handling utilities.
|
||||
pub mod commands;
|
||||
/// Event system and event handlers.
|
||||
pub mod events;
|
||||
mod ext;
|
||||
/// Bedrock UI form builders.
|
||||
pub mod forms;
|
||||
/// Constants for plugin permissions.
|
||||
///
|
||||
/// Use these in your `PluginMetadata` to request access to specific host features.
|
||||
pub mod permissions;
|
||||
/// Scheduler utilities.
|
||||
pub mod scheduler;
|
||||
|
||||
/// Command WIT API re-exports.
|
||||
pub mod command {
|
||||
pub use crate::wit::pumpkin::plugin::command::{
|
||||
Arg, ArgumentType, Command, CommandError, CommandNode, CommandSender, ConsumedArgs,
|
||||
StringType,
|
||||
};
|
||||
}
|
||||
|
||||
pub use wit::pumpkin::plugin::{
|
||||
bedrock_packets, block_entity, boss_bar, command as command_wit, common,
|
||||
context::{Context, Server},
|
||||
data_components, entity,
|
||||
entity_types::EntityType,
|
||||
event::{self as events_wit, EventType},
|
||||
gui, i18n, item_stack, java_dialogs, java_packets, particles, permission, player, scoreboard,
|
||||
server, text, uuid, world,
|
||||
};
|
||||
|
||||
// Convenience re-exports of commonly-used plugin types so plugin authors can
|
||||
// name them directly (e.g. build an `ItemStack` for a GUI or `/give`).
|
||||
pub use events::{EventHandler, FromIntoEvent};
|
||||
pub use wit::pumpkin::plugin::item_stack::ItemStack;
|
||||
|
||||
/// Java dialog WIT API re-exports.
|
||||
pub mod java_dialog {
|
||||
pub use crate::wit::pumpkin::plugin::java_dialogs::{ActionButton, DialogBody, DialogType};
|
||||
}
|
||||
|
||||
/// WIT-based logging subscriber.
|
||||
pub mod logging;
|
||||
|
||||
#[allow(clippy::too_many_arguments, missing_docs)]
|
||||
mod wit {
|
||||
wit_bindgen::generate!({
|
||||
skip: ["init-plugin"],
|
||||
path: "../pumpkin-plugin-wit/v0.1",
|
||||
world: "plugin",
|
||||
enable_method_chaining: true
|
||||
});
|
||||
|
||||
use super::Component;
|
||||
export!(Component);
|
||||
}
|
||||
|
||||
struct Component;
|
||||
|
||||
/// Metadata that describes a plugin to the server.
|
||||
pub struct PluginMetadata {
|
||||
/// The human-readable name of the plugin.
|
||||
pub name: String,
|
||||
/// The plugin's version string (e.g. `"1.0.0"`).
|
||||
pub version: String,
|
||||
/// The list of plugin authors.
|
||||
pub authors: Vec<String>,
|
||||
/// A short description of what the plugin does.
|
||||
pub description: String,
|
||||
/// The list of plugin dependencies.
|
||||
pub dependencies: Vec<String>,
|
||||
/// The list of permissions requested by the plugin.
|
||||
pub permissions: Vec<String>,
|
||||
}
|
||||
|
||||
impl wit::exports::pumpkin::plugin::metadata::Guest for Component {
|
||||
/// Returns the plugin metadata to the host.
|
||||
fn get_metadata() -> wit::exports::pumpkin::plugin::metadata::PluginMetadata {
|
||||
let metadata = plugin().metadata();
|
||||
wit::exports::pumpkin::plugin::metadata::PluginMetadata {
|
||||
name: metadata.name,
|
||||
version: metadata.version,
|
||||
authors: metadata.authors,
|
||||
description: metadata.description,
|
||||
dependencies: metadata.dependencies,
|
||||
permissions: metadata.permissions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl wit::Guest for Component {
|
||||
/// WIT entry point — delegates to [`Plugin::on_load`].
|
||||
fn on_load(context: Context) -> Result<(), String> {
|
||||
plugin().on_load(context)
|
||||
}
|
||||
|
||||
/// WIT entry point — delegates to [`Plugin::on_unload`].
|
||||
fn on_unload(context: Context) -> Result<(), String> {
|
||||
plugin().on_unload(context)
|
||||
}
|
||||
|
||||
/// WIT entry point — dispatches an incoming event to the registered handler for `event_id`.
|
||||
///
|
||||
/// Returns the event unchanged if no handler is registered for the given id.
|
||||
fn handle_event(event_id: u32, server: Server, event: events::Event) -> events::Event {
|
||||
let handlers = EVENT_HANDLERS.lock().unwrap();
|
||||
if let Some(handler) = handlers.get(&event_id) {
|
||||
handler.handle_erased(server, event)
|
||||
} else {
|
||||
event
|
||||
}
|
||||
}
|
||||
|
||||
/// WIT entry point — dispatches an incoming command invocation to the registered handler for `command_id`.
|
||||
///
|
||||
/// Returns a [`CommandError`](command::CommandError) if no handler is registered for the given id.
|
||||
fn handle_command(
|
||||
command_id: u32,
|
||||
sender: command::CommandSender,
|
||||
server: Server,
|
||||
args: command::ConsumedArgs,
|
||||
) -> Result<i32, command::CommandError> {
|
||||
let handlers = COMMAND_HANDLERS.lock().unwrap();
|
||||
handlers.get(&command_id).map_or_else(
|
||||
|| {
|
||||
Err(command::CommandError::CommandFailed(TextComponent::text(
|
||||
&format!("no handler registered for command id {command_id}"),
|
||||
)))
|
||||
},
|
||||
|handler| handler.handle(sender, server, args),
|
||||
)
|
||||
}
|
||||
|
||||
/// WIT entry point — dispatches a scheduled task invocation to the registered handler for `handler_id`.
|
||||
fn handle_task(handler_id: u32, server: Server) {
|
||||
let mut handlers = TASK_HANDLERS.lock().unwrap();
|
||||
handlers.handle(handler_id, server);
|
||||
}
|
||||
|
||||
fn handle_ai_goal_can_start(goal_id: u32, server: Server, entity: entity::Entity) -> bool {
|
||||
let mut handlers = crate::ai::AI_GOAL_HANDLERS.lock().unwrap();
|
||||
if let Some(goal) = handlers.handlers.get_mut(&goal_id) {
|
||||
goal.can_start(server, entity)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ai_goal_should_continue(
|
||||
goal_id: u32,
|
||||
server: Server,
|
||||
entity: entity::Entity,
|
||||
) -> bool {
|
||||
let mut handlers = crate::ai::AI_GOAL_HANDLERS.lock().unwrap();
|
||||
if let Some(goal) = handlers.handlers.get_mut(&goal_id) {
|
||||
goal.should_continue(server, entity)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ai_goal_start(goal_id: u32, server: Server, entity: entity::Entity) {
|
||||
let mut handlers = crate::ai::AI_GOAL_HANDLERS.lock().unwrap();
|
||||
if let Some(goal) = handlers.handlers.get_mut(&goal_id) {
|
||||
goal.start(server, entity);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ai_goal_tick(goal_id: u32, server: Server, entity: entity::Entity) {
|
||||
let mut handlers = crate::ai::AI_GOAL_HANDLERS.lock().unwrap();
|
||||
if let Some(goal) = handlers.handlers.get_mut(&goal_id) {
|
||||
goal.tick(server, entity);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ai_goal_stop(goal_id: u32, server: Server, entity: entity::Entity) {
|
||||
let mut handlers = crate::ai::AI_GOAL_HANDLERS.lock().unwrap();
|
||||
if let Some(goal) = handlers.handlers.get_mut(&goal_id) {
|
||||
goal.stop(server, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience alias for `core::result::Result<T, String>` used throughout the plugin API.
|
||||
pub type Result<T, E = String> = core::result::Result<T, E>;
|
||||
|
||||
/// The trait that every Pumpkin plugin must implement.
|
||||
///
|
||||
/// Use the [`register_plugin!`] macro to register your implementation with the runtime.
|
||||
pub trait Plugin: Send + Sync {
|
||||
/// Creates a new instance of the plugin.
|
||||
///
|
||||
/// Called once by the runtime before [`on_load`](Plugin::on_load).
|
||||
fn new() -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Returns the metadata for this plugin.
|
||||
fn metadata(&self) -> PluginMetadata;
|
||||
|
||||
/// Called when the plugin is loaded by the server.
|
||||
///
|
||||
/// Use this to register event handlers, commands, and perform any setup work.
|
||||
fn on_load(&mut self, _context: Context) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Called when the plugin is unloaded by the server.
|
||||
///
|
||||
/// Use this to clean up any resources acquired during [`on_load`](Plugin::on_load).
|
||||
fn on_unload(&mut self, _context: Context) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn register_plugin(build_plugin: fn() -> Box<dyn Plugin>) {
|
||||
let _ = tracing::subscriber::set_global_default(WitSubscriber::new());
|
||||
unsafe { PLUGIN = Some(build_plugin()) }
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the currently loaded plugin instance.
|
||||
///
|
||||
/// # Panics
|
||||
/// If called before [`register_plugin`] has initialized `PLUGIN`.
|
||||
fn plugin() -> &'static mut dyn Plugin {
|
||||
#[expect(static_mut_refs)]
|
||||
unsafe {
|
||||
PLUGIN.as_deref_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// The singleton plugin instance, initialised by [`register_plugin`].
|
||||
static mut PLUGIN: Option<Box<dyn Plugin>> = None;
|
||||
|
||||
/// Registers the provided type as a Pumpkin plugin.
|
||||
///
|
||||
/// This macro generates the WebAssembly export entry point that the server uses to
|
||||
/// instantiate the plugin. The type must implement the [`Plugin`] trait.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust,ignore
|
||||
/// register_plugin!(MyPlugin);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! register_plugin {
|
||||
($plugin_type:ty) => {
|
||||
#[unsafe(export_name = "init-plugin")]
|
||||
pub extern "C" fn __init_plugin() {
|
||||
$crate::register_plugin(|| Box::new(<$plugin_type as $crate::Plugin>::new()));
|
||||
}
|
||||
};
|
||||
}
|
||||
/// AI and mob goal utilities.
|
||||
pub mod ai;
|
||||
89
crates/pumpkin-plugin-api/src/logging.rs
Normal file
89
crates/pumpkin-plugin-api/src/logging.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use tracing_serde_structured::AsSerde;
|
||||
|
||||
use crate::wit;
|
||||
|
||||
/// A [`tracing::Subscriber`] that forwards events to the host server over WIT.
|
||||
///
|
||||
/// Installed automatically as the global subscriber when the plugin is loaded.
|
||||
pub(crate) struct WitSubscriber {
|
||||
next_id: AtomicU64,
|
||||
}
|
||||
|
||||
impl WitSubscriber {
|
||||
/// Creates a new `WitSubscriber` with the span ID counter starting at `1`.
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
next_id: AtomicU64::new(1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl tracing::Subscriber for WitSubscriber {
|
||||
/// Always returns `true` — all log levels are forwarded to the host.
|
||||
fn enabled(&self, _metadata: &tracing::Metadata<'_>) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Allocates a new monotonically increasing span ID.
|
||||
fn new_span(&self, _attrs: &tracing::span::Attributes<'_>) -> tracing::span::Id {
|
||||
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
|
||||
tracing::span::Id::from_u64(id)
|
||||
}
|
||||
|
||||
/// No-op — span field recording is not forwarded to the host.
|
||||
fn record(&self, _span: &tracing::span::Id, _values: &tracing::span::Record<'_>) {}
|
||||
|
||||
/// No-op — causality links are not forwarded to the host.
|
||||
fn record_follows_from(&self, _span: &tracing::span::Id, _follows: &tracing::span::Id) {}
|
||||
|
||||
/// Serialises the tracing event with `postcard` and sends it to the host via WIT.
|
||||
fn event(&self, event: &tracing::Event<'_>) {
|
||||
let serialized =
|
||||
postcard::to_allocvec(&event.as_serde()).expect("failed to serialize tracing event");
|
||||
wit::pumpkin::plugin::logging::log_tracing(&serialized);
|
||||
}
|
||||
|
||||
/// No-op — span entry is not tracked.
|
||||
fn enter(&self, _span: &tracing::span::Id) {}
|
||||
|
||||
/// No-op — span exit is not tracked.
|
||||
fn exit(&self, _span: &tracing::span::Id) {}
|
||||
}
|
||||
|
||||
/// The log severity level used with [`log`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum LogLevel {
|
||||
/// Very fine-grained diagnostic information.
|
||||
Trace,
|
||||
/// Diagnostic information useful during development.
|
||||
Debug,
|
||||
/// General informational messages.
|
||||
Info,
|
||||
/// Potentially harmful situations that do not stop execution.
|
||||
Warn,
|
||||
/// Errors that may require attention.
|
||||
Error,
|
||||
}
|
||||
|
||||
impl LogLevel {
|
||||
/// Converts this level to the WIT-generated `Level` type expected by the host.
|
||||
const fn to_wit(self) -> wit::pumpkin::plugin::logging::Level {
|
||||
match self {
|
||||
Self::Trace => wit::pumpkin::plugin::logging::Level::Trace,
|
||||
Self::Debug => wit::pumpkin::plugin::logging::Level::Debug,
|
||||
Self::Info => wit::pumpkin::plugin::logging::Level::Info,
|
||||
Self::Warn => wit::pumpkin::plugin::logging::Level::Warn,
|
||||
Self::Error => wit::pumpkin::plugin::logging::Level::Error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends a log message to the server at the given severity level.
|
||||
///
|
||||
/// Prefer the standard `tracing` macros (`tracing::info!`, `tracing::warn!`, etc.)
|
||||
/// for structured logging; use this function when you need a direct, low-level log call.
|
||||
pub fn log(level: LogLevel, message: &str) {
|
||||
wit::pumpkin::plugin::logging::log(level.to_wit(), message);
|
||||
}
|
||||
64
crates/pumpkin-plugin-api/src/permissions.rs
Normal file
64
crates/pumpkin-plugin-api/src/permissions.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
/// Allows the plugin to perform DNS resolution.
|
||||
pub const NETWORK_DNS: &str = "network.dns";
|
||||
|
||||
/// Allows the plugin to use TCP sockets.
|
||||
pub const NETWORK_TCP: &str = "network.tcp";
|
||||
|
||||
/// Allows the plugin to use UDP sockets.
|
||||
pub const NETWORK_UDP: &str = "network.udp";
|
||||
|
||||
/// Allows the plugin to initiate TCP connections.
|
||||
pub const NETWORK_TCP_CONNECT: &str = "network.tcp.connect";
|
||||
|
||||
/// Allows the plugin to bind TCP listeners (accept inbound connections).
|
||||
pub const NETWORK_TCP_BIND: &str = "network.tcp.bind";
|
||||
|
||||
/// Allows the plugin to send and receive UDP packets to specific destinations.
|
||||
pub const NETWORK_UDP_CONNECT: &str = "network.udp.connect";
|
||||
|
||||
/// Allows the plugin to bind UDP sockets to local ports.
|
||||
pub const NETWORK_UDP_BIND: &str = "network.udp.bind";
|
||||
|
||||
/// Allows the plugin to send datagram on non-connected UDP socket.
|
||||
pub const NETWORK_UDP_OUTGOING_DATAGRAM: &str = "network.udp.outgoingdatagram";
|
||||
|
||||
/// Restricts all networking permissions to loopback addresses (localhost) only.
|
||||
pub const NETWORK_LOOPBACK: &str = "network.loopback";
|
||||
|
||||
/// Allows the plugin to make outbound TCP/UDP connections.
|
||||
/// **Warning:** This is a powerful permission.
|
||||
pub const NETWORK_OUTBOUND: &str = "network.outbound";
|
||||
|
||||
/// Allows the plugin to make outbound HTTP connections.
|
||||
///
|
||||
/// This is separate from `network.outbound`. This allows the use of `wasi:http`; the other allows the more powerful `wasi:sockets`.
|
||||
pub const HTTP_OUTBOUND: &str = "http.outbound";
|
||||
|
||||
/// Allows the plugin to read files within its own data folder (`plugins/data/<name>`).
|
||||
pub const FS_READ_DATA: &str = "fs.read.data";
|
||||
|
||||
/// Allows the plugin to write files within its own data folder (`plugins/data/<name>`).
|
||||
///
|
||||
/// Note that even without `FS_READ_DATA`, this will allow the plugin to
|
||||
/// inspect (e.g. list) the contents of the directory. But it will block
|
||||
/// reading any file's contents.
|
||||
pub const FS_WRITE_DATA: &str = "fs.write.data";
|
||||
|
||||
/// Allows the plugin to read all environment variables.
|
||||
pub const SYS_ENV: &str = "sys.env";
|
||||
|
||||
/// Allows the plugin to read specific environment variables.
|
||||
/// Used with a prefix like "sys.env.PATH".
|
||||
pub const SYS_ENV_PREFIX: &str = "sys.env.";
|
||||
|
||||
/// Allows the plugin to read system information (CPU, Memory, OS).
|
||||
pub const SYS_INFO: &str = "sys.info";
|
||||
|
||||
/// Allows the plugin to read CPU information.
|
||||
pub const SYS_INFO_CPU: &str = "sys.info.cpu";
|
||||
|
||||
/// Allows the plugin to read RAM information.
|
||||
pub const SYS_INFO_RAM: &str = "sys.info.ram";
|
||||
|
||||
/// Allows the plugin to read OS information.
|
||||
pub const SYS_INFO_OS: &str = "sys.info.os";
|
||||
134
crates/pumpkin-plugin-api/src/scheduler.rs
Normal file
134
crates/pumpkin-plugin-api/src/scheduler.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
//! Task scheduling API for plugins.
|
||||
//!
|
||||
//! This module provides the ability for plugins to schedule closures to be
|
||||
//! executed after a delay or repeatedly in the server's main tick loop.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! use pumpkin_plugin_api::scheduler::SchedulerExt;
|
||||
//!
|
||||
//! context.schedule_delayed_task(20, |server| {
|
||||
//! server.log("One second has passed!");
|
||||
//! });
|
||||
//! ```
|
||||
|
||||
use crate::wit::pumpkin::plugin::context::Server;
|
||||
use crate::wit::pumpkin::plugin::scheduler;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// A type alias for a closure that can be scheduled as a task.
|
||||
pub type TaskHandler = Box<dyn FnMut(Server) + Send>;
|
||||
|
||||
pub(crate) struct Task {
|
||||
handler: TaskHandler,
|
||||
}
|
||||
|
||||
pub(crate) static TASK_HANDLERS: Mutex<LazyTaskHandlers> = Mutex::new(LazyTaskHandlers {
|
||||
handlers: BTreeMap::new(),
|
||||
next_id: 0,
|
||||
});
|
||||
|
||||
pub(crate) struct LazyTaskHandlers {
|
||||
handlers: BTreeMap<u32, Task>,
|
||||
next_id: u32,
|
||||
}
|
||||
|
||||
impl LazyTaskHandlers {
|
||||
/// Registers a new task handler and returns its unique ID.
|
||||
pub fn register(&mut self, handler: TaskHandler) -> u32 {
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
self.handlers.insert(id, Task { handler });
|
||||
id
|
||||
}
|
||||
|
||||
/// Executes the task handler for the given ID.
|
||||
pub fn handle(&mut self, id: u32, server: Server) {
|
||||
if let Some(task) = self.handlers.get_mut(&id) {
|
||||
(task.handler)(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait to provide ergonomic task scheduling on `Context` and `Server`.
|
||||
pub trait SchedulerExt {
|
||||
/// Schedules a task to be executed once after the specified number of ticks.
|
||||
///
|
||||
/// * `delay_ticks`: Number of game ticks to wait before execution.
|
||||
/// * `handler`: Closure to execute.
|
||||
///
|
||||
/// Returns a unique task ID.
|
||||
fn schedule_delayed_task<F>(&self, delay_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Server) + Send + 'static;
|
||||
|
||||
/// Schedules a task to be executed repeatedly.
|
||||
///
|
||||
/// * `delay_ticks`: Number of game ticks to wait before the first execution.
|
||||
/// * `period_ticks`: Number of ticks between subsequent executions.
|
||||
/// * `handler`: Closure to execute.
|
||||
///
|
||||
/// Returns a unique task ID.
|
||||
fn schedule_repeating_task<F>(&self, delay_ticks: u64, period_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Server) + Send + 'static;
|
||||
}
|
||||
|
||||
impl SchedulerExt for crate::Context {
|
||||
fn schedule_delayed_task<F>(&self, delay_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Server) + Send + 'static,
|
||||
{
|
||||
schedule_delayed_task(delay_ticks, handler)
|
||||
}
|
||||
|
||||
fn schedule_repeating_task<F>(&self, delay_ticks: u64, period_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Server) + Send + 'static,
|
||||
{
|
||||
schedule_repeating_task(delay_ticks, period_ticks, handler)
|
||||
}
|
||||
}
|
||||
|
||||
impl SchedulerExt for crate::Server {
|
||||
fn schedule_delayed_task<F>(&self, delay_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Self) + Send + 'static,
|
||||
{
|
||||
schedule_delayed_task(delay_ticks, handler)
|
||||
}
|
||||
|
||||
fn schedule_repeating_task<F>(&self, delay_ticks: u64, period_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Self) + Send + 'static,
|
||||
{
|
||||
schedule_repeating_task(delay_ticks, period_ticks, handler)
|
||||
}
|
||||
}
|
||||
|
||||
/// Lower-level function to schedule a delayed task.
|
||||
/// Prefer using [`SchedulerExt`] for a more ergonomic API.
|
||||
pub fn schedule_delayed_task<F>(delay_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Server) + Send + 'static,
|
||||
{
|
||||
let handler_id = TASK_HANDLERS.lock().unwrap().register(Box::new(handler));
|
||||
scheduler::schedule_delayed_task(handler_id, delay_ticks)
|
||||
}
|
||||
|
||||
/// Lower-level function to schedule a repeating task.
|
||||
/// Prefer using [`SchedulerExt`] for a more ergonomic API.
|
||||
pub fn schedule_repeating_task<F>(delay_ticks: u64, period_ticks: u64, handler: F) -> u32
|
||||
where
|
||||
F: FnMut(Server) + Send + 'static,
|
||||
{
|
||||
let handler_id = TASK_HANDLERS.lock().unwrap().register(Box::new(handler));
|
||||
scheduler::schedule_repeating_task(handler_id, delay_ticks, period_ticks)
|
||||
}
|
||||
|
||||
/// Cancels a scheduled task.
|
||||
pub fn cancel_task(task_id: u32) {
|
||||
scheduler::cancel_task(task_id);
|
||||
}
|
||||
Reference in New Issue
Block a user