Skip to main content

basalt_api/events/
mod.rs

1//! Game events and the event bus.
2//!
3//! This module provides both:
4//! - The generic event-bus infrastructure ([`EventBus`], [`Event`],
5//!   [`Stage`], [`BusKind`], [`EventRouting`])
6//! - Domain event types organized by area: [`block`](self#block-events),
7//!   [`chat`](self#chat-events), [`container`](self#container-events),
8//!   [`player`](self#player-events), and crafting/recipe events.
9//!
10//! Events are dispatched through the bus in three stages:
11//!
12//! 1. **Validate** — read-only checks, can cancel (permissions, anti-cheat)
13//! 2. **Process** — state mutation (world changes, inventory updates)
14//! 3. **Post** — side effects (broadcasting, persistence, logging)
15//!
16//! If any Validate handler cancels an event, Process and Post are
17//! skipped entirely.
18//!
19//! Use the macros ([`game_cancellable_event!`], [`game_event!`],
20//! [`instant_cancellable_event!`], [`instant_event!`]) to implement
21//! the [`Event`] trait for custom event types.
22
23mod block;
24mod bus;
25mod chat;
26mod container;
27mod crafting;
28#[cfg(feature = "raw-packets")]
29mod packet;
30mod player;
31mod traits;
32
33pub use block::{BlockBrokenEvent, BlockPlacedEvent, PlayerInteractEvent};
34pub use bus::EventBus;
35pub use chat::{ChatMessageEvent, CommandEvent};
36pub use container::*;
37pub use crafting::{
38    CraftingCraftedEvent, CraftingGridChangedEvent, CraftingPreCraftEvent,
39    CraftingRecipeClearedEvent, CraftingRecipeMatchedEvent, CraftingShiftClickBatchEvent,
40    RecipeBookFillRequestEvent, RecipeBookFilledEvent, RecipeLockedEvent, RecipeRegisterEvent,
41    RecipeRegisteredEvent, RecipeUnlockedEvent, RecipeUnregisteredEvent,
42};
43#[cfg(feature = "raw-packets")]
44pub use packet::RawPacketEvent;
45pub use player::{PlayerJoinedEvent, PlayerLeftEvent, PlayerMovedEvent};
46pub use traits::{BusKind, Event, EventRouting, Stage};
47
48/// Implements [`Event`] and [`EventRouting`] for a non-cancellable
49/// event dispatched on the **instant** loop's bus.
50#[macro_export]
51macro_rules! instant_event {
52    ($name:ident) => {
53        impl $crate::events::Event for $name {
54            fn is_cancelled(&self) -> bool {
55                false
56            }
57            fn cancel(&mut self) {}
58            fn as_any(&self) -> &dyn std::any::Any {
59                self
60            }
61            fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
62                self
63            }
64            fn bus_kind(&self) -> $crate::events::BusKind {
65                $crate::events::BusKind::Instant
66            }
67        }
68        impl $crate::events::EventRouting for $name {
69            const BUS: $crate::events::BusKind = $crate::events::BusKind::Instant;
70        }
71    };
72}
73
74/// Implements [`Event`] and [`EventRouting`] for a cancellable
75/// event dispatched on the **instant** loop's bus.
76///
77/// The struct must have a `cancelled: bool` field.
78#[macro_export]
79macro_rules! instant_cancellable_event {
80    ($name:ident) => {
81        impl $crate::events::Event for $name {
82            fn is_cancelled(&self) -> bool {
83                self.cancelled
84            }
85            fn cancel(&mut self) {
86                self.cancelled = true;
87            }
88            fn as_any(&self) -> &dyn std::any::Any {
89                self
90            }
91            fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
92                self
93            }
94            fn bus_kind(&self) -> $crate::events::BusKind {
95                $crate::events::BusKind::Instant
96            }
97        }
98        impl $crate::events::EventRouting for $name {
99            const BUS: $crate::events::BusKind = $crate::events::BusKind::Instant;
100        }
101    };
102}
103
104/// Implements [`Event`] and [`EventRouting`] for a non-cancellable
105/// event dispatched on the **game** loop's bus.
106#[macro_export]
107macro_rules! game_event {
108    ($name:ident) => {
109        impl $crate::events::Event for $name {
110            fn is_cancelled(&self) -> bool {
111                false
112            }
113            fn cancel(&mut self) {}
114            fn as_any(&self) -> &dyn std::any::Any {
115                self
116            }
117            fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
118                self
119            }
120            fn bus_kind(&self) -> $crate::events::BusKind {
121                $crate::events::BusKind::Game
122            }
123        }
124        impl $crate::events::EventRouting for $name {
125            const BUS: $crate::events::BusKind = $crate::events::BusKind::Game;
126        }
127    };
128}
129
130/// Implements [`Event`] and [`EventRouting`] for a cancellable
131/// event dispatched on the **game** loop's bus.
132///
133/// The struct must have a `cancelled: bool` field.
134#[macro_export]
135macro_rules! game_cancellable_event {
136    ($name:ident) => {
137        impl $crate::events::Event for $name {
138            fn is_cancelled(&self) -> bool {
139                self.cancelled
140            }
141            fn cancel(&mut self) {
142                self.cancelled = true;
143            }
144            fn as_any(&self) -> &dyn std::any::Any {
145                self
146            }
147            fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
148                self
149            }
150            fn bus_kind(&self) -> $crate::events::BusKind {
151                $crate::events::BusKind::Game
152            }
153        }
154        impl $crate::events::EventRouting for $name {
155            const BUS: $crate::events::BusKind = $crate::events::BusKind::Game;
156        }
157    };
158}