Events Reference¶
This reference documents all built-in events in MAID. Events are organized by their source package.
Event Base Class¶
All events inherit from Event:
from dataclasses import dataclass
from datetime import datetime
@dataclass
class Event:
"""Base class for all events."""
event_type: str # Auto-set to class name
timestamp: datetime # Auto-set to current time
cancelled: bool # Set to True to stop propagation
def cancel(self) -> None:
"""Cancel this event."""
self.cancelled = True
Engine Events (maid-engine)¶
Core lifecycle events from the engine.
TickEvent¶
Emitted at the start of each game tick.
@dataclass
class TickEvent(Event):
tick_number: int # Sequential tick counter
delta: float # Time since last tick in seconds
Use cases:
- Time-based processing
- Periodic tasks
- Animation/effect timing
Example:
async def on_tick(event: TickEvent):
if event.tick_number % 4 == 0: # Every second at 4 ticks/sec
await process_regeneration()
world.events.subscribe(TickEvent, on_tick)
EntityCreatedEvent¶
Emitted when an entity is created.
Use cases:
- Initialize entity state
- Register entity in indexes
- Trigger spawn effects
EntityDestroyedEvent¶
Emitted when an entity is destroyed.
Use cases:
- Clean up entity state
- Remove from indexes
- Trigger death/despawn effects
ComponentAddedEvent¶
Emitted when a component is added to an entity.
@dataclass
class ComponentAddedEvent(Event):
entity_id: UUID # Entity that received the component
component_type: str # Type name of the component
Use cases:
- React to capability changes
- Update system indexes
- Trigger effect application
ComponentRemovedEvent¶
Emitted when a component is removed from an entity.
@dataclass
class ComponentRemovedEvent(Event):
entity_id: UUID # Entity that lost the component
component_type: str # Type name of the component
Use cases:
- React to capability loss
- Update system indexes
- Trigger effect removal
TagAddedEvent¶
Emitted when a tag is added to an entity.
@dataclass
class TagAddedEvent(Event):
entity_id: UUID # Entity that received the tag
tag: str # Tag string
Use cases:
- React to state flags (e.g., "poisoned", "blessed")
- Update tag-based indexes
- Trigger tag-driven effects
TagRemovedEvent¶
Emitted when a tag is removed from an entity.
@dataclass
class TagRemovedEvent(Event):
entity_id: UUID # Entity that lost the tag
tag: str # Tag string
Use cases:
- React to state flag removal
- Update tag-based indexes
- Clean up tag-driven effects
PlayerConnectedEvent¶
Emitted when a player connects to the server.
@dataclass
class PlayerConnectedEvent(Event):
session_id: UUID # Network session ID
player_id: UUID | None # Entity ID (None if not yet logged in)
Use cases:
- Initialize session state
- Send welcome messages
- Track connection statistics
PlayerDisconnectedEvent¶
Emitted when a player disconnects from the server.
@dataclass
class PlayerDisconnectedEvent(Event):
session_id: UUID # Network session ID
player_id: UUID | None # Entity ID (None if not logged in)
Use cases:
- Save player state
- Clean up session
- Notify other players
PlayerCommandEvent¶
Emitted before a player command is processed.
@dataclass
class PlayerCommandEvent(Event):
player_id: UUID # Player entity ID
command: str # Command name
args: list[str] # Command arguments
success: bool # Whether the command succeeded
raw_input: str # Original unprocessed input
Use cases:
- Command logging
- Rate limiting
- Command interception
Example:
async def log_commands(event: PlayerCommandEvent):
logger.info(f"Player {event.player_id} executed: {event.command}")
world.events.subscribe(PlayerCommandEvent, log_commands)
RoomEnterEvent¶
Emitted when an entity enters a room.
@dataclass
class RoomEnterEvent(Event):
entity_id: UUID # Entity entering
room_id: UUID # Room being entered
from_room_id: UUID | None # Previous room (None if spawning)
Use cases:
- Send room descriptions
- Trigger room scripts
- Notify other occupants
RoomLeaveEvent¶
Emitted when an entity leaves a room.
@dataclass
class RoomLeaveEvent(Event):
entity_id: UUID # Entity leaving
room_id: UUID # Room being left
to_room_id: UUID | None # Destination room (None if despawning)
Use cases:
- Update room state
- Notify other occupants
- Trigger exit scripts
CustomEvent¶
Generic event for ad-hoc use without creating a new event class.
@dataclass
class CustomEvent(Event):
name: str # Custom event name
data: dict[str, Any] # Event data
Use cases:
- Quick prototyping
- Dynamic event types
- Plugin communication
Example:
# Emit custom event
await world.events.emit(CustomEvent(
name="weather_change",
data={"weather": "rain", "intensity": 0.5}
))
# Subscribe to custom events
async def on_custom(event: CustomEvent):
if event.name == "weather_change":
weather = event.data["weather"]
# Handle weather change
world.events.subscribe(CustomEvent, on_custom)
GridRoomAddedEvent¶
Emitted when a room is registered in the grid coordinate system.
@dataclass
class GridRoomAddedEvent(Event):
room_id: UUID # Room being registered
coord_x: int # X coordinate
coord_y: int # Y coordinate
coord_z: int # Z coordinate
terrain_type: str # Terrain type (default: "default")
movement_cost: float # Movement cost (default: 1.0)
Use cases:
- Update spatial indexes
- Trigger room initialization
- Log grid changes
GridRoomRemovedEvent¶
Emitted when a room is unregistered from the grid coordinate system.
@dataclass
class GridRoomRemovedEvent(Event):
room_id: UUID # Room being removed
coord_x: int # X coordinate
coord_y: int # Y coordinate
coord_z: int # Z coordinate
Use cases:
- Clean up spatial indexes
- Handle room destruction
- Log grid changes
SystemErrorEvent¶
Emitted when an error occurs in the tick loop or event dispatch.
@dataclass
class SystemErrorEvent(Event):
error_type: str # Exception class name
error_message: str # Error description
error_source: str # Where error originated ("tick_loop", "event_handler")
handler_name: str | None # Handler that raised (if applicable)
event_type_name: str | None # Event being processed (if applicable)
tick_number: int | None # Tick number (if applicable)
Use cases:
- Error monitoring and alerting
- Diagnostics collection
- System health tracking
Standard Library Events (maid-stdlib)¶
Common game events from the standard library.
CombatStartEvent¶
Emitted when combat begins between entities.
@dataclass
class CombatStartEvent(Event):
attacker_id: UUID # Entity initiating combat
defender_id: UUID # Entity being attacked
room_id: UUID # Room where combat occurs
Use cases:
- Initialize combat state
- Notify players
- Block certain actions during combat
CombatEndEvent¶
Emitted when combat ends.
@dataclass
class CombatEndEvent(Event):
combatant_ids: list[UUID] # All combatants involved
room_id: UUID # Room where combat occurred
Use cases:
- Clean up combat state
- Award experience
- Enable post-combat actions
DamageDealtEvent¶
Emitted when damage is dealt to an entity.
@dataclass
class DamageDealtEvent(Event):
source_id: UUID | None # Damage source (None for environmental)
target_id: UUID # Entity receiving damage
damage: int # Amount of damage
damage_type: str # Type: "physical", "fire", "ice", etc.
hit_location: str | None # Body location hit (optional)
Use cases:
- Update health displays
- Trigger damage reactions
- Log combat statistics
- Apply damage-based effects
Example:
async def on_damage(event: DamageDealtEvent):
# Check for death
target = world.entities.get(event.target_id)
if target:
health = target.try_get(HealthComponent)
if health and not health.is_alive:
await world.events.emit(EntityDeathEvent(
entity_id=event.target_id,
killer_id=event.source_id,
))
world.events.subscribe(DamageDealtEvent, on_damage)
EntityDeathEvent¶
Emitted when an entity dies.
@dataclass
class EntityDeathEvent(Event):
entity_id: UUID # Entity that died
killer_id: UUID | None # Entity that killed them (if any)
Use cases:
- Drop loot
- Award experience
- Respawn handling
- Death notifications
ItemPickedUpEvent¶
Emitted when an item is picked up.
@dataclass
class ItemPickedUpEvent(Event):
entity_id: UUID # Entity picking up
item_id: UUID # Item being picked up
room_id: UUID # Room where pickup occurred
Use cases:
- Update inventories
- Quest progress tracking
- Achievement tracking
ItemDroppedEvent¶
Emitted when an item is dropped.
@dataclass
class ItemDroppedEvent(Event):
entity_id: UUID # Entity dropping
item_id: UUID # Item being dropped
room_id: UUID # Room where drop occurred
Use cases:
- Update inventories
- Spawn item in room
- Trigger item scripts
MessageEvent¶
Emitted for communication messages (say, tell, channel).
@dataclass
class MessageEvent(Event):
sender_id: UUID | None # Sender (None for system messages)
target_ids: list[UUID] # Recipients
channel: str # Channel name: "say", "tell", "ooc", etc.
message: str # Message content
Use cases:
- Message routing
- Chat logging
- Profanity filtering
- Bridge integration
Quest Generation Events¶
QuestSeedCreatedEvent¶
Emitted when a story signal is accepted as a quest seed.
@dataclass
class QuestSeedCreatedEvent(Event):
seed_id: UUID # Unique seed identifier
seed_type: QuestSeedType # Type of story signal
source_entity: UUID # Entity that generated the signal
importance: float # Signal importance (0.0–1.0)
Use cases:
- Track quest generation pipeline
- Log story signal acceptance
- Debug quest seed flow
QuestGeneratedEvent¶
Emitted when a generated quest is created from a seed.
@dataclass
class QuestGeneratedEvent(Event):
quest_id: str # Generated quest identifier
seed_type: QuestSeedType # Original seed type
archetype_id: str # Quest archetype used
quest_giver_id: UUID # NPC assigned as quest giver
importance: float # Quest importance
Use cases:
- Track successful quest generation
- Monitor archetype distribution
- Trigger quest availability notifications
QuestOfferedEvent¶
Emitted when a generated quest is offered to a character.
@dataclass
class QuestOfferedEvent(Event):
quest_id: str # Quest identifier
character_id: UUID # Character receiving the offer
delivery_method: QuestDeliveryMethod # How the quest was offered
match_score: float # Player-quest match score
QuestDeliveredEvent¶
Emitted when a generated quest is delivered to a character.
@dataclass
class QuestDeliveredEvent(Event):
quest_id: str # Quest identifier
character_id: UUID # Character who received the quest
delivery_method: QuestDeliveryMethod # How the quest was delivered
Use cases:
- Track quest delivery
- Update quest state
- Trigger quest journal updates
QuestChainEvent¶
Emitted when a follow-up quest chain trigger is detected.
@dataclass
class QuestChainEvent(Event):
original_quest_id: str # Completed quest that triggered the chain
chain_signal: str # Signal for the next quest
chain_type: str # Chain type identifier
chain_depth: int # Current depth in the chain
QuestExpiredInternalEvent¶
Internal event emitted when a generated quest expires without being completed.
@dataclass
class QuestExpiredInternalEvent(Event):
quest_id: str # Expired quest identifier
reason: str | None = None # Expiration reason
Use cases:
- Clean up expired quest state
- Recycle quest seeds
- Track quest timeout metrics
Classic RPG Events (maid-classic-rpg)¶
Game-specific events from the classic RPG content pack.
Economy Events¶
ItemPurchasedEvent¶
Emitted when a player buys from a shop.
@dataclass
class ItemPurchasedEvent(Event):
buyer_id: UUID # Buyer entity ID
shop_id: UUID # Shop entity ID
item_id: UUID # Purchased item ID
price: int # Purchase price
ItemSoldEvent¶
Emitted when a player sells to a shop.
@dataclass
class ItemSoldEvent(Event):
seller_id: UUID # Seller entity ID
shop_id: UUID # Shop entity ID
item_id: UUID # Sold item ID
price: int # Sale price
GoldTransferEvent¶
Emitted when gold changes hands.
@dataclass
class GoldTransferEvent(Event):
from_id: UUID | None # Source (None = system)
to_id: UUID | None # Destination (None = system)
amount: int # Amount transferred
reason: str # Reason for transfer
BankDepositEvent¶
Emitted when gold is deposited.
@dataclass
class BankDepositEvent(Event):
character_id: UUID # Depositing character
amount: int # Amount deposited
fee: int # Transaction fee
new_balance: int # Balance after deposit
BankWithdrawEvent¶
Emitted when gold is withdrawn.
@dataclass
class BankWithdrawEvent(Event):
character_id: UUID # Withdrawing character
amount: int # Amount withdrawn
fee: int # Transaction fee
new_balance: int # Balance after withdrawal
BankTransferEvent¶
Emitted when gold is transferred between bank accounts.
@dataclass
class BankTransferEvent(Event):
from_account: UUID # Source account
to_account: UUID # Destination account
amount: int # Amount transferred
currency: str # Currency type (default: "gold")
TradeInitiatedEvent¶
Emitted when a trade is started.
@dataclass
class TradeInitiatedEvent(Event):
initiator_id: UUID # Player who initiated
target_id: UUID # Trade target
session_id: UUID # Trade session ID
TradeCompletedEvent¶
Emitted when a trade completes successfully.
@dataclass
class TradeCompletedEvent(Event):
session_id: UUID # Trade session ID
player1_id: UUID # First player
player2_id: UUID # Second player
items_1_to_2: list[UUID] # Items from player 1 to 2
items_2_to_1: list[UUID] # Items from player 2 to 1
gold_1_to_2: int # Gold from player 1 to 2
gold_2_to_1: int # Gold from player 2 to 1
TradeCancelledEvent¶
Emitted when a trade is cancelled.
@dataclass
class TradeCancelledEvent(Event):
session_id: UUID # Trade session ID
cancelled_by: UUID | None # Canceller (None = timeout)
reason: str # Cancellation reason
NPC Events¶
NPCSpawnedEvent¶
Emitted when an NPC spawns.
@dataclass
class NPCSpawnedEvent(Event):
entity_id: UUID # NPC entity ID
template_id: UUID # NPC template ID
room_id: UUID # Room where spawned
spawn_point_id: UUID # Spawn point ID
NPCDespawnedEvent¶
Emitted when an NPC despawns.
@dataclass
class NPCDespawnedEvent(Event):
entity_id: UUID # NPC entity ID
room_id: UUID # Room where despawned
reason: str # Reason: "death", "timeout", "cleanup"
NPCAggroEvent¶
Emitted when an NPC aggros on a target.
@dataclass
class NPCAggroEvent(Event):
npc_id: UUID # NPC entity ID
target_id: UUID # Aggro target
reason: str # Reason: "proximity", "attacked", "ally_attacked"
NPCDialogueEvent¶
Emitted when a player talks to an NPC.
@dataclass
class NPCDialogueEvent(Event):
player_id: UUID # Player entity ID
npc_id: UUID # NPC entity ID
message: str # Player's message
response: str # NPC's response
NPC Autonomy Events¶
Events emitted by the NPC autonomy system (maid_classic_rpg.events.autonomy).
NPCActivityChangedEvent¶
Emitted when an NPC's scheduled activity changes.
@dataclass
class NPCActivityChangedEvent(Event):
npc_id: UUID # NPC entity ID
previous_activity: ActivityType | None # Previous activity
new_activity: ActivityType # New activity
location: UUID # Activity location
NPCGoalCreatedEvent¶
Emitted when a new goal is added to an NPC.
@dataclass
class NPCGoalCreatedEvent(Event):
npc_id: UUID # NPC entity ID
goal_id: UUID # New goal ID
goal_category: GoalCategory # Goal category
NPCGoalCompletedEvent¶
Emitted when an NPC completes a goal.
@dataclass
class NPCGoalCompletedEvent(Event):
npc_id: UUID # NPC entity ID
goal_id: UUID # Completed goal ID
goal_category: GoalCategory # Goal category
NPCGoalFailedEvent¶
Emitted when an NPC goal fails.
@dataclass
class NPCGoalFailedEvent(Event):
npc_id: UUID # NPC entity ID
goal_id: UUID # Failed goal ID
goal_category: GoalCategory # Goal category
reason: str # Failure reason
NPCSocialInteractionEvent¶
Emitted when two NPCs complete a social interaction.
@dataclass
class NPCSocialInteractionEvent(Event):
initiator_id: UUID # Initiating NPC
target_id: UUID # Target NPC
interaction_type: str # Interaction type (gossip, trade, etc.)
outcome_type: str # Outcome classification
player_witnessed: bool # Whether a player saw it
NPCMoodChangedEvent¶
Emitted when an NPC's mood changes significantly.
@dataclass
class NPCMoodChangedEvent(Event):
npc_id: UUID # NPC entity ID
previous_mood: float # Previous mood value
new_mood: float # New mood value
cause: str # Cause of mood change
NPCActionEvent¶
Emitted when autonomy selects an action for an NPC.
@dataclass
class NPCActionEvent(Event):
npc_id: UUID # NPC entity ID
action_type: ActionType # Selected action type
target: UUID | str | None # Action target
ActionCompletedEvent¶
Emitted when an NPC action reaches completion.
@dataclass
class ActionCompletedEvent(Event):
npc_id: UUID # NPC entity ID
action_type: ActionType # Completed action type
ticks_elapsed: int # Ticks the action took
ActionFailedEvent¶
Emitted when an NPC action fails.
@dataclass
class ActionFailedEvent(Event):
npc_id: UUID # NPC entity ID
action_type: ActionType # Failed action type
reason: str # Failure reason
NPCBarkEvent¶
Emitted when an ambient bark is selected for an NPC.
@dataclass
class NPCBarkEvent(Event):
npc_id: UUID # NPC entity ID
room_id: UUID # Room where bark occurs
text: str # Bark text
bark_id: UUID # Unique bark identifier
StorySignalEvent¶
Emitted when story signal detection produces a signal.
@dataclass
class StorySignalEvent(Event):
signal_id: UUID # Signal identifier
signal_type: str # Signal classification
importance: float # Signal importance
involved_npc_ids: list[UUID] # NPCs involved
Quest Events¶
QuestAvailableEvent¶
Emitted when a quest becomes available to a character.
@dataclass
class QuestAvailableEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
QuestAcceptedEvent¶
Emitted when a character accepts a quest.
@dataclass
class QuestAcceptedEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
QuestObjectiveProgressEvent¶
Emitted when progress is made on a quest objective.
@dataclass
class QuestObjectiveProgressEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
objective_id: str # Objective identifier
current_count: int # Current progress
target_count: int # Required count
QuestObjectiveCompleteEvent¶
Emitted when a quest objective is completed.
@dataclass
class QuestObjectiveCompleteEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
objective_id: str # Objective identifier
QuestCompleteEvent¶
Emitted when all quest objectives are completed (ready to turn in).
@dataclass
class QuestCompleteEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
QuestTurnedInEvent¶
Emitted when a quest is turned in and rewards granted.
@dataclass
class QuestTurnedInEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
rewards: dict[str, Any] # Reward details
QuestFailedEvent¶
Emitted when a quest fails.
@dataclass
class QuestFailedEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
reason: str # Failure reason
QuestAbandonedEvent¶
Emitted when a character abandons a quest.
@dataclass
class QuestAbandonedEvent(Event):
character_id: UUID # Character entity ID
quest_id: str # Quest identifier
MonsterKilledEvent¶
Emitted when a monster is killed (for quest tracking).
@dataclass
class MonsterKilledEvent(Event):
killer_id: UUID # Killer entity ID
monster_id: UUID # Monster entity ID
monster_template_id: UUID # Monster template ID
room_id: UUID # Room where killed
ItemCollectedEvent¶
Emitted when an item is picked up (for quest tracking).
@dataclass
class ItemCollectedEvent(Event):
character_id: UUID # Character entity ID
item_id: UUID # Item entity ID
item_template_id: UUID | None # Item template (if any)
room_id: UUID # Room where collected
NPCTalkedToEvent¶
Emitted when a character talks to an NPC (for quest tracking).
@dataclass
class NPCTalkedToEvent(Event):
character_id: UUID # Character entity ID
npc_id: UUID # NPC entity ID
room_id: UUID # Room where conversation occurred
World Dynamics Events¶
TimeChangeEvent¶
Emitted when game time changes significantly.
@dataclass
class TimeChangeEvent(Event):
previous_time: GameTime | None # Previous game time
current_time: GameTime | None # Current game time
time_of_day_changed: bool # Whether time of day changed
season_changed: bool # Whether season changed
day_changed: bool # Whether day changed
SunriseEvent¶
Emitted at dawn.
SunsetEvent¶
Emitted at dusk.
SeasonChangeEvent¶
Emitted when the season changes.
@dataclass
class SeasonChangeEvent(Event):
old_season: Season | None # Previous season
new_season: Season | None # New season
game_time: GameTime | None # Current game time
WeatherChangeEvent¶
Emitted when weather changes in a region.
@dataclass
class WeatherChangeEvent(Event):
region_id: UUID | None # Region ID
old_weather: WeatherType | None # Previous weather
new_weather: WeatherType | None # New weather
game_time: GameTime | None # Current game time
WeatherEffectEvent¶
Emitted for periodic weather effects (damage, messages, etc.).
@dataclass
class WeatherEffectEvent(Event):
region_id: UUID | None # Region ID
weather_type: WeatherType | None # Current weather
effect_type: str # Effect: "damage", "message", etc.
affected_entities: list[UUID] # Affected entities
WorldEventStartEvent¶
Emitted when a world event begins.
@dataclass
class WorldEventStartEvent(Event):
event_id: UUID | None # Instance ID
definition_id: UUID | None # Event definition ID
world_event_type: EventType | None # Event type
scope: EventScope | None # Event scope
WorldEventEndEvent¶
Emitted when a world event ends.
@dataclass
class WorldEventEndEvent(Event):
event_id: UUID | None # Instance ID
definition_id: UUID | None # Event definition ID
state: EventState | None # Final state
participants: list[UUID] # Participating entities
WorldEventPhaseEvent¶
Emitted when a world event phase changes.
@dataclass
class WorldEventPhaseEvent(Event):
event_id: UUID | None # Instance ID
old_phase: int # Previous phase index
new_phase: int # New phase index
phase_name: str # Phase name
ServerAnnouncementEvent¶
Emitted for server-wide announcements.
@dataclass
class ServerAnnouncementEvent(Event):
message: str # Announcement text
announcement_type: str # Type: "info", "warning", "event", "admin"
source: str # Source (default: "system")
EcosystemCycleEvent¶
Emitted after each ecosystem simulation cycle.
@dataclass
class EcosystemCycleEvent(Event):
total_population: int # Total population count
births: int # Births this cycle
deaths: int # Deaths this cycle
migrations: int # Migrations this cycle
SpeciesExtinctionEvent¶
Emitted when a species goes extinct in an area.
@dataclass
class SpeciesExtinctionEvent(Event):
species_id: UUID | None # Species ID
area_id: UUID | None # Area ID
species_name: str # Species name
MigrationEvent¶
Emitted when creatures migrate between areas.
@dataclass
class MigrationEvent(Event):
species_id: UUID | None # Species ID
from_area: UUID | None # Source area
to_area: UUID | None # Destination area
count: int # Number of creatures
Guild Events¶
GuildCreatedEvent¶
Emitted when a guild is created.
@dataclass
class GuildCreatedEvent(Event):
guild_id: UUID | None # Guild ID
leader_id: UUID | None # Guild leader
guild_name: str # Guild name
GuildDisbandedEvent¶
Emitted when a guild is disbanded.
@dataclass
class GuildDisbandedEvent(Event):
guild_id: UUID | None # Guild ID
guild_name: str # Guild name
GuildMemberJoinedEvent¶
Emitted when a player joins a guild.
@dataclass
class GuildMemberJoinedEvent(Event):
guild_id: UUID | None # Guild ID
character_id: UUID | None # Joining character
character_name: str # Character name
GuildMemberLeftEvent¶
Emitted when a player leaves or is kicked from a guild.
@dataclass
class GuildMemberLeftEvent(Event):
guild_id: UUID | None # Guild ID
character_id: UUID | None # Leaving character
character_name: str # Character name
was_kicked: bool # Whether kicked
kicked_by: UUID | None # Who kicked (if applicable)
GuildRankChangedEvent¶
Emitted when a member's rank changes.
@dataclass
class GuildRankChangedEvent(Event):
guild_id: UUID | None # Guild ID
character_id: UUID | None # Affected character
old_rank: str # Previous rank
new_rank: str # New rank
changed_by: UUID | None # Who changed it
GuildLevelUpEvent¶
Emitted when a guild levels up.
@dataclass
class GuildLevelUpEvent(Event):
guild_id: UUID | None # Guild ID
new_level: int # New guild level
perks_unlocked: list[str] # Newly unlocked perks
GuildChatEvent¶
Emitted for guild chat messages.
@dataclass
class GuildChatEvent(Event):
guild_id: UUID | None # Guild ID
sender_id: UUID | None # Message sender
sender_name: str # Sender name
message: str # Chat message
is_announcement: bool # Whether it's an announcement
Faction & Reputation Events¶
ReputationChangeEvent¶
Emitted when a character's reputation changes.
@dataclass
class ReputationChangeEvent(Event):
character_id: UUID | None # Affected character
faction_id: UUID | None # Faction ID
faction_name: str # Faction name
old_value: int # Previous reputation value
new_value: int # New reputation value
old_level: str # Previous reputation level
new_level: str # New reputation level
Achievement Events¶
AchievementUnlockedEvent¶
Emitted when a player earns an achievement.
@dataclass
class AchievementUnlockedEvent(Event):
character_id: UUID | None # Character entity ID
achievement_id: UUID | None # Achievement ID
achievement_name: str # Achievement name
points: int # Points awarded
AchievementProgressEvent¶
Emitted when achievement progress is made.
@dataclass
class AchievementProgressEvent(Event):
character_id: UUID | None # Character entity ID
achievement_id: UUID | None # Achievement ID
criterion_index: int # Criterion index
current: int # Current progress
required: int # Required for completion
Crafting Events¶
CraftingAttemptEvent¶
Emitted when crafting is attempted.
@dataclass
class CraftingAttemptEvent(Event):
character_id: UUID | None # Crafting character
recipe_id: UUID | None # Recipe ID
station_id: UUID | None # Crafting station (if any)
CraftingSuccessEvent¶
Emitted on successful craft.
@dataclass
class CraftingSuccessEvent(Event):
character_id: UUID | None # Crafting character
recipe_id: UUID | None # Recipe ID
item_id: UUID | None # Crafted item ID
quality: str # Item quality
CraftingFailureEvent¶
Emitted on failed craft.
@dataclass
class CraftingFailureEvent(Event):
character_id: UUID | None # Crafting character
recipe_id: UUID | None # Recipe ID
reason: str # Failure reason
materials_lost: list[UUID] # Lost material IDs
GatheringEvent¶
Emitted when gathering resources.
@dataclass
class GatheringEvent(Event):
character_id: UUID | None # Gathering character
node_id: UUID | None # Resource node ID
materials: list[UUID] # Gathered material IDs
skill_gained: float # Skill experience gained
RecipeLearnedEvent¶
Emitted when a recipe is learned.
@dataclass
class RecipeLearnedEvent(Event):
character_id: UUID | None # Learning character
recipe_id: UUID | None # Recipe ID
recipe_name: str # Recipe name
EnchantmentAppliedEvent¶
Emitted when an enchantment is applied to an item.
@dataclass
class EnchantmentAppliedEvent(Event):
character_id: UUID | None # Character applying
item_id: UUID | None # Target item ID
enchantment_type: str # Enchantment type
tier: int # Enchantment tier
GemSocketedEvent¶
Emitted when a gem is socketed into an item.
@dataclass
class GemSocketedEvent(Event):
character_id: UUID | None # Character socketing
item_id: UUID | None # Target item ID
gem_type: str # Gem type
ItemRepairedEvent¶
Emitted when an item is repaired.
@dataclass
class ItemRepairedEvent(Event):
character_id: UUID | None # Repairing character
item_id: UUID | None # Repaired item ID
durability_restored: int # Durability points restored
Auction Events¶
AuctionListedEvent¶
Emitted when an item is listed on the auction house.
@dataclass
class AuctionListedEvent(Event):
seller_id: UUID | None # Seller entity ID
listing_id: UUID | None # Listing ID
item_id: UUID | None # Listed item ID
starting_price: int # Starting bid price
buyout_price: int | None # Buyout price (if any)
AuctionBidEvent¶
Emitted when a bid is placed.
@dataclass
class AuctionBidEvent(Event):
bidder_id: UUID | None # Bidder entity ID
listing_id: UUID | None # Listing ID
bid_amount: int # Bid amount
previous_bidder_id: UUID | None # Outbid player (if any)
AuctionSoldEvent¶
Emitted when an auction completes with a sale.
@dataclass
class AuctionSoldEvent(Event):
seller_id: UUID | None # Seller entity ID
buyer_id: UUID | None # Buyer entity ID
listing_id: UUID | None # Listing ID
item_id: UUID | None # Sold item ID
price: int # Final sale price
was_buyout: bool # Whether it was a buyout
AuctionExpiredEvent¶
Emitted when an auction expires without a sale.
@dataclass
class AuctionExpiredEvent(Event):
seller_id: UUID | None # Seller entity ID
listing_id: UUID | None # Listing ID
item_id: UUID | None # Unsold item ID
AuctionCancelledEvent¶
Emitted when an auction is cancelled.
@dataclass
class AuctionCancelledEvent(Event):
seller_id: UUID | None # Seller entity ID
listing_id: UUID | None # Listing ID
item_id: UUID | None # Item ID
Admin & Moderation Events¶
AdminActionEvent¶
Emitted when an admin performs an action.
@dataclass
class AdminActionEvent(Event):
admin_id: UUID | None # Admin entity ID
admin_name: str # Admin name
action: str # Action performed
target_id: UUID | None # Target entity (if any)
target_name: str # Target name
details: str # Action details
AdminTeleportEvent¶
Emitted when an admin teleports.
@dataclass
class AdminTeleportEvent(Event):
admin_id: UUID | None # Admin entity ID
from_room_id: UUID | None # Origin room
to_room_id: UUID | None # Destination room
method: str # Method: "goto", "transfer", "at"
AdminLoadEvent¶
Emitted when an admin loads an entity.
@dataclass
class AdminLoadEvent(Event):
admin_id: UUID | None # Admin entity ID
entity_type: str # Type: "item", "monster"
entity_id: UUID | None # Loaded entity ID
room_id: UUID | None # Target room
AdminPurgeEvent¶
Emitted when an admin purges entities.
@dataclass
class AdminPurgeEvent(Event):
admin_id: UUID | None # Admin entity ID
room_id: UUID | None # Target room
purged_count: int # Number of entities purged
purge_type: str # Type: "all", "items", "monsters"
ServerShutdownEvent¶
Emitted when the server is shutting down.
@dataclass
class ServerShutdownEvent(Event):
initiated_by: UUID | None # Admin who initiated (if any)
reason: str # Shutdown reason
delay_seconds: int # Delay before shutdown
ServerRebootEvent¶
Emitted when the server is rebooting.
@dataclass
class ServerRebootEvent(Event):
initiated_by: UUID | None # Admin who initiated (if any)
reason: str # Reboot reason
delay_seconds: int # Delay before reboot
ModerationActionEvent¶
Emitted when a moderation action is taken.
@dataclass
class ModerationActionEvent(Event):
moderator_id: UUID | None # Moderator entity ID
moderator_name: str # Moderator name
action: str # Action: "ban", "mute", "kick", "warn", "jail", "freeze", etc.
target_id: UUID | None # Target entity ID
target_name: str # Target name
reason: str # Action reason
duration: float | None # Duration in seconds (None = permanent)
PlayerBannedEvent¶
Emitted when a player is banned.
@dataclass
class PlayerBannedEvent(Event):
banned_by: UUID | None # Admin who banned
account_id: UUID | None # Banned account ID
account_name: str # Account name
reason: str # Ban reason
permanent: bool # Whether permanent
PlayerUnbannedEvent¶
Emitted when a player is unbanned.
@dataclass
class PlayerUnbannedEvent(Event):
unbanned_by: UUID | None # Admin who unbanned
account_id: UUID | None # Unbanned account ID
account_name: str # Account name
PlayerMutedEvent¶
Emitted when a player is muted.
@dataclass
class PlayerMutedEvent(Event):
muted_by: UUID | None # Admin who muted
character_id: UUID | None # Muted character
character_name: str # Character name
duration: float | None # Duration in seconds (None = until unmuted)
PlayerUnmutedEvent¶
Emitted when a player is unmuted.
@dataclass
class PlayerUnmutedEvent(Event):
unmuted_by: UUID | None # Admin who unmuted
character_id: UUID | None # Unmuted character
character_name: str # Character name
PlayerKickedEvent¶
Emitted when a player is kicked.
@dataclass
class PlayerKickedEvent(Event):
kicked_by: UUID | None # Admin who kicked
session_id: UUID | None # Player's session ID
character_name: str # Character name
reason: str # Kick reason
PlayerWarnedEvent¶
Emitted when a player receives a warning.
@dataclass
class PlayerWarnedEvent(Event):
warned_by: UUID | None # Admin who warned
character_id: UUID | None # Warned character
character_name: str # Character name
warning: str # Warning message
PlayerJailedEvent¶
Emitted when a player is jailed.
@dataclass
class PlayerJailedEvent(Event):
jailed_by: UUID | None # Admin who jailed
character_id: UUID | None # Jailed character
character_name: str # Character name
reason: str # Jail reason
jail_room_id: UUID | None # Jail room
PlayerUnjailedEvent¶
Emitted when a player is released from jail.
@dataclass
class PlayerUnjailedEvent(Event):
unjailed_by: UUID | None # Admin who released
character_id: UUID | None # Released character
character_name: str # Character name
PlayerFrozenEvent¶
Emitted when a player is frozen (cannot act).
@dataclass
class PlayerFrozenEvent(Event):
frozen_by: UUID | None # Admin who froze
character_id: UUID | None # Frozen character
character_name: str # Character name
PlayerThawedEvent¶
Emitted when a frozen player is thawed.
@dataclass
class PlayerThawedEvent(Event):
thawed_by: UUID | None # Admin who thawed
character_id: UUID | None # Thawed character
character_name: str # Character name
SnoopStartEvent¶
Emitted when an admin starts snooping a player.
@dataclass
class SnoopStartEvent(Event):
snooper_id: UUID | None # Admin snooping
target_id: UUID | None # Snooped player
target_name: str # Player name
SnoopEndEvent¶
Emitted when an admin stops snooping a player.
@dataclass
class SnoopEndEvent(Event):
snooper_id: UUID | None # Admin who was snooping
target_id: UUID | None # Snooped player
Builder/OLC Events¶
BuilderEditEvent¶
Emitted when a builder edits content.
@dataclass
class BuilderEditEvent(Event):
builder_id: UUID | None # Builder entity ID
builder_name: str # Builder name
edit_type: str # Type: "room", "item", "monster", "zone"
target_id: UUID | None # Edited entity ID
action: str # Action: "create", "edit", "delete"
changes: dict[str, Any] # Change details
OLCLockAcquiredEvent¶
Emitted when a builder acquires an edit lock.
@dataclass
class OLCLockAcquiredEvent(Event):
session_id: UUID | None # Edit session ID
editor_type: str # Editor type
target_id: UUID | None # Locked entity ID
OLCLockReleasedEvent¶
Emitted when a builder releases an edit lock.
@dataclass
class OLCLockReleasedEvent(Event):
session_id: UUID | None # Edit session ID
editor_type: str # Editor type
target_id: UUID | None # Unlocked entity ID
Event Priority¶
Events are processed in handler priority order:
from maid_engine.core.events import EventPriority
class EventPriority(Enum):
HIGHEST = auto() # Runs first - validation, blocking
HIGH = auto() # Pre-processing
NORMAL = auto() # Standard handlers
LOW = auto() # Post-processing
LOWEST = auto() # Runs last - logging, cleanup
Subscribing to Events¶
from maid_engine.core.events import EventPriority
# Basic subscription
world.events.subscribe(DamageDealtEvent, my_handler)
# With priority
world.events.subscribe(
DamageDealtEvent,
validation_handler,
priority=EventPriority.HIGHEST
)
# One-time subscription
world.events.subscribe(
PlayerConnectedEvent,
first_player_bonus,
once=True
)
Emitting Events¶
# Async emission (immediate)
await world.events.emit(DamageDealtEvent(
source_id=attacker.id,
target_id=target.id,
damage=25,
damage_type="physical",
))
# Sync emission (queued)
world.events.emit_sync(MyEvent(...))
# Process queued events
await world.events.process_pending()
Canceling Events¶
async def block_damage_in_safe_zone(event: DamageDealtEvent):
target = world.entities.get(event.target_id)
if target and is_in_safe_zone(target):
event.cancel() # Prevents further processing
world.events.subscribe(
DamageDealtEvent,
block_damage_in_safe_zone,
priority=EventPriority.HIGHEST
)
Creating Custom Events¶
from dataclasses import dataclass
from uuid import UUID
from maid_engine.core.events import Event
@dataclass
class QuestCompletedEvent(Event):
"""Emitted when a player completes a quest."""
player_id: UUID
quest_id: UUID
quest_name: str
experience_reward: int = 0
gold_reward: int = 0
# Use in your content pack
def get_events(self) -> list[type[Event]]:
return [QuestCompletedEvent]
Event Best Practices¶
- Keep events immutable: Don't modify event data in handlers
- Use specific event types: Avoid overly generic events
- Document event flow: Comment the expected sequence of events
- Handle errors gracefully: Don't let handler errors crash the system
- Clean up subscriptions: Unsubscribe when systems shut down
- Use appropriate priorities: Validation early, logging late