maid-engine¶
The maid-engine package provides the core infrastructure for building MUD games with MAID. It is the foundation layer that all other MAID packages build upon.
Installation¶
pip install maid-engine
# With AI providers
pip install maid-engine[openai]
pip install maid-engine[anthropic]
pip install maid-engine[ollama]
Module Overview¶
Core (maid_engine.core)¶
The core module contains the fundamental building blocks:
- engine - Main
GameEngineclass - tick loop, content pack loading - world -
Worldclass - state management, entity tracking - events -
EventBusand core event types - ecs - Entity Component System implementation
Commands (maid_engine.commands)¶
The command system provides layered, priority-based command resolution:
- registry -
LayeredCommandRegistryfor command management - decorators -
@commanddecorator and helpers - arguments - Argument parsing utilities
- hooks - Pre/post command hooks
- locks - Permission lock expressions
Plugins (maid_engine.plugins)¶
The content pack system for extensibility:
- protocol -
ContentPackprotocol andBaseContentPack - loader -
ContentPackLoaderfor discovery and loading - manifest -
ContentPackManifestmetadata
Storage (maid_engine.storage)¶
Document-based persistence layer:
- document_store -
DocumentStoreinterface and implementations
Networking (maid_engine.net)¶
Network layer for player connections:
- server - Base
NetworkServerclass - session -
Sessionbase class - telnet - Telnet protocol support
- web - WebSocket support
AI Integration (maid_engine.ai)¶
LLM provider abstraction:
- providers - LLM provider interface and implementations
- conversation - Conversation history management
- prompts - Prompt building utilities
- rate_limiter - API rate limiting
- safety - Content filtering
Authentication (maid_engine.auth)¶
Account and session management.
Configuration (maid_engine.config)¶
Settings and configuration with Pydantic.
Internationalization (maid_engine.i18n)¶
Multi-language support with Translator and translation utilities.
Key Classes¶
GameEngine¶
The central game engine that manages the tick loop and content packs.
GameEngine
¶
GameEngine(
settings: Settings | None = None,
document_store: DocumentStore | None = None,
)
Main game engine that runs the tick loop.
The GameEngine manages the game world, networking, and the main tick loop that drives all game systems. It is content-agnostic - all game-specific functionality comes from content packs.
Example
engine = GameEngine()
Load content packs¶
engine.load_content_pack(my_content_pack)
await engine.start()
Engine runs until stopped¶
In another context:¶
await engine.stop()
load_content_pack
¶
load_content_pack(
pack: ContentPack, use_hot_reload: bool = False
) -> None
Load a content pack.
When the engine is stopped, content packs are loaded synchronously. When the engine is running, set use_hot_reload=True to use the hot reload manager for safe runtime loading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack
|
ContentPack
|
The content pack to load. |
required |
use_hot_reload
|
bool
|
If True and engine is running, use hot reload. If False and engine is running, raises RuntimeError. |
False
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If engine is running and use_hot_reload is False. |
ValueError
|
If pack is already loaded or dependencies are missing. |
World¶
Central state management for the game world.
World
¶
Central game world state manager.
The World holds all game state including entities, rooms, and provides efficient queries for game logic.
EventBus¶
Event-driven communication system.
EventBus
¶
Publish/subscribe event system.
The EventBus allows systems to communicate through events without direct coupling. Handlers can be async or sync.
Supports wildcard subscriptions via subscribe_all() to receive all events.
Example
bus = EventBus()
async def on_damage(event: DamageDealtEvent): print(f"Damage dealt: {event.damage}")
bus.subscribe(DamageDealtEvent, on_damage)
Subscribe to ALL events (wildcard)¶
def log_event(event: Event): print(f"Event: {event.event_type}") bus.subscribe_all(log_event)
await bus.emit(DamageDealtEvent( source_id=attacker.id, target_id=defender.id, damage=25, damage_type="physical" ))
subscribe
¶
subscribe(
event_type: type[E],
handler: EventHandler | SyncEventHandler,
priority: EventPriority = NORMAL,
once: bool = False,
source_pack: str | None = None,
) -> UUID
Subscribe to an event type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
type[E]
|
The event class to subscribe to |
required |
handler
|
EventHandler | SyncEventHandler
|
Async or sync function to handle events |
required |
priority
|
EventPriority
|
Handler priority (higher priority runs first) |
NORMAL
|
once
|
bool
|
If True, handler is removed after first invocation |
False
|
source_pack
|
str | None
|
Name of the content pack registering this handler (for hot reload) |
None
|
Returns:
| Type | Description |
|---|---|
UUID
|
Handler ID for unsubscribing |
unsubscribe
¶
Unsubscribe a handler by ID.
If called during event dispatch, the removal is deferred until the dispatch completes to ensure safe iteration.
Returns:
| Type | Description |
|---|---|
bool
|
True if handler was found and removed (or queued for removal) |
emit
async
¶
emit(event: Event) -> None
Emit an event immediately, invoking all handlers.
Handlers are invoked in priority order. If an event is cancelled, remaining handlers are not called.
Both type-specific handlers and wildcard handlers (registered via subscribe_all) are invoked.
Handler removals during dispatch are deferred until dispatch completes.
Entity¶
Base class for all game entities.
Entity
¶
Entity(
entity_id: UUID | None = None,
manager: EntityManager | None = None,
)
Represents a game entity as a collection of components.
Entities are essentially just IDs that group components together. The EntityManager handles the actual component storage and queries.
Example
entity = Entity() entity.add(PositionComponent(room_id=room.id)) entity.add(HealthComponent(current=100, maximum=100))
if entity.has(HealthComponent): health = entity.get(HealthComponent) health.damage(10)
ContentPack Protocol¶
Protocol defining the content pack interface.
ContentPack
¶
Bases: Protocol
Protocol defining the interface for content packs.
Content packs provide game functionality to the MAID engine. They can include: - ECS systems that process entities - Event types for communication - Commands for player interaction - Document schemas for persistence - Setup/teardown hooks
Important
Content packs that are discovered via entry points or directory scanning
MUST have a no-argument constructor (or a constructor where all parameters
have default values). This is because the discovery mechanism cannot pass
constructor arguments. If your pack requires initialization parameters,
consider using the on_load method or environment variables instead.
Example
class MyContentPack: def init(self) -> None: # No required arguments - this is important for auto-discovery! self._initialized = False
@property
def manifest(self) -> ContentPackManifest:
return ContentPackManifest(
name="my-pack",
version="1.0.0",
display_name="My Pack",
description="A custom content pack",
)
def get_dependencies(self) -> list[str]:
return ["maid-stdlib"]
def get_systems(self, world: World) -> list[System]:
return [MySystem(world)]
def get_events(self) -> list[type[Event]]:
return [MyEvent]
def register_commands(self, registry: CommandRegistry) -> None:
registry.register(...)
def register_document_schemas(self, store: DocumentStore) -> None:
store.register_schema("my_collection", MyModel)
async def on_load(self, engine: GameEngine) -> None:
# Initialize resources - use this for configuration that
# would otherwise require constructor arguments
self._initialized = True
async def on_unload(self, engine: GameEngine) -> None:
# Cleanup resources
pass
manifest
property
¶
manifest: ContentPackManifest
Get the content pack manifest.
Returns metadata about this pack including name, version, dependencies, and capabilities.
get_dependencies
¶
Get the names of content packs this pack depends on.
Dependencies must be loaded before this pack can be loaded. Returns a list of content pack names (not versions).
get_systems
¶
get_events
¶
get_events() -> list[type[Event]]
Get event types defined by this pack.
These event types can be used by the EventBus for publish/subscribe communication.
Returns:
| Type | Description |
|---|---|
list[type[Event]]
|
List of Event subclasses |
register_commands
¶
Register commands provided by this pack.
Commands are registered with the engine's CommandRegistry and can be executed by players.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
AnyCommandRegistry
|
The command registry to register with |
required |
register_document_schemas
¶
register_document_schemas(store: DocumentStore) -> None
Register document schemas used by this pack.
Schemas define the structure of documents stored in the document store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
DocumentStore
|
The document store to register schemas with |
required |
on_load
async
¶
on_load(engine: GameEngine) -> None
Called when the pack is loaded.
Use this hook to: - Initialize resources - Load data files - Subscribe to events - Set up background tasks
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
engine
|
GameEngine
|
The game engine |
required |
on_unload
async
¶
on_unload(engine: GameEngine) -> None
Called when the pack is unloaded.
Use this hook to: - Clean up resources - Save state - Unsubscribe from events - Cancel background tasks
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
engine
|
GameEngine
|
The game engine |
required |
LayeredCommandRegistry¶
Priority-based command resolution.
LayeredCommandRegistry
¶
Command registry with layered resolution for content packs.
Commands can be registered by multiple content packs. When a command is executed, the highest priority registration is used.
The registry now integrates with: - Hook system: Pre/post command hooks for logging, rate limiting, etc. - Lock system: Permission checks using lock expressions
Example
registry = LayeredCommandRegistry()
Set pack priorities (higher = wins)¶
registry.set_pack_priority("my-game", 100) registry.set_pack_priority("stdlib", 50) registry.set_pack_priority("engine", 0)
Register commands from different packs¶
registry.register("look", look_handler, pack_name="stdlib") registry.register("look", custom_look_handler, pack_name="my-game")
When "look" is executed, my-game's handler is used (priority 100)¶
Register hooks¶
registry.register_pre_hook("rate_limiter", check_rate_limit) registry.register_post_hook("logger", log_command)
Register custom lock functions¶
registry.register_lock_function("is_owner", check_ownership)
execute
async
¶
execute(
context: CommandContext,
player_access_level: AccessLevel = PLAYER,
) -> bool
Execute a command using the highest-priority handler with lock checking and hook pipeline.
Execution flow: 1. Find the command definition 2. Check lock expression (if defined) 3. Check access level 4. Run pre-hooks (can cancel execution) 5. Execute command handler 6. Run post-hooks (always runs, even on exception)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
CommandContext
|
Command context containing session, player_id, command, args, etc. |
required |
player_access_level
|
AccessLevel
|
The access level of the player executing |
PLAYER
|
Returns:
| Type | Description |
|---|---|
bool
|
True if command was handled successfully, False if command not found |
bool
|
or execution was cancelled |
Raises:
| Type | Description |
|---|---|
PermissionError
|
If player lacks required access level |
Package API¶
Full package API documentation:
maid_engine
¶
MAID Engine - Core infrastructure for building MUD games.
This package provides the foundational infrastructure for building Multi-User Dungeon (MUD) games, including:
- Entity Component System (ECS) for game entity management
- Event-driven communication via EventBus
- Network layer (Telnet and WebSocket support)
- Authentication and session management
- Storage abstraction (SQL for auth, document store for game data)
- Plugin/content pack system for extensibility
- AI provider abstraction
- Internationalization (i18n) support
AccessLevel
¶
Bases: IntEnum
Command access levels.
BaseContentPack
¶
Base implementation of ContentPack with sensible defaults.
Extend this class to create a content pack with minimal boilerplate. Override only the methods you need.
Example
class MyPack(BaseContentPack): @property def manifest(self) -> ContentPackManifest: return ContentPackManifest( name="my-pack", version="1.0.0", display_name="My Pack", description="Custom content", )
def get_systems(self, world: World) -> list[System]:
return [MySystem(world)]
manifest
property
¶
manifest: ContentPackManifest
Get the content pack manifest. Must be overridden.
get_dependencies
¶
get_systems
¶
on_load
async
¶
on_load(engine: GameEngine) -> None
on_unload
async
¶
on_unload(engine: GameEngine) -> None
register_commands
¶
register_document_schemas
¶
register_document_schemas(store: DocumentStore) -> None
CommandContext
dataclass
¶
CommandContext(
session: Any,
player_id: UUID,
command: str,
args: list[str],
raw_input: str,
world: World,
document_store: DocumentStore | None = None,
metadata: dict[str, Any] = dict(),
target: Any | None = None,
)
Context passed to command handlers.
Attributes:
| Name | Type | Description |
|---|---|---|
session |
Any
|
The player session |
player_id |
UUID
|
UUID of the player entity |
command |
str
|
The command name executed |
args |
list[str]
|
Command arguments |
raw_input |
str
|
Full raw input string |
world |
World
|
The game world |
document_store |
DocumentStore | None
|
Document store for persistence |
metadata |
dict[str, Any]
|
Additional metadata |
target |
Any | None
|
Optional target entity for lock evaluation (e.g., for owns()/holds() checks) |
CommandDefinition
dataclass
¶
CommandDefinition(
name: str,
handler: CommandHandler,
pack_name: str,
priority: int = 0,
aliases: list[str] = list(),
category: str = "general",
description: str = "",
usage: str = "",
access_level: AccessLevel = PLAYER,
hidden: bool = False,
locks: str = "",
metadata: dict[str, Any] = dict(),
)
Definition of a registered command.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Primary command name |
handler |
CommandHandler
|
Async function to handle the command |
pack_name |
str
|
Name of the content pack that registered this |
priority |
int
|
Priority for layered resolution |
aliases |
list[str]
|
Alternative names for this command |
category |
str
|
Command category for help |
description |
str
|
Short description |
usage |
str
|
Usage string |
access_level |
AccessLevel
|
Minimum access level required |
hidden |
bool
|
Whether to hide from help listings |
locks |
str
|
Lock expression for permission checks (e.g., "perm(admin) OR owns()") |
metadata |
dict[str, Any]
|
Additional metadata for hooks (e.g., cooldowns, combat state) |
CommandRegistry
¶
Simple command registry without layering.
For basic command registration without content pack support.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
all_commands
¶
all_commands() -> list[CommandDefinition]
commands_by_category
¶
commands_by_category() -> dict[
str, list[CommandDefinition]
]
Get commands grouped by category.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
execute
async
¶
execute(
context: CommandContext,
player_access_level: AccessLevel = PLAYER,
) -> bool
Execute a command.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
CommandContext
|
Command context |
required |
player_access_level
|
AccessLevel
|
The access level of the player executing |
PLAYER
|
Returns:
| Type | Description |
|---|---|
bool
|
True if command was handled successfully |
Raises:
| Type | Description |
|---|---|
PermissionError
|
If player lacks required access level |
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
register
¶
register(
name: str,
handler: CommandHandler,
*,
aliases: list[str] | None = None,
category: str = "general",
description: str = "",
usage: str = "",
access_level: AccessLevel = PLAYER,
hidden: bool = False,
) -> None
Register a command.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
unregister
¶
Unregister a command.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
Component
¶
Bases: BaseModel
Base class for all ECS components.
Components are pure data containers that can be attached to entities. They contain no logic - all behavior is implemented in Systems.
Example
class PositionComponent(Component): room_id: UUID x: int = 0 y: int = 0
ContentPack
¶
Bases: Protocol
Protocol defining the interface for content packs.
Content packs provide game functionality to the MAID engine. They can include: - ECS systems that process entities - Event types for communication - Commands for player interaction - Document schemas for persistence - Setup/teardown hooks
Important
Content packs that are discovered via entry points or directory scanning
MUST have a no-argument constructor (or a constructor where all parameters
have default values). This is because the discovery mechanism cannot pass
constructor arguments. If your pack requires initialization parameters,
consider using the on_load method or environment variables instead.
Example
class MyContentPack: def init(self) -> None: # No required arguments - this is important for auto-discovery! self._initialized = False
@property
def manifest(self) -> ContentPackManifest:
return ContentPackManifest(
name="my-pack",
version="1.0.0",
display_name="My Pack",
description="A custom content pack",
)
def get_dependencies(self) -> list[str]:
return ["maid-stdlib"]
def get_systems(self, world: World) -> list[System]:
return [MySystem(world)]
def get_events(self) -> list[type[Event]]:
return [MyEvent]
def register_commands(self, registry: CommandRegistry) -> None:
registry.register(...)
def register_document_schemas(self, store: DocumentStore) -> None:
store.register_schema("my_collection", MyModel)
async def on_load(self, engine: GameEngine) -> None:
# Initialize resources - use this for configuration that
# would otherwise require constructor arguments
self._initialized = True
async def on_unload(self, engine: GameEngine) -> None:
# Cleanup resources
pass
manifest
property
¶
manifest: ContentPackManifest
Get the content pack manifest.
Returns metadata about this pack including name, version, dependencies, and capabilities.
get_dependencies
¶
Get the names of content packs this pack depends on.
Dependencies must be loaded before this pack can be loaded. Returns a list of content pack names (not versions).
Source code in packages/maid-engine/src/maid_engine/plugins/protocol.py
get_events
¶
get_events() -> list[type[Event]]
Get event types defined by this pack.
These event types can be used by the EventBus for publish/subscribe communication.
Returns:
| Type | Description |
|---|---|
list[type[Event]]
|
List of Event subclasses |
Source code in packages/maid-engine/src/maid_engine/plugins/protocol.py
get_systems
¶
Get ECS systems provided by this pack.
Systems are registered with the engine's SystemManager and are updated each tick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
world
|
World
|
The game world to create systems for |
required |
Returns:
| Type | Description |
|---|---|
list[System]
|
List of System instances to register |
Source code in packages/maid-engine/src/maid_engine/plugins/protocol.py
on_load
async
¶
on_load(engine: GameEngine) -> None
Called when the pack is loaded.
Use this hook to: - Initialize resources - Load data files - Subscribe to events - Set up background tasks
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
engine
|
GameEngine
|
The game engine |
required |
Source code in packages/maid-engine/src/maid_engine/plugins/protocol.py
on_unload
async
¶
on_unload(engine: GameEngine) -> None
Called when the pack is unloaded.
Use this hook to: - Clean up resources - Save state - Unsubscribe from events - Cancel background tasks
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
engine
|
GameEngine
|
The game engine |
required |
Source code in packages/maid-engine/src/maid_engine/plugins/protocol.py
register_commands
¶
Register commands provided by this pack.
Commands are registered with the engine's CommandRegistry and can be executed by players.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
AnyCommandRegistry
|
The command registry to register with |
required |
Source code in packages/maid-engine/src/maid_engine/plugins/protocol.py
register_document_schemas
¶
register_document_schemas(store: DocumentStore) -> None
Register document schemas used by this pack.
Schemas define the structure of documents stored in the document store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
DocumentStore
|
The document store to register schemas with |
required |
Source code in packages/maid-engine/src/maid_engine/plugins/protocol.py
ContentPackLoader
¶
Manages content pack loading with dependency resolution.
Example
loader = ContentPackLoader()
Discover and register available packs¶
for pack in discover_content_packs(): loader.register(pack)
Load packs in dependency order¶
ordered_packs = loader.resolve_load_order() for pack in ordered_packs: engine.load_content_pack(pack)
Source code in packages/maid-engine/src/maid_engine/plugins/loader.py
can_unload
¶
Check if a pack can be unloaded.
Returns:
| Type | Description |
|---|---|
tuple[bool, list[str]]
|
Tuple of (can_unload, list of blocking dependents) |
Source code in packages/maid-engine/src/maid_engine/plugins/loader.py
get
¶
get(pack_name: str) -> ContentPack | None
get_dependents
¶
Get packs that depend on the given pack.
Source code in packages/maid-engine/src/maid_engine/plugins/loader.py
mark_loaded
¶
mark_unloaded
¶
register
¶
register(pack: ContentPack) -> None
resolve_load_order
¶
resolve_load_order(
pack_names: list[str] | None = None,
) -> list[ContentPack]
Resolve the loading order for content packs.
Uses topological sort to order packs by dependencies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_names
|
list[str] | None
|
Specific packs to load (default: all available) |
None
|
Returns:
| Type | Description |
|---|---|
list[ContentPack]
|
List of packs in dependency order |
Raises:
| Type | Description |
|---|---|
DependencyError
|
If dependencies cannot be resolved |
Source code in packages/maid-engine/src/maid_engine/plugins/loader.py
unregister
¶
unregister(pack_name: str) -> ContentPack | None
ContentPackManifest
dataclass
¶
ContentPackManifest(
name: str,
version: str,
display_name: str = "",
description: str = "",
dependencies: dict[str, str] = dict(),
provides: list[str] = list(),
requires: list[str] = list(),
authors: list[str] = list(),
license: str = "",
homepage: str = "",
keywords: list[str] = list(),
)
Metadata about a content pack.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Unique identifier for the pack (e.g., "classic-rpg") |
version |
str
|
Semantic version string (e.g., "0.1.0") |
display_name |
str
|
Human-readable name (e.g., "Classic RPG") |
description |
str
|
Brief description of the pack |
dependencies |
dict[str, str]
|
Dict of pack_name -> version_constraint |
provides |
list[str]
|
List of capability identifiers this pack provides |
requires |
list[str]
|
List of capability identifiers this pack requires |
authors |
list[str]
|
List of author names |
license |
str
|
SPDX license identifier |
homepage |
str
|
URL to pack homepage/repository |
keywords |
list[str]
|
List of keywords for discovery |
from_dict
classmethod
¶
from_dict(data: dict[str, Any]) -> ContentPackManifest
Create manifest from a dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
dict[str, Any]
|
Dictionary with 'pack' key containing manifest data |
required |
Returns:
| Type | Description |
|---|---|
ContentPackManifest
|
ContentPackManifest instance |
Source code in packages/maid-engine/src/maid_engine/plugins/manifest.py
from_toml
classmethod
¶
from_toml(path: Path) -> ContentPackManifest
Load manifest from a TOML file.
Expected format
[pack] name = "my-pack" version = "1.0.0" display_name = "My Pack" description = "A custom content pack"
[pack.dependencies] maid-stdlib = ">=0.1.0"
[pack.capabilities] provides = ["combat-system", "magic-system"] requires = ["ecs", "event-bus"]
Source code in packages/maid-engine/src/maid_engine/plugins/manifest.py
satisfies_dependency
¶
Check if this pack satisfies a dependency requirement.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Required pack name |
required |
version
|
str
|
Version constraint (e.g., ">=0.1.0") |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if this pack satisfies the requirement |
Source code in packages/maid-engine/src/maid_engine/plugins/manifest.py
to_dict
¶
Convert manifest to dictionary.
Source code in packages/maid-engine/src/maid_engine/plugins/manifest.py
DocumentCollection
¶
Bases: ABC
Abstract base class for document collections.
A collection holds documents of a specific type, identified by UUID. All operations are async for compatibility with async databases.
Example
Get a collection¶
characters = store.get_collection("characters")
CRUD operations¶
doc_id = await characters.create(character_data) character = await characters.get(doc_id) await characters.update(doc_id, updated_data) await characters.delete(doc_id)
Query¶
results = await characters.query(QueryOptions( filters={"level": 10}, order_by="name", limit=20 ))
count
abstractmethod
async
¶
Count documents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filters
|
dict[str, Any] | None
|
Optional filters to apply |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of matching documents |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
create
abstractmethod
async
¶
Create a new document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
T
|
Document data |
required |
doc_id
|
UUID | None
|
Optional specific UUID (generated if not provided) |
None
|
Returns:
| Type | Description |
|---|---|
UUID
|
UUID of created document |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
delete
abstractmethod
async
¶
Delete a document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc_id
|
UUID
|
Document UUID |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if document was deleted, False if not found |
exists
abstractmethod
async
¶
Check if a document exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc_id
|
UUID
|
Document UUID |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if document exists |
get
abstractmethod
async
¶
Get a document by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc_id
|
UUID
|
Document UUID |
required |
Returns:
| Type | Description |
|---|---|
T | None
|
Document if found, None otherwise |
get_many
abstractmethod
async
¶
Get multiple documents by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc_ids
|
list[UUID]
|
List of document UUIDs |
required |
Returns:
| Type | Description |
|---|---|
list[T]
|
List of found documents (may be shorter than doc_ids) |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
query
abstractmethod
async
¶
query(options: QueryOptions) -> list[T]
Query documents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
options
|
QueryOptions
|
Query options (filters, ordering, pagination) |
required |
Returns:
| Type | Description |
|---|---|
list[T]
|
List of matching documents |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
update
abstractmethod
async
¶
Update an existing document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc_id
|
UUID
|
Document UUID |
required |
document
|
T
|
New document data |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if document was updated, False if not found |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
DocumentStore
¶
Bases: ABC
Abstract base class for the document store.
The document store manages collections of documents. Content packs register their document schemas, then use collections for persistence.
Example
In content pack initialization¶
store.register_schema("characters", CharacterModel) store.register_schema("items", ItemModel)
Later, in game logic¶
characters = store.get_collection("characters") character = await characters.get(character_id)
query_collector
property
¶
Get the query collector for profiling (if enabled).
close
abstractmethod
async
¶
Close the document store.
Closes database connections and cleans up resources.
collection_names
abstractmethod
¶
Get names of all registered collections.
Returns:
| Type | Description |
|---|---|
list[str]
|
List of collection names |
get_collection
abstractmethod
¶
get_collection(name: str) -> DocumentCollection[Any]
Get a document collection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Collection name |
required |
Returns:
| Type | Description |
|---|---|
DocumentCollection[Any]
|
DocumentCollection for the given name |
Raises:
| Type | Description |
|---|---|
KeyError
|
If collection is not registered |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
has_collection
abstractmethod
¶
Check if a collection is registered.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Collection name |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if collection exists |
initialize
abstractmethod
async
¶
Initialize the document store.
Creates necessary database tables/structures. Should be called before using the store.
register_schema
abstractmethod
¶
Register a document schema.
Must be called before using a collection. The schema defines the structure of documents in the collection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Collection name |
required |
schema
|
type[BaseModel]
|
Pydantic model class for document validation |
required |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
set_query_collector
¶
Set the query collector for profiling.
The query collector must be started externally (e.g., via ProfileManager). When set, the store will record query profiling data during operations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collector
|
QueryCollector | None
|
The QueryCollector instance, or None to disable profiling. |
required |
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
EngineState
¶
Bases: Enum
Game engine states.
Entity
¶
Entity(
entity_id: UUID | None = None,
manager: EntityManager | None = None,
)
Represents a game entity as a collection of components.
Entities are essentially just IDs that group components together. The EntityManager handles the actual component storage and queries.
Example
entity = Entity() entity.add(PositionComponent(room_id=room.id)) entity.add(HealthComponent(current=100, maximum=100))
if entity.has(HealthComponent): health = entity.get(HealthComponent) health.damage(10)
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
add
¶
Add a component to this entity.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
get
¶
Get a component by type. Raises KeyError if not found.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
has
¶
has(*component_types: type[Component]) -> bool
Check if entity has all specified component types.
has_any
¶
has_any(*component_types: type[Component]) -> bool
Check if entity has any of the specified component types.
has_tag
¶
remove
¶
Remove and return a component from this entity.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
remove_tag
¶
Remove a tag from this entity. Returns True if tag was present.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
to_dict
¶
Serialize entity to dictionary.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
try_get
¶
Get a component by type, or None if not found.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
EntityManager
¶
Manages all entities and provides efficient component queries.
The EntityManager maintains indexes for fast component-based queries and handles entity lifecycle events.
Example
manager = EntityManager()
Create entities¶
player = manager.create() player.add(PositionComponent(room_id=room_id)) player.add(HealthComponent(current=100, maximum=100))
Query entities with specific components¶
for entity in manager.with_components(PositionComponent, HealthComponent): pos = entity.get(PositionComponent) health = entity.get(HealthComponent)
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
clear
¶
Remove all entities.
count
¶
destroy
¶
Destroy an entity. Returns True if entity existed.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
get_or_raise
¶
get_or_raise(entity_id: UUID) -> Entity
Get an entity by ID, raising KeyError if not found.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
with_components
¶
Get all entities that have all specified component types.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
with_tags
¶
with_tags(*tags: str) -> Iterator[Entity]
Get all entities that have all specified tags.
Source code in packages/maid-engine/src/maid_engine/core/ecs/entity.py
Event
dataclass
¶
Base class for all events.
Events are messages that can be emitted and handled by subscribers. They carry data about something that happened in the game.
Example
@dataclass class PlayerDamagedEvent(Event): player_id: UUID damage: int source_id: UUID | None = None
EventBus
¶
Publish/subscribe event system.
The EventBus allows systems to communicate through events without direct coupling. Handlers can be async or sync.
Supports wildcard subscriptions via subscribe_all() to receive all events.
Example
bus = EventBus()
async def on_damage(event: DamageDealtEvent): print(f"Damage dealt: {event.damage}")
bus.subscribe(DamageDealtEvent, on_damage)
Subscribe to ALL events (wildcard)¶
def log_event(event: Event): print(f"Event: {event.event_type}") bus.subscribe_all(log_event)
await bus.emit(DamageDealtEvent( source_id=attacker.id, target_id=defender.id, damage=25, damage_type="physical" ))
Source code in packages/maid-engine/src/maid_engine/core/events.py
processed_count
property
¶
Get the total number of events that have been processed.
This count includes all events emitted via emit() since the EventBus was created or last cleared. It does not include events queued via emit_sync() that haven't been processed yet.
Returns:
| Type | Description |
|---|---|
int
|
Total number of events processed |
clear
¶
Remove all handlers, pending events, and reset counters.
Source code in packages/maid-engine/src/maid_engine/core/events.py
emit
async
¶
emit(event: Event) -> None
Emit an event immediately, invoking all handlers.
Handlers are invoked in priority order. If an event is cancelled, remaining handlers are not called.
Both type-specific handlers and wildcard handlers (registered via subscribe_all) are invoked.
Handler removals during dispatch are deferred until dispatch completes.
Source code in packages/maid-engine/src/maid_engine/core/events.py
emit_sync
¶
emit_sync(event: Event) -> None
Queue an event for later processing.
Use this when you need to emit from a sync context. Call process_pending() to handle queued events.
Source code in packages/maid-engine/src/maid_engine/core/events.py
get_handler_ids_for_pack
¶
Get all handler IDs registered by a content pack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
Name of the content pack |
required |
Returns:
| Type | Description |
|---|---|
set[UUID]
|
Set of handler UUIDs registered by the pack |
Source code in packages/maid-engine/src/maid_engine/core/events.py
get_handler_source
¶
Get the source pack for a handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler_id
|
UUID
|
The handler's UUID |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The pack name that registered this handler, or None if unknown |
Source code in packages/maid-engine/src/maid_engine/core/events.py
get_handlers_for_pack
¶
Get all handlers registered by a content pack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
Name of the content pack |
required |
Returns:
| Type | Description |
|---|---|
dict[str, list[EventHandler]]
|
Dictionary mapping event type names (strings) to lists of handlers |
Source code in packages/maid-engine/src/maid_engine/core/events.py
handler_count
¶
handler_count(event_type: type[Event] | None = None) -> int
Get the number of handlers, optionally filtered by event type.
Source code in packages/maid-engine/src/maid_engine/core/events.py
has_handlers
¶
has_handlers(event_type: type[Event]) -> bool
Check if any handlers are registered for an event type.
is_dispatching
¶
Check if currently dispatching events.
Returns:
| Type | Description |
|---|---|
bool
|
True if in the middle of an event dispatch |
process_pending
async
¶
Process all pending events.
Returns:
| Type | Description |
|---|---|
int
|
Number of events processed |
Source code in packages/maid-engine/src/maid_engine/core/events.py
subscribe
¶
subscribe(
event_type: type[E],
handler: EventHandler | SyncEventHandler,
priority: EventPriority = NORMAL,
once: bool = False,
source_pack: str | None = None,
) -> UUID
Subscribe to an event type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
type[E]
|
The event class to subscribe to |
required |
handler
|
EventHandler | SyncEventHandler
|
Async or sync function to handle events |
required |
priority
|
EventPriority
|
Handler priority (higher priority runs first) |
NORMAL
|
once
|
bool
|
If True, handler is removed after first invocation |
False
|
source_pack
|
str | None
|
Name of the content pack registering this handler (for hot reload) |
None
|
Returns:
| Type | Description |
|---|---|
UUID
|
Handler ID for unsubscribing |
Source code in packages/maid-engine/src/maid_engine/core/events.py
subscribe_all
¶
subscribe_all(
handler: EventHandler | SyncEventHandler,
priority: EventPriority = NORMAL,
once: bool = False,
source_pack: str | None = None,
) -> UUID
Subscribe to ALL events (wildcard subscription).
This handler will be invoked for every event emitted, regardless of type. Useful for logging, metrics collection, or debugging.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler
|
EventHandler | SyncEventHandler
|
Async or sync function to handle events |
required |
priority
|
EventPriority
|
Handler priority (higher priority runs first) |
NORMAL
|
once
|
bool
|
If True, handler is removed after first invocation |
False
|
source_pack
|
str | None
|
Name of the content pack registering this handler (for hot reload) |
None
|
Returns:
| Type | Description |
|---|---|
UUID
|
Handler ID for unsubscribing |
Source code in packages/maid-engine/src/maid_engine/core/events.py
unsubscribe
¶
Unsubscribe a handler by ID.
If called during event dispatch, the removal is deferred until the dispatch completes to ensure safe iteration.
Returns:
| Type | Description |
|---|---|
bool
|
True if handler was found and removed (or queued for removal) |
Source code in packages/maid-engine/src/maid_engine/core/events.py
unsubscribe_all
¶
unsubscribe_all(event_type: type[Event]) -> int
Unsubscribe all handlers for an event type.
Returns:
| Type | Description |
|---|---|
int
|
Number of handlers removed |
Source code in packages/maid-engine/src/maid_engine/core/events.py
unsubscribe_pack
¶
Unsubscribe all handlers registered by a content pack.
If called during event dispatch, the removal is deferred until the dispatch completes to ensure safe iteration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
Name of the content pack whose handlers should be removed |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of handlers removed (or queued for removal) |
Source code in packages/maid-engine/src/maid_engine/core/events.py
GameEngine
¶
GameEngine(
settings: Settings | None = None,
document_store: DocumentStore | None = None,
)
Main game engine that runs the tick loop.
The GameEngine manages the game world, networking, and the main tick loop that drives all game systems. It is content-agnostic - all game-specific functionality comes from content packs.
Example
engine = GameEngine()
Load content packs¶
engine.load_content_pack(my_content_pack)
await engine.start()
Engine runs until stopped¶
In another context:¶
await engine.stop()
Source code in packages/maid-engine/src/maid_engine/core/engine.py
bridge_manager
property
¶
Get the bridge manager for external service integration.
characters
property
¶
Get character manager.
Note: This is a placeholder. Content packs should attach their managers to the engine or world.
hot_reload
property
¶
Get the hot reload manager (lazy-initialized).
The hot reload manager is created on first access. This allows hot reload operations to be performed on the engine at runtime, including loading, unloading, and reloading content packs while the engine is running.
Returns:
| Type | Description |
|---|---|
HotReloadManager
|
The HotReloadManager instance for this engine. |
provider_registry
property
¶
Get the LLM provider registry.
The provider registry manages AI/LLM providers (Anthropic, OpenAI, Ollama, etc.) for use by AI-powered features like NPC dialogue. Providers are initialized from settings during engine construction.
Returns:
| Type | Description |
|---|---|
LLMProviderRegistry
|
The LLMProviderRegistry instance for this engine. |
quest_manager
property
¶
Get quest manager.
Note: This is set by content packs that provide quest functionality.
reward_distributor
property
¶
Get reward distributor.
Note: This is set by content packs that provide quest functionality.
rss_feed_manager
property
¶
Get the RSS feed manager (if enabled).
tick_collector
property
¶
Get the tick collector for profiling (if enabled).
add_shutdown_callback
¶
get_stats
¶
Get engine statistics.
Source code in packages/maid-engine/src/maid_engine/core/engine.py
load_content_pack
¶
load_content_pack(
pack: ContentPack, use_hot_reload: bool = False
) -> None
Load a content pack.
When the engine is stopped, content packs are loaded synchronously. When the engine is running, set use_hot_reload=True to use the hot reload manager for safe runtime loading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack
|
ContentPack
|
The content pack to load. |
required |
use_hot_reload
|
bool
|
If True and engine is running, use hot reload. If False and engine is running, raises RuntimeError. |
False
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If engine is running and use_hot_reload is False. |
ValueError
|
If pack is already loaded or dependencies are missing. |
Source code in packages/maid-engine/src/maid_engine/core/engine.py
relay_to_external
async
¶
Relay a game message to mapped external channels.
This is a convenience method that wraps bridge_manager.relay_to_external(). Content packs can call this to send game channel messages to external services like Discord and IRC.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game_channel
|
str
|
The game channel name (e.g., "ooc", "chat", "newbie") |
required |
sender_name
|
str
|
The name of the sender in the game |
required |
message
|
str
|
The message content |
required |
Source code in packages/maid-engine/src/maid_engine/core/engine.py
run
async
¶
Start and run until stopped.
This is a convenience method that starts the engine and waits for it to be stopped.
Source code in packages/maid-engine/src/maid_engine/core/engine.py
set_server
¶
set_tick_collector
¶
Set the tick collector for profiling.
The tick collector must be started externally (e.g., via ProfileManager). When set, the engine will record tick profiling data during each tick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collector
|
TickCollector | None
|
The TickCollector instance, or None to disable profiling. |
required |
Source code in packages/maid-engine/src/maid_engine/core/engine.py
start
async
¶
Start the game engine.
Source code in packages/maid-engine/src/maid_engine/core/engine.py
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | |
stop
async
¶
Stop the game engine.
Source code in packages/maid-engine/src/maid_engine/core/engine.py
unload_content_pack
¶
Unload a content pack.
Can only be done when engine is stopped. Returns True if pack was unloaded.
Source code in packages/maid-engine/src/maid_engine/core/engine.py
InMemoryDocumentStore
¶
Bases: DocumentStore
In-memory document store for testing.
Uses dictionaries. Not suitable for production.
Source code in packages/maid-engine/src/maid_engine/storage/document_store.py
LayeredCommandRegistry
¶
Command registry with layered resolution for content packs.
Commands can be registered by multiple content packs. When a command is executed, the highest priority registration is used.
The registry now integrates with: - Hook system: Pre/post command hooks for logging, rate limiting, etc. - Lock system: Permission checks using lock expressions
Example
registry = LayeredCommandRegistry()
Set pack priorities (higher = wins)¶
registry.set_pack_priority("my-game", 100) registry.set_pack_priority("stdlib", 50) registry.set_pack_priority("engine", 0)
Register commands from different packs¶
registry.register("look", look_handler, pack_name="stdlib") registry.register("look", custom_look_handler, pack_name="my-game")
When "look" is executed, my-game's handler is used (priority 100)¶
Register hooks¶
registry.register_pre_hook("rate_limiter", check_rate_limit) registry.register_post_hook("logger", log_command)
Register custom lock functions¶
registry.register_lock_function("is_owner", check_ownership)
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
event_bus
property
writable
¶
Get the event bus for PlayerCommandEvent emission.
hook_registry
property
¶
Get the hook registry for advanced hook management.
lock_evaluator
property
¶
Get the lock evaluator for advanced lock management.
all_commands
¶
all_commands() -> list[CommandDefinition]
Get highest-priority definitions for all commands.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
commands_by_category
¶
commands_by_category() -> dict[
str, list[CommandDefinition]
]
Get commands grouped by category.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
execute
async
¶
execute(
context: CommandContext,
player_access_level: AccessLevel = PLAYER,
) -> bool
Execute a command using the highest-priority handler with lock checking and hook pipeline.
Execution flow: 1. Find the command definition 2. Check lock expression (if defined) 3. Check access level 4. Run pre-hooks (can cancel execution) 5. Execute command handler 6. Run post-hooks (always runs, even on exception)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
CommandContext
|
Command context containing session, player_id, command, args, etc. |
required |
player_access_level
|
AccessLevel
|
The access level of the player executing |
PLAYER
|
Returns:
| Type | Description |
|---|---|
bool
|
True if command was handled successfully, False if command not found |
bool
|
or execution was cancelled |
Raises:
| Type | Description |
|---|---|
PermissionError
|
If player lacks required access level |
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | |
get
¶
get(name: str) -> CommandDefinition | None
Get the highest-priority command definition.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
get_all_layers
¶
get_all_layers(name: str) -> list[CommandDefinition]
Get all definitions for a command across all packs.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
get_commands_for_pack
¶
Get all command names registered by a content pack.
This is useful for hot reload inspection to see what commands a pack has registered.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
Name of the content pack |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
List of command names registered by the pack |
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
get_pack_command_definitions
¶
get_pack_command_definitions(
pack_name: str,
) -> list[CommandDefinition]
Get all command definitions registered by a content pack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
Name of the content pack |
required |
Returns:
| Type | Description |
|---|---|
list[CommandDefinition]
|
List of CommandDefinition objects registered by the pack |
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
get_pack_priority
¶
register
¶
register(
name: str,
handler: CommandHandler,
pack_name: str,
*,
priority: int | None = None,
aliases: list[str] | None = None,
category: str = "general",
description: str = "",
usage: str = "",
access_level: AccessLevel = PLAYER,
hidden: bool = False,
locks: str = "",
metadata: dict[str, Any] | None = None,
) -> None
Register a command from a content pack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Primary command name |
required |
handler
|
CommandHandler
|
Async function to handle the command |
required |
pack_name
|
str
|
Name of the content pack registering this command |
required |
priority
|
int | None
|
Priority for layered resolution (defaults to pack priority) |
None
|
aliases
|
list[str] | None
|
Alternative names for this command |
None
|
category
|
str
|
Command category for help |
'general'
|
description
|
str
|
Short description |
''
|
usage
|
str
|
Usage string |
''
|
access_level
|
AccessLevel
|
Minimum access level required |
PLAYER
|
hidden
|
bool
|
Whether to hide from help listings |
False
|
locks
|
str
|
Lock expression for permission checks (e.g., "perm(admin) OR owns()") |
''
|
metadata
|
dict[str, Any] | None
|
Additional metadata for hooks (e.g., cooldowns, combat state) |
None
|
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
register_lock_function
¶
Register a custom lock function.
Lock functions are named predicates that can be used in lock expressions. Each function receives a LockContext and a list of string arguments, and returns a boolean.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The function name used in expressions (e.g., "is_owner") |
required |
func
|
Callable[[LockContext, list[str]], bool]
|
The function to call, receives (context, args) and returns bool |
required |
Example
def check_gold(ctx: LockContext, args: list[str]) -> bool: player = ctx.get_player() if not player: return False required = int(args[0]) if args else 0 return player.gold >= required
registry.register_lock_function("has_gold", check_gold)
Now you can use "has_gold(100)" in lock expressions¶
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
register_post_hook
¶
register_post_hook(
name: str,
handler: Callable[..., Any],
priority: HookPriority = NORMAL,
commands: list[str] | None = None,
categories: list[str] | None = None,
) -> None
Register a post-command hook.
Post-hooks run after the command handler completes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Unique identifier for the hook |
required |
handler
|
Callable[..., Any]
|
Async or sync function accepting PostHookContext |
required |
priority
|
HookPriority
|
Execution priority (lower runs first) |
NORMAL
|
commands
|
list[str] | None
|
Filter to specific command names (None = all) |
None
|
categories
|
list[str] | None
|
Filter to specific categories (None = all) |
None
|
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
register_pre_hook
¶
register_pre_hook(
name: str,
handler: Callable[..., Any],
priority: HookPriority = NORMAL,
commands: list[str] | None = None,
categories: list[str] | None = None,
) -> None
Register a pre-command hook.
Pre-hooks run before the command handler and can cancel execution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Unique identifier for the hook |
required |
handler
|
Callable[..., Any]
|
Async or sync function accepting PreHookContext |
required |
priority
|
HookPriority
|
Execution priority (lower runs first) |
NORMAL
|
commands
|
list[str] | None
|
Filter to specific command names (None = all) |
None
|
categories
|
list[str] | None
|
Filter to specific categories (None = all) |
None
|
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
set_pack_priority
¶
Set the priority for a content pack.
Higher priority packs override lower priority ones.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
unregister
¶
Unregister a command from a specific pack.
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
unregister_hook
¶
Unregister a hook by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The unique identifier of the hook to remove |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if a hook was found and removed, False otherwise |
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
unregister_pack
¶
Unregister all commands from a pack.
Returns:
| Type | Description |
|---|---|
int
|
Number of commands unregistered |
Source code in packages/maid-engine/src/maid_engine/commands/registry.py
QueryOptions
dataclass
¶
QueryOptions(
filters: dict[str, Any] = dict(),
order_by: str | None = None,
order: SortOrder = ASC,
limit: int | None = None,
offset: int = 0,
)
Options for querying documents.
Attributes:
| Name | Type | Description |
|---|---|---|
filters |
dict[str, Any]
|
Dict of field_name -> value for exact matches |
order_by |
str | None
|
Field name to sort by |
order |
SortOrder
|
Sort direction |
limit |
int | None
|
Maximum number of results |
offset |
int
|
Number of results to skip |
RoomEnterEvent
dataclass
¶
RoomIndex
¶
Index for efficient room-based entity lookups.
Source code in packages/maid-engine/src/maid_engine/core/world.py
add
¶
Add entity to room index.
Source code in packages/maid-engine/src/maid_engine/core/world.py
clear
¶
count_in_room
¶
get_entities
¶
get_room
¶
move
¶
Move entity to new room. Returns previous room ID.
Source code in packages/maid-engine/src/maid_engine/core/world.py
remove
¶
Remove entity from index. Returns previous room ID.
Source code in packages/maid-engine/src/maid_engine/core/world.py
RoomLeaveEvent
dataclass
¶
SortOrder
¶
Bases: Enum
Sort order for queries.
StorageAware
¶
Bases: Protocol
Protocol for systems that need document store access.
Systems implementing this protocol will automatically receive the document store during registration with the engine.
Example
class GuildSystem(System, StorageAware): def init(self, world: World) -> None: super().init(world) self._storage: DocumentStore | None = None
def set_storage(self, store: DocumentStore) -> None:
self._storage = store
async def startup(self) -> None:
if self._storage:
# Load from database
...
set_storage
¶
set_storage(store: DocumentStore) -> None
Receive the document store for persistence.
Called automatically by the engine when the system is registered.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
DocumentStore
|
The document store instance |
required |
Source code in packages/maid-engine/src/maid_engine/storage/protocols.py
System
¶
Bases: ABC
Base class for all ECS systems.
Systems contain the logic that operates on entities with specific components. They are executed each tick by the SystemManager.
Example
class MovementSystem(System): priority = 10 # Lower = runs earlier
async def update(self, delta: float) -> None:
for entity in self.entities.with_components(
PositionComponent, MovementComponent
):
pos = entity.get(PositionComponent)
mov = entity.get(MovementComponent)
# Process movement...
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
SystemManager
¶
Manages and runs all ECS systems.
The SystemManager handles system lifecycle and executes systems in priority order each tick. It also tracks which content pack registered each system to support hot reloading.
Example
manager = SystemManager(world) manager.register(MovementSystem(world), source_pack="maid-stdlib") manager.register(CombatSystem(world), source_pack="maid-classic-rpg")
In game loop¶
await manager.update(delta_time)
Hot reload: unregister all systems from a pack¶
removed = await manager.unregister_systems_for_pack("maid-classic-rpg")
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
disable
¶
disable(system_type: type[System]) -> bool
Disable a system. Returns True if system exists.
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
enable
¶
enable(system_type: type[System]) -> bool
Enable a system. Returns True if system exists.
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
get
¶
get_or_raise
¶
Get a registered system by type, raising KeyError if not found.
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
get_source_pack
¶
get_source_pack(system_type: type[System]) -> str | None
Get the source pack name for a system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system_type
|
type[System]
|
The type of system to look up |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The pack name or None if no source pack was specified |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
get_system_dependents
¶
Get systems that depend on the given system type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system_type
|
type[System]
|
The system type to check |
required |
Returns:
| Type | Description |
|---|---|
list[type[System]]
|
List of system types that depend on this system |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
get_system_types_for_pack
¶
get_system_types_for_pack(
pack_name: str,
) -> list[type[System]]
Get all system types registered by a specific content pack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
The name of the content pack |
required |
Returns:
| Type | Description |
|---|---|
list[type[System]]
|
List of system types registered by this pack |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
get_systems_for_pack
¶
get_systems_for_pack(pack_name: str) -> list[System]
Get all systems registered by a specific content pack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
The name of the content pack |
required |
Returns:
| Type | Description |
|---|---|
list[System]
|
List of systems registered by this pack |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
pause_for_removal
async
¶
Pause tick processing for safe system removal.
This method waits for any in-progress tick to complete and prevents new ticks from starting until resume_after_removal is called.
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
register
¶
register(
system: System,
source_pack: str | None = None,
dependencies: list[type[System]] | None = None,
) -> None
Register a system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system
|
System
|
The system instance to register |
required |
source_pack
|
str | None
|
Optional name of the content pack that registered this system |
None
|
dependencies
|
list[type[System]] | None
|
Optional list of system types this system depends on |
None
|
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
remove_system_safely
async
¶
remove_system_safely(
system_type: type[System],
check_dependencies: bool = True,
) -> System | None
Remove a single system safely with tick pause.
This is a convenience method that handles pausing ticks, removing the system, and resuming ticks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system_type
|
type[System]
|
The type of system to remove |
required |
check_dependencies
|
bool
|
Whether to check for dependent systems |
True
|
Returns:
| Type | Description |
|---|---|
System | None
|
The removed system or None if not found |
Raises:
| Type | Description |
|---|---|
SystemDependencyError
|
If other systems depend on this one |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
resume_after_removal
async
¶
Resume tick processing after system removal.
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
safe_removal_context
async
¶
Context manager for safe system removal.
This provides a convenient way to safely remove systems while ensuring ticks are paused and properly resumed.
Example
async with manager.safe_removal_context() as ctx: await ctx.remove_system(MovementSystem) await ctx.remove_system(CombatSystem)
Yields:
| Type | Description |
|---|---|
'AsyncIterator[SystemRemovalContext]'
|
SystemRemovalContext for performing removals |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
shutdown
async
¶
Shut down all systems.
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
startup
async
¶
unregister
¶
Unregister a system by type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
system_type
|
type[System]
|
The type of system to unregister |
required |
Returns:
| Type | Description |
|---|---|
System | None
|
The unregistered system or None if not found |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
unregister_systems_for_pack
async
¶
unregister_systems_for_pack(
pack_name: str, check_dependencies: bool = True
) -> list[System]
Unregister all systems registered by a content pack.
This method safely removes all systems from a pack, calling shutdown on each system and respecting dependency ordering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pack_name
|
str
|
The name of the content pack |
required |
check_dependencies
|
bool
|
Whether to check for and warn about dependencies |
True
|
Returns:
| Type | Description |
|---|---|
list[System]
|
List of systems that were unregistered |
Raises:
| Type | Description |
|---|---|
SystemDependencyError
|
If check_dependencies is True and systems from other packs depend on systems being removed |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
update
async
¶
Update all enabled systems.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
delta
|
float
|
Time since last update in seconds |
required |
Source code in packages/maid-engine/src/maid_engine/core/ecs/system.py
TickEvent
dataclass
¶
TranslationCatalog
¶
A catalog of translations for a single locale.
The catalog stores translations indexed by their msgid (and optional context). It supports loading from PO and MO files, plural forms, and context-based lookups.
Attributes:
| Name | Type | Description |
|---|---|---|
locale |
The locale code (e.g., 'en_US', 'de_DE'). |
|
entries |
dict[str, TranslationEntry]
|
Dictionary mapping keys to TranslationEntry objects. |
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locale
|
str
|
The locale code for this catalog. |
required |
Source code in packages/maid-engine/src/maid_engine/i18n/catalog.py
get_entry
¶
get_entry(
msgid: str, context: str | None = None
) -> TranslationEntry | None
Get the translation entry for a msgid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msgid
|
str
|
The message to look up. |
required |
context
|
str | None
|
Optional context for disambiguation. |
None
|
Returns:
| Type | Description |
|---|---|
TranslationEntry | None
|
The TranslationEntry, or None if not found. |
Source code in packages/maid-engine/src/maid_engine/i18n/catalog.py
has_translation
¶
Check if a translation exists for the given msgid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msgid
|
str
|
The message to check. |
required |
context
|
str | None
|
Optional context for disambiguation. |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if a non-fuzzy translation exists. |
Source code in packages/maid-engine/src/maid_engine/i18n/catalog.py
load
classmethod
¶
load(
path: str | Path, locale: str | None = None
) -> TranslationCatalog
Load a translation catalog from a file.
Supports both PO and MO file formats (detected by extension).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to the translation file. |
required |
locale
|
str | None
|
Optional locale override (defaults to filename). |
None
|
Returns:
| Type | Description |
|---|---|
TranslationCatalog
|
A TranslationCatalog instance. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
ValueError
|
If the file format is not supported. |
Source code in packages/maid-engine/src/maid_engine/i18n/catalog.py
translate
¶
translate(
msgid: str,
context: str | None = None,
n: int | None = None,
default: str | None = None,
) -> str
Translate a message.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msgid
|
str
|
The message to translate. |
required |
context
|
str | None
|
Optional context for disambiguation. |
None
|
n
|
int | None
|
The number for plural selection (None for singular). |
None
|
default
|
str | None
|
Default value if translation not found (defaults to msgid). |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The translated string, or default/msgid if not found. |
Source code in packages/maid-engine/src/maid_engine/i18n/catalog.py
TranslationEntry
dataclass
¶
TranslationEntry(
msgid: str,
msgstr: str = "",
msgstr_plural: list[str] = list(),
msgid_plural: str | None = None,
context: str | None = None,
fuzzy: bool = False,
)
A single translation entry.
Attributes:
| Name | Type | Description |
|---|---|---|
msgid |
str
|
The original message (source string). |
msgstr |
str
|
The translated message (single string for singular). |
msgstr_plural |
list[str]
|
List of plural forms (index 0 is singular). |
msgid_plural |
str | None
|
The plural form of the source string. |
context |
str | None
|
Optional context for disambiguation. |
fuzzy |
bool
|
Whether this translation is marked as fuzzy/uncertain. |
get_translation
¶
Get the translation for this entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int | None
|
The number for plural selection (None for singular). |
None
|
plural_expr
|
str
|
Expression to evaluate plural form index. |
'(n != 1)'
|
Returns:
| Type | Description |
|---|---|
str
|
The translated string, or empty string if not translated. |
Source code in packages/maid-engine/src/maid_engine/i18n/catalog.py
Translator
¶
Translator(
default_locale: str = "en",
fallback_locale: str | None = None,
log_missing: bool = True,
missing_handler: Callable[[str, str | None, str], None]
| None = None,
)
Translation service that manages catalogs and provides translation functions.
The Translator loads translation catalogs for multiple locales and provides methods for translating messages with support for: - Locale fallback chains - Plural forms - Context-based disambiguation - Missing translation logging
Example
translator = Translator(default_locale="en", fallback_locale="en") translator.load_directory("/path/to/locales") translator.translate("Hello, world!") 'Hallo, Welt!' # if current_locale is 'de'
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
default_locale
|
str
|
The default locale to use when none is set. |
'en'
|
fallback_locale
|
str | None
|
Locale to fall back to when translation is missing. |
None
|
log_missing
|
bool
|
Whether to log missing translations. |
True
|
missing_handler
|
Callable[[str, str | None, str], None] | None
|
Optional callback for missing translations. Called with (msgid, context, locale). |
None
|
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
get_catalog
¶
get_catalog(locale: str) -> TranslationCatalog | None
Get the catalog for a specific locale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locale
|
str
|
The locale code. |
required |
Returns:
| Type | Description |
|---|---|
TranslationCatalog | None
|
The TranslationCatalog, or None if not loaded. |
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
get_current_locale
¶
Get the current locale from context.
Returns:
| Type | Description |
|---|---|
str
|
The current locale code. |
gettext
¶
Translate a message (GNU gettext compatible).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msgid
|
str
|
The message to translate. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The translated string. |
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
load_catalog
¶
Load a translation catalog from a file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to the PO or MO file. |
required |
locale
|
str | None
|
Optional locale override (defaults to filename). |
None
|
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
load_directory
¶
Load all translation catalogs from a directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directory
|
str | Path
|
Path to the directory containing translation files. |
required |
pattern
|
str
|
Glob pattern for translation files. |
'*.po'
|
recursive
|
bool
|
Whether to search recursively. |
False
|
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
ngettext
¶
Translate a message with plural forms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msgid
|
str
|
The singular form of the message. |
required |
msgid_plural
|
str
|
The plural form of the message. |
required |
n
|
int
|
The number determining which form to use. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The translated string. |
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
npgettext
¶
Translate a message with context and plural forms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
str
|
The context for disambiguation. |
required |
msgid
|
str
|
The singular form of the message. |
required |
msgid_plural
|
str
|
The plural form of the message. |
required |
n
|
int
|
The number determining which form to use. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The translated string. |
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
pgettext
¶
Translate a message with context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
str
|
The context for disambiguation. |
required |
msgid
|
str
|
The message to translate. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The translated string. |
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
set_current_locale
¶
Set the current locale in context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locale
|
str
|
The locale code to set. |
required |
translate
¶
translate(
msgid: str,
context: str | None = None,
n: int | None = None,
msgid_plural: str | None = None,
locale: str | None = None,
default: str | None = None,
) -> str
Translate a message.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
msgid
|
str
|
The message to translate. |
required |
context
|
str | None
|
Optional context for disambiguation. |
None
|
n
|
int | None
|
The number for plural selection. |
None
|
msgid_plural
|
str | None
|
The plural form of the message (for fallback). |
None
|
locale
|
str | None
|
Optional locale override (uses current_locale if not provided). |
None
|
default
|
str | None
|
Default value if translation not found. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The translated string, or the original msgid if not found. |
Source code in packages/maid-engine/src/maid_engine/i18n/translator.py
World
¶
Central game world state manager.
The World holds all game state including entities, rooms, and provides efficient queries for game logic.
Example
world = World(settings) await world.startup()
Create a player entity¶
player = world.create_entity() player.add(PositionComponent(room_id=starting_room.id)) player.add(HealthComponent(current=100, maximum=100))
Query entities in a room¶
for entity in world.entities_in_room(room_id): ...
Source code in packages/maid-engine/src/maid_engine/core/world.py
engine
property
¶
Get the game engine reference.
This is set by the GameEngine when it creates the World. Systems can use this to access engine-level resources like character managers, item managers, etc.
grid
property
¶
Get the grid manager for coordinate-based room operations.
The GridManager provides spatial indexing and queries for rooms placed on a 3D coordinate grid. It supports: - O(1) coordinate lookups - Radius and rectangular region queries - A* pathfinding between rooms - Automatic exit creation between adjacent rooms
Example
Register a room at a coordinate¶
world.grid.register_room(room_id, GridCoord(5, 10))
Or use the convenience method¶
world.register_room_at_coord(room_id, GridCoord(5, 10))
Find a path between rooms¶
result = world.grid.find_path(from_room_id, to_room_id) if result.found: print(result.directions) # ["n", "e", "e"]
all_areas
¶
all_rooms
¶
clear
¶
Clear all world state.
Source code in packages/maid-engine/src/maid_engine/core/world.py
count_in_room
¶
delete_data
¶
destroy_entity
¶
entities_in_room
¶
entities_in_room(room_id: UUID) -> Iterator[Entity]
Get all entities in a specific room.
Source code in packages/maid-engine/src/maid_engine/core/world.py
get_area
¶
get_data
¶
get_entity_room
¶
get_room
¶
increment_tick
¶
move_entity
¶
Move an entity to a new room.
Updates both the room index and any PositionComponent on the entity. Emits RoomLeaveEvent and RoomEnterEvent.
Returns:
| Type | Description |
|---|---|
bool
|
True if move was successful |
Source code in packages/maid-engine/src/maid_engine/core/world.py
place_entity_in_room
¶
Place an entity in a room (for initial placement).
Source code in packages/maid-engine/src/maid_engine/core/world.py
register_area
¶
register_room
¶
register_room_at_coord
¶
register_room_at_coord(
room_id: UUID,
coord: GridCoord,
movement_cost: float = 1.0,
terrain_type: str | None = None,
metadata: dict[str, Any] | None = None,
) -> GridRoom
Register a room at a specific grid coordinate.
This is a convenience method that delegates to grid.register_room(). If the GridManager has auto_create_exits enabled, this will automatically create bidirectional exits to adjacent registered rooms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
The UUID of the room entity. |
required |
coord
|
GridCoord
|
The grid coordinate for the room. |
required |
movement_cost
|
float
|
Cost to enter this room for pathfinding (default 1.0). Higher values make the room less desirable for pathfinding. |
1.0
|
terrain_type
|
str | None
|
Optional terrain type string (e.g., "forest", "water"). |
None
|
metadata
|
dict[str, Any] | None
|
Optional dictionary of additional room metadata. |
None
|
Returns:
| Type | Description |
|---|---|
GridRoom
|
The created GridRoom object. |
Raises:
| Type | Description |
|---|---|
CoordinateOccupiedError
|
If a room already exists at the coordinate. |
CoordinateBlockedError
|
If the coordinate is blocked. |
Example
from maid_engine.core.grid import GridCoord
Register the starting room¶
starting_room = world.create_entity() world.register_room(starting_room.id, {"name": "Town Square"}) world.register_room_at_coord( starting_room.id, GridCoord(0, 0), terrain_type="cobblestone", )
Register adjacent rooms - exits are created automatically¶
inn = world.create_entity() world.register_room(inn.id, {"name": "The Rusty Lantern Inn"}) world.register_room_at_coord(inn.id, GridCoord(0, 1))
Source code in packages/maid-engine/src/maid_engine/core/world.py
remove_entity_from_room
¶
Remove an entity from its current room without destroying it.
This is used when an item is picked up and moves to inventory.
Returns:
| Type | Description |
|---|---|
UUID | None
|
The room ID the entity was in, or None if not in a room |
Source code in packages/maid-engine/src/maid_engine/core/world.py
room_count
¶
set_data
¶
shutdown
async
¶
startup
async
¶
tick
async
¶
Process a single game tick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
delta
|
float
|
Time since last tick in seconds |
required |
Source code in packages/maid-engine/src/maid_engine/core/world.py
unregister_area
¶
unregister_room
¶
discover_content_packs
¶
discover_content_packs(
search_paths: list[Path] | None = None,
use_entry_points: bool = True,
) -> list[ContentPack]
Discover available content packs.
Content packs are discovered from: 1. Python entry points (maid.content_packs) - installed packages 2. Local directories containing manifest.toml files
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
search_paths
|
list[Path] | None
|
Additional directories to search for packs |
None
|
use_entry_points
|
bool
|
Whether to search entry points |
True
|
Returns:
| Type | Description |
|---|---|
list[ContentPack]
|
List of discovered ContentPack instances |
Source code in packages/maid-engine/src/maid_engine/plugins/loader.py
get_translator
¶
get_translator() -> Translator | None
Get the global translator instance.
Returns:
| Type | Description |
|---|---|
Translator | None
|
The global Translator for the current context, or None if not set. |
set_translator
¶
set_translator(translator: Translator | None) -> None
Set the global translator instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
translator
|
Translator | None
|
The Translator to use globally, or None to clear. |
required |