Skip to content

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.

@dataclass
class EntityCreatedEvent(Event):
    entity_id: UUID    # ID of the created entity

Use cases:

  • Initialize entity state
  • Register entity in indexes
  • Trigger spawn effects

EntityDestroyedEvent

Emitted when an entity is destroyed.

@dataclass
class EntityDestroyedEvent(Event):
    entity_id: UUID    # ID of the destroyed entity

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.

@dataclass
class SunriseEvent(Event):
    game_time: GameTime | None     # Current game time

SunsetEvent

Emitted at dusk.

@dataclass
class SunsetEvent(Event):
    game_time: GameTime | None     # Current game time

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

  1. Keep events immutable: Don't modify event data in handlers
  2. Use specific event types: Avoid overly generic events
  3. Document event flow: Comment the expected sequence of events
  4. Handle errors gracefully: Don't let handler errors crash the system
  5. Clean up subscriptions: Unsubscribe when systems shut down
  6. Use appropriate priorities: Validation early, logging late