maid-classic-rpg¶
The maid-classic-rpg package provides a complete classic MUD gameplay experience, building on top of maid-engine and maid-stdlib.
Installation¶
Module Overview¶
Systems (maid_classic_rpg.systems)¶
Game systems implementing classic MUD mechanics:
| System Module | Description |
|---|---|
combat |
Turn-based tactical combat |
magic |
Spellcasting and magical effects |
crafting |
Item creation and recipes |
economy |
Shops, trading, banking |
quests |
Quest objectives and rewards |
quests.generation |
Automated quest generation integration |
social |
Guilds, factions, achievements |
pvp |
Arenas, duels, rankings |
world |
Time, weather, ecosystems |
npc |
NPC behavior and AI dialogue |
npc.autonomy |
NPC autonomy (needs, goals, schedules, social, barks) |
skills |
Character skills and progression |
Commands (maid_classic_rpg.commands)¶
Game-specific commands:
| Category | Commands |
|---|---|
| Combat | attack, defend, flee, cast, use |
| Economy | buy, sell, trade, bank, auction |
| Social | guild, faction, party, tell, shout |
| Dialogue | talk, ask, greet, conversations |
| Crafting | craft, gather, recipe |
| Quests | quest, objectives, abandon |
| PvP | duel, arena, rankings |
| Debug | debug_brain — inspect NPC autonomy state (admin only, no @ prefix) |
Models (maid_classic_rpg.models)¶
Data models for game entities:
| Module | Description |
|---|---|
combat |
Combat-related data structures |
magic |
Spell definitions and effects |
economy |
Shop, trade, and currency models |
crafting |
Recipes and materials |
social |
Guild and faction structures |
npc |
NPC configuration and dialogue |
skills |
Skill definitions and trees |
world |
Time, weather, terrain |
Events (maid_classic_rpg.events)¶
Game-specific events:
| Module | Description |
|---|---|
combat |
Combat-related events |
economy |
Economy/trade events |
quests |
Quest progression events |
autonomy |
NPC autonomy events (need changes, goal updates, schedule transitions, social interactions) |
Components (maid_classic_rpg.components)¶
Game-specific ECS components:
| Component | Description |
|---|---|
CharacterStatsComponent |
D&D-style ability scores (STR, DEX, etc.) |
CharacterInfoComponent |
Character class, race, and background |
SkillsComponent |
Character skills and levels |
AbilitiesComponent |
Known abilities |
WeaponComponent / ArmorComponent |
Equipped weapon and armor properties |
Systems¶
Combat System¶
Turn-based tactical combat with positioning and abilities.
from maid_classic_rpg.systems.combat import MeleeCombatSystem
# Combat system handles:
# - Initiative and turn order
# - Attack resolution
# - Damage calculation
# - Status effects
# - Death and respawn
combat
¶
Combat systems for melee and ranged combat.
BaseCombatSystem
¶
Bases: System, ABC
Abstract base class for combat systems.
Provides structure for combat flow: engagement, turn processing, damage calculation, and disengagement.
start_combat
abstractmethod
async
¶
Initiate combat between two entities.
end_combat
abstractmethod
async
¶
End combat for an entity.
process_attack
abstractmethod
async
¶
process_attack(
attacker: Entity,
defender: Entity,
weapon_id: UUID | None = None,
) -> tuple[bool, int]
Process an attack action.
calculate_damage
abstractmethod
async
¶
Calculate final damage after modifiers.
BodyDamageResult
¶
BodyDamageResult(
actual_damage: int = 0,
part_destroyed: bool = False,
effects: list[StatusEffectType] | None = None,
vital_hit: bool = False,
)
Result of applying damage to a body part.
BodySystem
¶
BodySystem(world: World)
Bases: System
System for managing body parts and location-based damage.
Handles: - Applying damage to specific body parts - Tracking body part health - Determining effects when parts are damaged/destroyed - Body part regeneration
apply_damage_to_location
¶
apply_damage_to_location(
body: BodyComponent,
location: str,
damage: int,
armor_value: int = 0,
) -> BodyDamageResult
Apply damage to a specific body location.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent to damage |
required |
location
|
str
|
Name of the body part |
required |
damage
|
int
|
Amount of damage to apply |
required |
armor_value
|
int
|
Additional armor to apply (on top of part's armor) |
0
|
Returns:
| Type | Description |
|---|---|
BodyDamageResult
|
BodyDamageResult with damage details |
heal_location
¶
Heal a specific body location.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent to heal |
required |
location
|
str
|
Name of the body part |
required |
amount
|
int
|
Amount of healing |
required |
Returns:
| Type | Description |
|---|---|
int
|
Actual amount healed |
restore_part
¶
Restore a destroyed body part to minimal health.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
location
|
str
|
Name of the body part to restore |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if part was restored |
get_total_health
¶
Get total health across all body parts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
Tuple of (current_health, max_health) |
get_health_percentage
¶
Get overall health percentage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
Returns:
| Type | Description |
|---|---|
float
|
Health percentage (0-100) |
is_vital_destroyed
¶
Check if any vital body part is destroyed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if a vital part is destroyed (entity should be dead) |
get_status_summary
¶
Get a status summary of all body parts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Dict mapping part name to status string |
add_part_effect
¶
Add a status effect to a body part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
location
|
str
|
Name of the body part |
required |
effect
|
str
|
Effect to add |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if effect was added |
remove_part_effect
¶
Remove a status effect from a body part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
location
|
str
|
Name of the body part |
required |
effect
|
str
|
Effect to remove |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if effect was removed |
clear_part_effects
¶
Clear all status effects from a body part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body
|
BodyComponent
|
The BodyComponent |
required |
location
|
str
|
Name of the body part |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of effects cleared |
DamageSystem
¶
DamageSystem(world: World)
Bases: System
System for applying damage from combat to characters.
Handles: - Applying attack results to character vitals - Location-based damage to body parts - Status effect application - Death determination
update
async
¶
Update tick - check for deaths from damage-over-time effects.
DOT damage is applied by StatusEffectManager via apply_direct_damage(). This method checks for entities that died from DOT since last tick.
remove_body
¶
Remove a character's body component from the cache.
Call when an entity is destroyed to prevent unbounded cache growth.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
The character UUID to remove. |
required |
get_or_create_body
¶
Get or create a body component for a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
The character |
required |
Returns:
| Type | Description |
|---|---|
BodyComponent
|
BodyComponent for the character |
apply_attack_result
async
¶
Apply an attack result to a target character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
AttackResult
|
The attack result to apply |
required |
target
|
Character
|
The target character |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if target was killed |
apply_direct_damage
¶
apply_direct_damage(
target: Character,
damage: int,
_damage_type: DamageType = TRUE,
location: str | None = None,
source_id: UUID | None = None,
) -> int
Apply direct damage to a target (no attack roll).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
The target character |
required |
damage
|
int
|
Amount of damage |
required |
_damage_type
|
DamageType
|
Type of damage (for future resistance calculations) |
TRUE
|
location
|
str | None
|
Optional body location |
None
|
source_id
|
UUID | None
|
Optional source entity ID for event emission |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Actual damage dealt |
heal_character
¶
Heal a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
The character to heal |
required |
amount
|
int
|
Amount to heal |
required |
location
|
str | None
|
Optional specific body part to heal |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Actual amount healed |
is_alive
¶
Check if a character is alive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
The character to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if character is alive |
get_health_status
¶
Get a description of character's health status.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
The character |
required |
Returns:
| Type | Description |
|---|---|
str
|
Health status string |
get_body_status
¶
Get detailed body part status for a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
The character |
required |
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Dict mapping body part to status |
StatusEffectManager
¶
StatusEffectManager(world: World)
Bases: System
System for managing status effects on entities.
Handles: - Adding/removing status effects - Effect duration tracking - Effect tick processing (damage over time, etc.) - Effect stacking rules
add_effect
¶
add_effect(
target: Character,
effect_type: StatusEffectType,
source_id: UUID | None = None,
duration: float | None = None,
intensity: float = 1.0,
stacks: int = 1,
) -> StatusEffect
Add a status effect to a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
Character to affect |
required |
effect_type
|
StatusEffectType
|
Type of effect |
required |
source_id
|
UUID | None
|
Entity that caused the effect |
None
|
duration
|
float | None
|
Override default duration |
None
|
intensity
|
float
|
Effect intensity multiplier |
1.0
|
stacks
|
int
|
Number of stacks to apply |
1
|
Returns:
| Type | Description |
|---|---|
StatusEffect
|
The created or updated StatusEffect |
remove_effect
¶
Remove a status effect from a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
Character to affect |
required |
effect_type
|
StatusEffectType
|
Type of effect to remove |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if effect was found and removed |
remove_all_effects
¶
Remove all effects from a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
Character to clear |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of effects removed |
get_effects
¶
Get all active effects on a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
Character to check |
required |
Returns:
| Type | Description |
|---|---|
list[StatusEffect]
|
List of active effects (copy) |
has_effect
¶
Check if character has a specific effect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
Character to check |
required |
effect_type
|
StatusEffectType
|
Effect type to look for |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if effect is active |
get_effect_stacks
¶
Get the number of stacks of an effect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
Character to check |
required |
effect_type
|
StatusEffectType
|
Effect type |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of stacks (0 if not present) |
get_effect_modifier
¶
Get the modifier value from an active effect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Character
|
Character to check |
required |
effect_type
|
StatusEffectType
|
Effect type |
required |
Returns:
| Type | Description |
|---|---|
float
|
Effect intensity * stacks (0.0 if not present) |
MeleeCombatSystem
¶
MeleeCombatSystem(world: World)
Bases: System
System for resolving melee combat attacks.
Handles attack resolution including: - Accuracy calculation with all modifiers - Hit location selection - Damage calculation with modifiers - Critical hits - Dodge/block/parry mechanics
update
async
¶
Update tick - melee combat is resolved immediately, not per-tick.
resolve_attack
async
¶
resolve_attack(
attacker: Character,
target: Character,
weapon: Item | None,
attacker_position: CombatPosition | None = None,
target_position: CombatPosition | None = None,
attacker_zone: CombatZone = MELEE,
target_zone: CombatZone = MELEE,
attacker_size: CreatureSize = MEDIUM,
target_size: CreatureSize = MEDIUM,
weapon_size: CreatureSize | None = None,
_other_attackers: list[CombatPosition] | None = None,
aimed_location: str | None = None,
attacker_grid_state: CombatantGridState | None = None,
target_grid_state: CombatantGridState | None = None,
) -> AttackResult
Resolve a melee attack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attacker
|
Character
|
Character making the attack |
required |
target
|
Character
|
Character being attacked |
required |
weapon
|
Item | None
|
Weapon being used (None for unarmed) |
required |
attacker_position
|
CombatPosition | None
|
Tactical position of attacker (legacy 3x3 grid) |
None
|
target_position
|
CombatPosition | None
|
Tactical position of target (legacy 3x3 grid) |
None
|
attacker_zone
|
CombatZone
|
Combat zone of attacker |
MELEE
|
target_zone
|
CombatZone
|
Combat zone of target |
MELEE
|
attacker_size
|
CreatureSize
|
Size of the attacker creature |
MEDIUM
|
target_size
|
CreatureSize
|
Size of the target creature |
MEDIUM
|
weapon_size
|
CreatureSize | None
|
Absolute size of the weapon (if different from wielder) |
None
|
_other_attackers
|
list[CombatPosition] | None
|
Positions of other attackers (for flanking, legacy) |
None
|
aimed_location
|
str | None
|
Specific body part to target (optional) |
None
|
attacker_grid_state
|
CombatantGridState | None
|
New variable-grid position/facing state |
None
|
target_grid_state
|
CombatantGridState | None
|
New variable-grid position/facing state for target |
None
|
Returns:
| Type | Description |
|---|---|
AttackResult
|
AttackResult with full attack outcome |
RangedCombatSystem
¶
RangedCombatSystem(world: World)
Bases: System
System for resolving ranged combat attacks.
Handles attacks across room boundaries including: - Line of sight checks - Range/distance modifiers - Ranged weapon mechanics - Cover system - Ammunition tracking - Reload mechanics - Moving target penalties
Note: Facing-based bonuses (backstab, flanking) do NOT apply to ranged attacks. Those bonuses only apply to melee combat.
shutdown
async
¶
Clean up reload timers and ammo tracking to prevent memory leak.
resolve_attack
async
¶
resolve_attack(
attacker: Character,
target: Character,
weapon: Item,
distance_rooms: int = 0,
attacker_zone: CombatZone = RANGED_NEAR,
target_zone: CombatZone = MELEE,
line_of_sight: LineOfSight | None = None,
target_in_cover: bool = False,
cover_level: float = 0.0,
target_is_moving: bool = False,
aimed_location: str | None = None,
) -> AttackResult
Resolve a ranged attack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attacker
|
Character
|
Character making the attack |
required |
target
|
Character
|
Character being attacked |
required |
weapon
|
Item
|
Ranged weapon being used |
required |
distance_rooms
|
int
|
Number of rooms between attacker and target |
0
|
attacker_zone
|
CombatZone
|
Combat zone of attacker |
RANGED_NEAR
|
target_zone
|
CombatZone
|
Combat zone of target |
MELEE
|
line_of_sight
|
LineOfSight | None
|
Line of sight info between positions |
None
|
target_in_cover
|
bool
|
Whether target has cover |
False
|
cover_level
|
float
|
Cover percentage (0.0-1.0, 1.0 = full cover) |
0.0
|
target_is_moving
|
bool
|
Whether target moved this tick |
False
|
aimed_location
|
str | None
|
Specific body part to target |
None
|
Returns:
| Type | Description |
|---|---|
AttackResult
|
AttackResult with full attack outcome |
get_reload_remaining
¶
Get remaining reload time for an attacker.
force_reload
¶
Manually trigger a reload (for reload command).
Magic System¶
Spellcasting with mana costs, cooldowns, and magical effects.
from maid_classic_rpg.systems.magic import SpellSystem
# Magic system handles:
# - Spell learning and memorization
# - Mana management
# - Spell effects and duration
# - Magical item enchantments
magic
¶
Magic systems for spellcasting and effects.
ActiveBuff
dataclass
¶
ActiveBuff(
id: UUID,
name: str,
source_id: UUID | None,
target_id: UUID,
expires_at: float,
effect_type: str,
stat_modifiers: dict[str, int] = dict(),
damage_reduction: float = 0.0,
damage_increase: float = 0.0,
status_immunity: list[StatusEffectType] = list(),
tick_effect: str | None = None,
tick_interval: float = 1.0,
last_tick: float = 0.0,
tick_damage: int = 0,
tick_heal: int = 0,
tick_damage_type: DamageType | None = None,
stacks: int = 1,
max_stacks: int = 1,
is_buff: bool = True,
can_dispel: bool = True,
icon: str = "",
)
A temporary buff/debuff on a character.
BuffAppliedEvent
dataclass
¶
BuffDispelledEvent
dataclass
¶
BuffExpiredEvent
dataclass
¶
SpellEffectSystem
¶
SpellEffectSystem(world: World)
Bases: System
Manages active spell effects, buffs, and debuffs.
register_handler
¶
Register a custom effect handler.
apply_effect
async
¶
apply_effect(
caster: Character,
target: Character,
effect_type: str,
params: dict[str, Any],
) -> dict[str, Any]
Apply a spell effect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
caster
|
Character
|
Character casting the spell |
required |
target
|
Character
|
Target of the effect |
required |
effect_type
|
str
|
Type of effect to apply |
required |
params
|
dict[str, Any]
|
Effect parameters |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Result dictionary with effect outcome |
add_buff
¶
add_buff(target_id: UUID, buff: ActiveBuff) -> bool
Add a buff to a character.
Returns True if buff was added, False if stacking failed.
remove_buff
¶
Remove a buff by name. Returns True if removed.
get_buff
¶
get_buff(
target_id: UUID, buff_name: str
) -> ActiveBuff | None
Get a specific buff by name.
get_stat_modifier
¶
Get total stat modifier from all buffs.
get_damage_reduction
¶
Get total damage reduction from all buffs (0.0-1.0).
get_damage_increase
¶
Get total damage increase from all buffs (capped at 5.0 / 500%).
has_status_immunity
¶
Check if target is immune to a status effect.
dispel
async
¶
dispel(
target_id: UUID,
dispeller_id: UUID | None = None,
count: int = 1,
buffs_only: bool = False,
debuffs_only: bool = False,
) -> int
Dispel buffs/debuffs from a target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_id
|
UUID
|
Character to dispel |
required |
dispeller_id
|
UUID | None
|
Who is dispelling |
None
|
count
|
int
|
Max effects to remove |
1
|
buffs_only
|
bool
|
Only remove positive effects |
False
|
debuffs_only
|
bool
|
Only remove negative effects |
False
|
Returns:
| Type | Description |
|---|---|
int
|
Number of effects dispelled |
clear_buffs
¶
Remove all buffs from a target. Returns count removed.
SpellCastCompleteEvent
dataclass
¶
SpellCastInterruptedEvent
dataclass
¶
SpellCastStartEvent
dataclass
¶
SpellLearnedEvent
dataclass
¶
CastingState
dataclass
¶
CastingState(
caster_id: UUID,
spell_name: str,
target_id: UUID | None,
started_at: float,
completes_at: float,
room_id: UUID | None,
mana_cost: int = 0,
cooldown: float = 0.0,
)
Tracks an in-progress spell cast.
SpellCastResult
dataclass
¶
SpellCastResult(
success: bool = False,
message: str = "",
damage_dealt: int = 0,
healing_done: int = 0,
effects_applied: list[StatusEffectType] = list(),
targets_hit: list[UUID] = list(),
mana_spent: int = 0,
)
Result of attempting to cast a spell.
SpellSystem
¶
SpellSystem(world: World)
Bases: System, StorageAware
Handles spell casting, effects, and cooldowns.
update
async
¶
Process casting completions and clean up expired cooldowns.
start_cast
async
¶
start_cast(
caster: Character,
spell_name: str,
target: Character | None = None,
) -> tuple[bool, str]
Begin casting a spell.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
caster
|
Character
|
Character casting the spell |
required |
spell_name
|
str
|
Internal name of the spell |
required |
target
|
Character | None
|
Optional target character |
None
|
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
interrupt_cast
async
¶
Interrupt an in-progress cast.
Refunds mana spent when cast was initiated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
caster_id
|
UUID
|
ID of caster to interrupt |
required |
reason
|
str
|
Reason for interruption |
'interrupted'
|
Returns:
| Type | Description |
|---|---|
bool
|
True if a cast was interrupted |
get_casting_state
¶
get_casting_state(caster_id: UUID) -> CastingState | None
Get the current casting state for a character.
learn_spell
¶
Teach a spell to a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character to teach |
required |
spell_name
|
str
|
Spell internal name |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if spell was learned (not already known) |
forget_spell
¶
Remove a spell from a character's known spells.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character to forget spell |
required |
spell_name
|
str
|
Spell internal name |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if spell was removed |
get_known_spells
¶
Get all spells known by a character.
get_known_spell
¶
Get a specific learned spell.
get_cooldown_remaining
¶
Get remaining cooldown time in game seconds.
register_magic_commands
¶
register_magic_commands(
spell_system: SpellSystem, skill_system: SkillSystem
) -> None
Register all magic and ability commands.
Crafting System¶
Item creation with recipes, materials, and skill requirements.
from maid_classic_rpg.systems.crafting import CraftingSystem
# Crafting system handles:
# - Recipe discovery and learning
# - Material gathering
# - Crafting skill progression
# - Quality and variation
crafting
¶
Crafting system components.
CraftingResult
dataclass
¶
CraftingResult(
success: bool,
error: str = "",
item: Item | None = None,
quality: MaterialQuality = COMMON,
skill_gained: float = 0.0,
materials_lost: list[UUID] = list(),
)
Result of a crafting attempt.
CraftingSystem
¶
CraftingSystem(world: World)
Bases: System
Manages all crafting operations.
set_item_manager
¶
Set the item manager for creating crafted items.
This allows deferred wiring when the ItemManager is created after the CraftingSystem (e.g., during content pack loading).
attempt_craft
async
¶
attempt_craft(
character: Character,
recipe: Recipe,
materials: list[MaterialItem],
station: CraftingStation | None = None,
item_manager: ItemManager | None = None,
) -> CraftingResult
Attempt to craft an item from a recipe.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character doing the crafting |
required |
recipe
|
Recipe
|
Recipe to craft |
required |
materials
|
list[MaterialItem]
|
Materials to use |
required |
station
|
CraftingStation | None
|
Crafting station (if required) |
None
|
item_manager
|
ItemManager | None
|
Optional explicit item manager for creating output. If not provided, uses the system's configured ItemManager or falls back to world.items. |
None
|
Returns:
| Type | Description |
|---|---|
CraftingResult
|
CraftingResult with success/failure and created item |
learn_recipe
¶
Teach a recipe to a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character to teach |
required |
recipe
|
Recipe
|
Recipe to learn |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if successfully learned |
character_knows_recipe
¶
Check if character knows a recipe.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character to check |
required |
recipe
|
Recipe
|
Recipe to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if character knows the recipe |
find_materials_for_recipe
¶
find_materials_for_recipe(
recipe: Recipe, inventory: list[MaterialItem]
) -> tuple[list[MaterialItem], list[str]]
Find matching materials for a recipe from an inventory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recipe
|
Recipe
|
Recipe to match |
required |
inventory
|
list[MaterialItem]
|
Available materials |
required |
Returns:
| Type | Description |
|---|---|
tuple[list[MaterialItem], list[str]]
|
Tuple of (matched materials, missing material types) |
EnchantingSystem
¶
Handles item enchantment.
enchant_item
async
¶
enchant_item(
character: Character,
item: Item,
enchantment_type: EnchantmentType,
reagent_consumed: bool = True,
station: CraftingStation | None = None,
) -> EnchantResult
Apply an enchantment to an item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character enchanting |
required |
item
|
Item
|
Item to enchant |
required |
enchantment_type
|
EnchantmentType
|
Type of enchantment |
required |
reagent_consumed
|
bool
|
Whether reagent cost was paid |
True
|
station
|
CraftingStation | None
|
Enchanting station if available |
None
|
Returns:
| Type | Description |
|---|---|
EnchantResult
|
EnchantResult with success/failure |
Enchantment
¶
Bases: MAIDBaseModel
An enchantment applied to an item.
EnchantmentType
¶
Bases: str, Enum
Types of enchantments.
EnchantResult
dataclass
¶
EnchantResult(
success: bool,
error: str = "",
enchantment: Enchantment | None = None,
item_damaged: bool = False,
)
Result of an enchanting attempt.
GemType
¶
Bases: str, Enum
Types of socketable gems.
RepairResult
dataclass
¶
RepairResult(
success: bool,
error: str = "",
durability_restored: int = 0,
new_durability: int = 0,
)
Result of a repair attempt.
RepairSystem
¶
Handles item repair and durability.
repair_item
async
¶
repair_item(
character: Character,
item: Item,
use_materials: bool = False,
station: CraftingStation | None = None,
) -> RepairResult
Repair a damaged item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character doing the repair |
required |
item
|
Item
|
Item to repair |
required |
use_materials
|
bool
|
Whether materials are being used for bonus |
False
|
station
|
CraftingStation | None
|
Crafting station if available |
None
|
Returns:
| Type | Description |
|---|---|
RepairResult
|
RepairResult with success/failure |
damage_item
¶
Apply durability damage to an item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
Item
|
Item to damage |
required |
amount
|
int
|
Durability points to remove |
1
|
Returns:
| Type | Description |
|---|---|
bool
|
True if item is now broken (0 durability) |
SocketedGem
¶
Bases: MAIDBaseModel
A gem socketed into an item.
SocketingSystem
¶
Handles gem socketing into items.
socket_gem
async
¶
socket_gem(
character: Character, item: Item, gem: Item
) -> SocketResult
Socket a gem into an item.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character doing the socketing |
required |
item
|
Item
|
Item to socket into |
required |
gem
|
Item
|
Gem item to socket |
required |
Returns:
| Type | Description |
|---|---|
SocketResult
|
SocketResult with success/failure |
remove_gem
async
¶
remove_gem(
character: Character, item: Item, socket_index: int
) -> SocketResult
Remove a gem from an item (destroys the gem).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character doing the removal |
required |
item
|
Item
|
Item to remove gem from |
required |
socket_index
|
int
|
Index of socket to empty |
required |
Returns:
| Type | Description |
|---|---|
SocketResult
|
SocketResult indicating success/failure |
SocketResult
dataclass
¶
SocketResult(
success: bool,
error: str = "",
gem: SocketedGem | None = None,
)
Result of a gem socketing attempt.
GatheringResult
dataclass
¶
GatheringResult(
success: bool,
error: str = "",
materials: list[MaterialItem] = list(),
skill_gained: float = 0.0,
)
Result of a gathering attempt.
GatheringSystem
¶
GatheringSystem(world: World)
Bases: System, StorageAware
Manages resource gathering in the world.
register_node
¶
Register a resource node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node
|
ResourceNode
|
Node to register |
required |
unregister_node
¶
Unregister a resource node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node_id
|
UUID
|
ID of node to remove |
required |
Returns:
| Type | Description |
|---|---|
ResourceNode | None
|
Removed node, or None if not found |
get_node
¶
Get a node by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node_id
|
UUID
|
Node ID |
required |
Returns:
| Type | Description |
|---|---|
ResourceNode | None
|
Node if found |
get_nodes_in_room
¶
Get all resource nodes in a room.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
Room ID |
required |
visible_only
|
bool
|
If True, exclude hidden nodes |
True
|
Returns:
| Type | Description |
|---|---|
list[ResourceNode]
|
List of nodes in the room |
attempt_gather
async
¶
attempt_gather(
character: Character, node: ResourceNode
) -> GatheringResult
Attempt to gather from a resource node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character gathering |
required |
node
|
ResourceNode
|
Node to gather from |
required |
Returns:
| Type | Description |
|---|---|
GatheringResult
|
GatheringResult with success/failure and materials |
attempt_skinning
async
¶
attempt_skinning(
character: Character, corpse: Item
) -> GatheringResult
Attempt to skin a corpse for leather/materials.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character skinning |
required |
corpse
|
Item
|
Corpse item to skin |
required |
Returns:
| Type | Description |
|---|---|
GatheringResult
|
GatheringResult with success/failure and materials |
all_nodes
¶
Get all registered nodes.
Returns:
| Type | Description |
|---|---|
list[ResourceNode]
|
List of all nodes |
MaterialQuality
¶
Bases: IntEnum
Material quality tiers with numeric values for calculations.
RecipeManager
¶
RecipeManager(
data_dir: Path | None = None,
store: DocumentStore | None = None,
)
Manages recipe loading, storage, and queries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_dir
|
Path | None
|
Directory containing recipe YAML files |
None
|
store
|
DocumentStore | None
|
DocumentStore instance for persistence |
None
|
load
async
¶
Load all recipes from storage and YAML files.
Returns:
| Type | Description |
|---|---|
int
|
Number of recipes loaded |
save_recipe
async
¶
Save a recipe to persistent storage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recipe
|
Recipe
|
Recipe to save |
required |
register
¶
Register a recipe.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recipe
|
Recipe
|
Recipe to register |
required |
unregister
¶
Unregister a recipe.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recipe_id
|
UUID
|
ID of recipe to remove |
required |
Returns:
| Type | Description |
|---|---|
Recipe | None
|
Removed recipe, or None if not found |
get
¶
Get a recipe by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recipe_id
|
UUID
|
Recipe ID |
required |
Returns:
| Type | Description |
|---|---|
Recipe | None
|
Recipe if found |
find_by_name
¶
Find a recipe by name (case-insensitive).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Recipe name to search for |
required |
Returns:
| Type | Description |
|---|---|
Recipe | None
|
Matching recipe, or None |
get_recipes_for_skill
¶
Get all recipes for a skill up to a level.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skill
|
str
|
Skill name |
required |
max_level
|
int
|
Maximum skill level filter |
100
|
Returns:
| Type | Description |
|---|---|
list[Recipe]
|
List of matching recipes |
get_learnable_recipes
¶
Get recipes a character can learn but doesn't know.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character to check |
required |
skill
|
str
|
Skill to check recipes for |
required |
Returns:
| Type | Description |
|---|---|
list[Recipe]
|
List of learnable recipes |
get_known_recipes
¶
Get all recipes known by a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character to check |
required |
Returns:
| Type | Description |
|---|---|
list[Recipe]
|
List of known recipes |
get_auto_learned_recipes
¶
Get recipes that are automatically learned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skill
|
str
|
Skill name |
required |
skill_level
|
int
|
Character's skill level |
required |
Returns:
| Type | Description |
|---|---|
list[Recipe]
|
List of auto-learned recipes |
get_recipe_by_output
¶
Get recipe that produces a specific item template.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_template_id
|
UUID
|
Item template ID |
required |
Returns:
| Type | Description |
|---|---|
Recipe | None
|
Recipe if found |
all_recipes
¶
Get all registered recipes.
Returns:
| Type | Description |
|---|---|
list[Recipe]
|
List of all recipes |
StationRegistry
¶
Manages crafting stations in the world.
register
¶
Register a crafting station.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station
|
CraftingStation
|
Station to register |
required |
unregister
¶
Unregister a crafting station.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station_id
|
UUID
|
ID of station to unregister |
required |
Returns:
| Type | Description |
|---|---|
CraftingStation | None
|
The removed station, or None if not found |
get
¶
Get a station by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station_id
|
UUID
|
Station ID |
required |
Returns:
| Type | Description |
|---|---|
CraftingStation | None
|
Station if found, None otherwise |
get_stations_in_room
¶
get_stations_in_room(
room_id: UUID, station_type: StationType | None = None
) -> list[CraftingStation]
Get crafting stations in a room.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
Room ID to search |
required |
station_type
|
StationType | None
|
Optional filter by station type |
None
|
Returns:
| Type | Description |
|---|---|
list[CraftingStation]
|
List of matching stations |
get_stations_by_type
¶
Get all stations of a specific type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station_type
|
StationType
|
Type to search for |
required |
Returns:
| Type | Description |
|---|---|
list[CraftingStation]
|
List of matching stations |
find_nearest_station
¶
find_nearest_station(
room_id: UUID,
station_type: StationType,
world: World,
max_distance: int = 10,
) -> tuple[CraftingStation | None, int]
Find nearest station of type using BFS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
Starting room ID |
required |
station_type
|
StationType
|
Type of station to find |
required |
world
|
World
|
World instance for room graph traversal |
required |
max_distance
|
int
|
Maximum rooms to search |
10
|
Returns:
| Type | Description |
|---|---|
tuple[CraftingStation | None, int]
|
Tuple of (station or None, distance). Distance is -1 if not found. |
all_stations
¶
Get all registered stations.
Returns:
| Type | Description |
|---|---|
list[CraftingStation]
|
List of all stations |
apply_quality_to_item
¶
apply_quality_to_item(
item: Item, quality: MaterialQuality
) -> None
Apply quality modifiers to a crafted item's stats.
Modifies: - Weapon damage (dice bonus) - Armor value - Item value (gold) - Stores quality in metadata
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item
|
Item
|
The crafted item to modify |
required |
quality
|
MaterialQuality
|
Quality tier to apply |
required |
calculate_output_quality
¶
calculate_output_quality(
crafter_skill: int,
recipe_difficulty: int,
materials: list[MaterialItem],
quality_variance: float = 0.5,
skill_bonus_divisor: float = 20.0,
) -> MaterialQuality
Calculate the quality of a crafted item.
Formula: - Base quality from average material quality - Skill bonus: (skill - difficulty) / 20 quality levels - Random variance: ± 0.5 quality levels (configurable) - Clamped to valid quality range (1-5)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
crafter_skill
|
int
|
Crafter's skill level (1-100) |
required |
recipe_difficulty
|
int
|
Recipe difficulty (1-100) |
required |
materials
|
list[MaterialItem]
|
List of materials used |
required |
quality_variance
|
float
|
Random variance range (default 0.5) |
0.5
|
skill_bonus_divisor
|
float
|
Points above difficulty per quality level |
20.0
|
Returns:
| Type | Description |
|---|---|
MaterialQuality
|
Final quality tier for the crafted item |
Economy System¶
Shops, trading, banking, and auction house.
from maid_classic_rpg.systems.economy import ShopSystem
# Economy system handles:
# - NPC shops with inventory
# - Player-to-player trading
# - Banking and storage
# - Auction house
economy
¶
Economy systems for shops, trading, banking, and auctions.
AuctionHouse
¶
AuctionHouse(world: World)
Bases: System, StorageAware
Manages the auction house system.
Handles listing, searching, bidding, and purchasing.
set_storage
¶
set_storage(store: DocumentStore) -> None
Receive storage from the engine via StorageAware protocol.
update
async
¶
Process expired auctions and deliver pending gold periodically.
list_item
async
¶
list_item(
seller: Character,
item: Item,
starting_price: int,
buyout_price: int | None = None,
duration_hours: int = 24,
) -> AuctionResult
List an item for auction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seller
|
Character
|
Character listing the item |
required |
item
|
Item
|
Item to list |
required |
starting_price
|
int
|
Starting bid price |
required |
buyout_price
|
int | None
|
Optional instant purchase price |
None
|
duration_hours
|
int
|
Auction duration |
24
|
Returns:
| Type | Description |
|---|---|
AuctionResult
|
AuctionResult with success/failure and listing |
place_bid
async
¶
Place a bid on an auction, wrapped in critical_write("economy.auction.bid").
buyout
async
¶
buyout(
buyer: Character,
listing_id: UUID,
item_manager: ItemManager | None = None,
) -> BuyoutResult
Instantly purchase at buyout price, wrapped in critical_write("economy.auction.buyout").
cancel_listing
async
¶
cancel_listing(
seller: Character,
listing_id: UUID,
item_manager: ItemManager | None = None,
) -> CancelResult
Cancel an auction listing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seller
|
Character
|
Character cancelling |
required |
listing_id
|
UUID
|
Listing to cancel |
required |
item_manager
|
ItemManager | None
|
Item manager for getting item |
None
|
Returns:
| Type | Description |
|---|---|
CancelResult
|
CancelResult with success/failure |
search
async
¶
search(
query: str | None = None,
item_type: str | None = None,
min_price: int | None = None,
max_price: int | None = None,
seller_name: str | None = None,
sort_by: str = "expires_at",
limit: int = 50,
offset: int = 0,
) -> list[AuctionListing]
Search active auction listings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str | None
|
Search term for item name |
None
|
item_type
|
str | None
|
Filter by item type |
None
|
min_price
|
int | None
|
Minimum current bid |
None
|
max_price
|
int | None
|
Maximum current bid |
None
|
seller_name
|
str | None
|
Filter by seller name |
None
|
sort_by
|
str
|
Sort field (expires_at, price_asc, price_desc, bid_count) |
'expires_at'
|
limit
|
int
|
Maximum results |
50
|
offset
|
int
|
Result offset for pagination |
0
|
Returns:
| Type | Description |
|---|---|
list[AuctionListing]
|
List of matching listings |
get_listing_by_short_id
¶
Get a listing by short ID prefix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
short_id
|
str
|
First 7 characters of listing ID |
required |
Returns:
| Type | Description |
|---|---|
AuctionListing | None
|
Matching listing, or None |
get_seller_listings
¶
Get all listings by a seller.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seller_id
|
UUID
|
Seller character ID |
required |
active_only
|
bool
|
If True, only return active listings |
False
|
Returns:
| Type | Description |
|---|---|
list[AuctionListing]
|
List of listings |
get_pending_gold
¶
Get pending gold for a character (from sales/refunds).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character ID |
required |
Returns:
| Type | Description |
|---|---|
int
|
Pending gold amount |
collect_pending_gold
async
¶
Collect the character's durable owed gold in a single durable commit.
Single-authority rule (issue #139): the durable owed-balance lives on
the character's PendingPayoutComponent (round-tripped through
Character.pending_payout_gold). The offline-safe _pending_gold
store is only an accrual projection; it is folded into the character
owed-balance here (and on login) before anything is credited, so the
two never diverge. After folding, this method credits the carried gold
and drains the owed-balance to zero, then makes BOTH durable in ONE
characters upsert via CharacterManager.update. The
owed-decrement IS the idempotency record: a re-run after a successful
commit sees owed already 0 and grants nothing, so a lost projection
write or a retried collect can never double-credit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character collecting (must have a live ECS entity for the component dual-write; offline callers still work via the DTO accessor fallback). |
required |
Returns:
| Type | Description |
|---|---|
int
|
Amount of gold credited (0 if nothing was owed). |
persist_pending_payouts
async
¶
Durably persist the pending-payouts singleton on demand.
Public entry point for the collect handler: after an item delivery is acknowledged (cleared from the in-flight buffer in memory) the cleared owed-state must be made durable BEFORE the operation is treated as complete, otherwise a crash before the lazy periodic save would reload a stale pending item and re-deliver it. The owned-set guard only backstops the residual window between the inventory flush and this call.
commit_character
async
¶
Durably commit the character (inventory + owed-balance + markers).
Public entry point for the collect handler's item delivery: the player
character entity is transient so critical_write's dirty-flush
SKIPS it; the only durable character primitive is
CharacterManager.update -> snapshot components into the DTO ->
upsert the characters collection. The handler stamps the inventory
add and its per-item auction_item:<id> delivered-marker in the live
components, then calls this to land BOTH in ONE durable DTO upsert.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the durable upsert fails (A-R3-1), so the caller can roll back the in-memory add/marker and leave the item owed. |
prune_stale_delivered_markers
async
¶
Durably prune bounded-retention auction_item delivered-markers.
A-R4-2: each collected item leaves a permanent auction_item:<id>
marker (A-R3-2) that suppresses re-delivery after disposal. Pruned here
once the marker is provably no longer needed -- the item is owed in
NEITHER store (so it can never be re-presented as pending) AND the
marker is older than :data:AUCTION_ITEM_MARKER_RETENTION (so we are
well outside any crash-recovery window in which a not-yet-synced store
might still resurrect it). This keeps the marker set bounded by the
items collected within the retention window instead of growing forever.
The prune is made durable in its own CharacterManager.update upsert
so a crash cannot reload the pruned markers and regrow the set. A commit
failure is swallowed (best-effort cleanup): the markers simply survive
to be retried on the next collect -- never a correctness problem, since
a stale marker only ever over-suppresses a re-delivery of an item that
is no longer owed anyway.
I-R7-1: the "owed in NEITHER store" test reads the IN-MEMORY owed-set,
which can diverge from the durable store. acknowledge_delivered
clears the in-flight buffer in memory BEFORE persist_pending_payouts
makes that clear durable; if the persist failed, the store still owes
the item while memory does not. Pruning the marker then would let a
restart (which reloads the still-owed item) re-deliver an item the
player already received and possibly disposed of. So the prune is
WITHHELD entirely unless the durable store is provably in sync with
memory (:meth:_is_store_synced); when it is not, the in-memory
owed-set cannot be trusted and the markers simply survive to a later
collect once the store has caught up.
get_pending_items
¶
Get pending items for a character (from wins).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character ID |
required |
Returns:
| Type | Description |
|---|---|
list[UUID]
|
List of pending item IDs |
collect_pending_items
¶
Claim pending items for a character for delivery.
Delivery is acknowledgement-based: the items returned here are moved
into an in-flight buffer rather than being discarded outright. They are
only considered delivered once the caller has successfully added them to
the recipient's authoritative inventory and signalled this by calling
:meth:acknowledge_delivered, or explicitly returns them via
:meth:requeue_pending_item. Anything left unacknowledged in the
in-flight buffer is treated as a crash mid-delivery and recovered to the
pending queue on the next collect, so a lookup exception or any other
crash after the claim but before the inventory add cannot silently lose
the items.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character ID |
required |
Returns:
| Type | Description |
|---|---|
list[UUID]
|
List of item IDs claimed for delivery |
delivery_lock
¶
Return the per-character lock guarding collect-and-deliver.
Callers hold this lock across the whole claim+deliver critical section so two concurrent collects for the same character are serialised: the second waits for the first to finish and then finds nothing pending and nothing in-flight, preventing double delivery and phantom pending items.
This delegates to the process-global
:func:get_character_commit_lock (issue #139, I-R6-1) so the auction's
collect-and-deliver section serialises not only against other auction
collects but against EVERY other commit section mutating the SAME live
character -- e.g. a quest turn-in or an achievement claim crediting gold
and flushing via CharacterManager.update. Those subsystems already
hold the same shared lock for their grant->commit->rollback window, so
sharing it here closes the cross-subsystem interleave that the auction's
previous instance-local lock did not cover. The lock is acquired exactly
ONCE per collect (at the top of the handler / the auto-deliver loop) and
the store-level _payout_store_lock is always taken strictly inside
it, so the per-character lock stays outermost and cannot deadlock.
acknowledge_delivered
¶
Acknowledge that a claimed item was successfully delivered.
This is the authoritative "this item landed in the recipient's inventory" signal. The caller MUST invoke it immediately after a successful inventory add (with no intervening await) so the delivered/undelivered decision is made at the exact delivery point rather than re-derived later from mutable inventory state. The item is dropped from the in-flight buffer; once gone it can never be re-owed even if the player later drops, sells, or consumes it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Owner the item was delivered to |
required |
item_id
|
UUID
|
Item that was successfully delivered |
required |
requeue_pending_item
¶
Return an undeliverable item to the pending queue.
Used when a claimed item cannot be added to the recipient's inventory (e.g. it is full) so the item is preserved rather than lost. The item is cleared from the in-flight buffer (it has been explicitly handled) and re-queued idempotently so it can never be both delivered and pending.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Owner the item should remain pending for |
required |
item_id
|
UUID
|
Item that could not be delivered |
required |
auto_deliver_pending_gold
async
¶
Deliver pending gold to all online players via the durable path.
Called periodically from update() and on player connection. Routes
every delivery through :meth:collect_pending_gold, which folds the
accrual projection into the durable owed-balance and commits the credit
in a single characters upsert (the single-authority rule, #139), so
auto-delivery can never diverge from an explicit auction collect.
Returns:
| Type | Description |
|---|---|
int
|
Total gold delivered across all players. |
BankSystem
¶
BankSystem(world: World)
Bases: System, StorageAware
System for bank operations.
Banking uses Character.bank_gold for storage. This system handles deposit/withdraw transactions. Bank NPC registrations are persisted via the DocumentStore.
get_transactions
¶
Get transaction history, optionally filtered by character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID | None
|
If provided, only return transactions for this character. |
None
|
Returns:
| Type | Description |
|---|---|
list[BankTransaction]
|
List of BankTransaction records. |
register_bank
¶
Register a bank NPC.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bank
|
BankNPC
|
The bank NPC to register. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the bank's room_id does not correspond to an existing entity in the world. |
check_balance
async
¶
Check bank balance.
Returns:
| Type | Description |
|---|---|
tuple[bool, int]
|
Tuple of (success, balance) |
deposit
async
¶
deposit(
character_id: UUID,
amount: int,
bank: BankNPC | None,
character_manager: CharacterManager,
) -> tuple[bool, str, int]
Deposit gold into bank, wrapped in critical_write("economy.bank.deposit").
withdraw
async
¶
withdraw(
character_id: UUID,
amount: int,
bank: BankNPC | None,
character_manager: CharacterManager,
) -> tuple[bool, str, int]
Withdraw gold from bank, wrapped in critical_write("economy.bank.withdraw").
transfer
async
¶
transfer(
from_character_id: UUID,
to_character_id: UUID,
amount: int,
character_manager: CharacterManager,
) -> tuple[bool, str]
Transfer gold between bank accounts, wrapped in critical_write("economy.bank.transfer").
ShopManager
¶
ShopManager(world: World | None = None)
Manages shop data and operations.
Handles shop registration, inventory, and pricing calculations.
register_shop
¶
Register a shop.
Validates room_id exists in world (if world is set) and warns on overwriting an existing shop in the same room.
register_merchant
¶
Register a merchant NPC linked to a shop.
get_merchant_for_shop
¶
Get the MerchantNPC associated with a shop.
unregister_shop
¶
Unregister a shop. Returns the shop if found.
get_shop_by_merchant
¶
Get shop by merchant entity ID.
ShopSystem
¶
ShopSystem(world: World)
Bases: System, StorageAware
System for processing shop transactions and restocking.
Handles: - Buy/sell transactions - Price calculations with modifiers - Inventory restocking over time - Shop gold management
list_inventory
async
¶
list_inventory(
shop: Shop,
item_manager: ItemManager,
charisma_mod: int = 0,
reputation: int = 0,
) -> list[tuple[str, int, int]]
Get shop inventory for display.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shop
|
Shop
|
Shop to list |
required |
item_manager
|
ItemManager
|
Item manager |
required |
charisma_mod
|
int
|
Player's charisma modifier for price calculation |
0
|
reputation
|
int
|
Player's reputation for price calculation |
0
|
Returns:
| Type | Description |
|---|---|
list[tuple[str, int, int]]
|
List of (item_name, price, quantity) |
buy_item
async
¶
buy_item(
shop: Shop,
buyer_id: UUID,
item_template_id: UUID,
character_manager: CharacterManager,
item_manager: ItemManager,
charisma_mod: int = 0,
reputation: int = 0,
) -> tuple[bool, str, Item | None]
Process a purchase, wrapped in critical_write("economy.shop.buy").
sell_item
async
¶
sell_item(
shop: Shop,
seller_id: UUID,
item_id: UUID,
character_manager: CharacterManager,
item_manager: ItemManager,
charisma_mod: int = 0,
reputation: int = 0,
) -> tuple[bool, str, int]
Process a sale, wrapped in critical_write("economy.shop.sell").
get_value
async
¶
get_value(
shop: Shop,
item: Item,
charisma_mod: int = 0,
reputation: int = 0,
) -> tuple[bool, int]
Get what a shop would pay for an item.
Returns:
| Type | Description |
|---|---|
tuple[bool, int]
|
Tuple of (would_buy, price) |
get_buy_price
async
¶
get_buy_price(
shop: Shop,
entry: ShopInventoryEntry,
charisma_mod: int = 0,
reputation: int = 0,
) -> int
Get the buy price for a shop item entry.
TradeSystem
¶
TradeSystem(world: World)
Bases: System
System for managing player-to-player trades.
Trade flow: 1. Player A initiates trade with Player B 2. Player B accepts (PENDING -> ACTIVE) 3. Both players add/remove items and gold 4. Both players lock their offers (ACTIVE -> LOCKED) 5. Both players confirm (LOCKED -> CONFIRMED -> COMPLETED)
Either player can cancel at any time before completion.
get_player_session
¶
Get the active trade session for a player.
initiate_trade
async
¶
Start a trade with another player.
Returns:
| Type | Description |
|---|---|
tuple[bool, str, TradeSession | None]
|
Tuple of (success, message, session_or_none) |
accept_trade
async
¶
Accept a pending trade invitation.
add_item
async
¶
add_item(
player_id: UUID,
item_id: UUID,
character_manager: CharacterManager,
) -> tuple[bool, str]
Add an item to trade offer.
remove_item
async
¶
Remove an item from trade offer.
set_gold
async
¶
Set gold amount in trade offer.
confirm_trade
async
¶
confirm_trade(
player_id: UUID,
character_manager: CharacterManager,
item_manager: ItemManager,
) -> tuple[bool, str]
Confirm and execute trade.
cancel_trade
async
¶
cancel_trade(
session_id: UUID,
cancelled_by: UUID | None = None,
reason: str = "cancelled",
) -> None
Cancel a trade session.
get_trade_status
¶
Get current trade status for a player.
Returns:
| Type | Description |
|---|---|
dict[str, object] | None
|
Dict with trade details or None if not in trade. |
Quest System¶
Quest tracking with objectives, rewards, and progression.
from maid_classic_rpg.systems.quests.generation.system import QuestGenerationSystem
# Quest system handles:
# - Quest discovery and acceptance
# - Objective tracking
# - Reward distribution
# - Quest chains and prerequisites
quests
¶
Quest system for MAID.
Provides quest definitions, tracking, and rewards.
QuestManager
¶
QuestManager(
quest_data_dir: Path | None = None,
quest_log_dir: Path | None = None,
event_bus: EventBus | None = None,
)
Manages quest definitions and character quest logs.
Responsibilities: - Load quest definitions from data files - Store and retrieve quest logs per character - Check quest prerequisites - Manage quest state transitions
Example
manager = QuestManager() await manager.load()
Get available quests for a character¶
available = await manager.get_available_quests(character)
Accept a quest¶
await manager.accept_quest(character, "starter_quest_1")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quest_data_dir
|
Path | None
|
Directory containing quest definition files |
None
|
quest_log_dir
|
Path | None
|
Directory for storing character quest logs (fallback) |
None
|
get_quest_log
¶
Get or create a quest log for a character.
get_all_quest_logs
¶
Get all character quest logs.
Returns:
| Type | Description |
|---|---|
list[tuple[UUID, QuestLog]]
|
List of (character_id, quest_log) tuples. |
save_quest_log
async
¶
Save a character's quest log to storage.
Public wrapper for _save_quest_log.
check_prerequisites
¶
Check if a character meets quest prerequisites.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quest
|
Quest
|
Quest to check |
required |
character
|
Character
|
Character to check |
required |
quest_log
|
QuestLog
|
Character's quest log |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (meets_prereqs, reason_if_not) |
get_available_quests
async
¶
Get quests available to a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character to check |
required |
npc_id
|
UUID | None
|
Optional NPC to filter by (only quests this NPC gives) |
None
|
Returns:
| Type | Description |
|---|---|
list[Quest]
|
List of available quests |
accept_quest
async
¶
Accept a quest for a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character accepting the quest |
required |
quest_id
|
str
|
Quest to accept |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
abandon_quest
async
¶
Abandon an active quest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character abandoning the quest |
required |
quest_id
|
str
|
Quest to abandon |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
expire_quest
async
¶
Expire an active quest for a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character with the active quest. |
required |
quest_id
|
str
|
Quest identifier to expire. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if quest was expired. |
register_generated_quest
¶
Register a generated quest at runtime.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quest
|
Quest
|
Generated quest model. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If quest_id already exists. |
invalidate_quest
¶
Invalidate a generated quest and remove pending offers.
get_generated_quests
¶
Get all currently registered generated quests.
get_npc_quests
async
¶
Get quests related to an NPC for a character.
Returns dict with keys: - available: Quests NPC can offer - in_progress: Quests in progress related to NPC - ready_to_turn_in: Completed quests to turn in to NPC
get_quests_by_category
async
¶
Get active quests by category.
DeliverObjectiveHandler
¶
DeliverObjectiveHandler(quest_manager: QuestManager)
Handler for DELIVER objective type.
Deliver objectives require giving a specific item to a specific NPC. This is checked when interacting with the target NPC.
check_delivery
async
¶
check_delivery(
character_id: UUID,
npc_id: UUID,
item_id: UUID,
item_template_id: UUID | None,
) -> list[str]
Check if giving this item completes any deliver objectives.
Returns:
| Type | Description |
|---|---|
list[str]
|
List of quest IDs where delivery was successful |
EscortObjectiveHandler
¶
EscortObjectiveHandler(quest_manager: QuestManager)
Handler for ESCORT objective type.
Escort objectives require an NPC to reach a destination room while keeping them alive.
check_escort_arrival
async
¶
Check if NPC arriving at room completes any escort objectives.
Returns:
| Type | Description |
|---|---|
list[tuple[UUID, str]]
|
List of (character_id, quest_id) for completed escorts |
ObjectiveTracker
¶
ObjectiveTracker(world: World, quest_manager: QuestManager)
Bases: System, StorageAware
System for tracking quest objective progress.
Subscribes to game events and updates quest progress accordingly. Handles all objective types: kill, collect, deliver, visit, talk, etc.
Inherits from StorageAware to receive storage injection and pass it to QuestManager.
get_reward_distributor
¶
get_reward_distributor(
item_manager: Any = None,
) -> RewardDistributor
Get or create the reward distributor for quest turn-ins.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
item_manager
|
Any
|
Optional item manager for item rewards. |
None
|
Returns:
| Type | Description |
|---|---|
RewardDistributor
|
RewardDistributor instance. |
set_storage
¶
set_storage(store: DocumentStore) -> None
Receive storage from the engine and pass it to QuestManager.
RewardDistributor
¶
RewardDistributor(
world: World,
quest_manager: QuestManager,
item_manager: ItemManager | None = None,
)
Handles quest reward distribution.
Responsibilities: - Validate quest can be turned in - Grant XP, gold, items, reputation - Handle reward choices - Emit reward events - Update quest state to TURNED_IN
set_item_manager
¶
Set or update the item manager reference.
This allows deferred wiring when the ItemManager is created after the RewardDistributor (e.g., during content pack loading).
turn_in_quest
async
¶
turn_in_quest(
character: Character,
quest_id: str,
reward_choice_index: int | None = None,
) -> tuple[bool, str, dict[str, Any] | None]
Turn in a completed quest and grant rewards.
Wrapped in critical_write("quest.turn_in") so reward grants (xp/gold/items/reputation) and quest-state transitions are flushed together. On timeout/overload, returns a retry-oriented failure tuple and the caller should leave the quest in COMPLETE state for retry.
reconcile_quest_completions
async
¶
Repair the quest-log projection from authoritative completion markers.
Lazy on-access recovery for the cross-store durability invariant: the
durable completion markers are the authority and the quest-log
projection is reconciled to them. For every quest:<id>:<op> marker
whose completion the projection does not reflect (a crash committed the
marker + gold but lost the projection save), the projection is repaired
(marked TURNED_IN, completion count raised via max) and any reward
items the marker recorded are re-minted best-effort. Markers are
DEDUP-only; the completion count authority remains
quest_log.completion_count (raise-only).
Pruning is conservative: a marker is removed ONLY after the durable
projection is re-confirmed to reflect it AND it is older than
:data:_MARKER_RETENTION, so a fresh marker is never pruned out of its
recovery window.
Social System¶
Guilds, factions, achievements, and social features.
from maid_classic_rpg.systems.social import GuildSystem
# Social system handles:
# - Guild creation and management
# - Faction reputation
# - Achievement tracking
# - Friend lists and ignore
social
¶
Social systems for player communication and groups.
AchievementSystem
¶
AchievementSystem(world: World)
Bases: System, StorageAware
System for tracking achievements.
Listens to game events and updates achievement progress accordingly.
update
async
¶
No per-tick processing needed — achievements are event-driven via update_criterion().
register_achievement
¶
Register an achievement.
unregister_achievement
¶
Unregister an achievement.
get_achievement
¶
Get an achievement by ID.
get_achievement_by_name
¶
Get an achievement by name.
get_achievements_by_category
¶
Get all achievements in a category.
get_progress
¶
Get a character's progress on an achievement.
get_all_progress
¶
Get all achievement progress for a character.
get_earned_achievements
¶
Get all achievements a character has earned.
get_total_points
¶
Get total achievement points for a character.
has_achievement
¶
Check if a character has earned an achievement.
update_criterion
async
¶
update_criterion(
character_id: UUID,
criterion_type: str,
target_id: UUID | None = None,
target_type: str = "",
amount: int = 1,
) -> list[Achievement]
Update progress on all matching criteria.
Returns:
| Type | Description |
|---|---|
list[Achievement]
|
List of newly completed achievements |
grant_achievement
async
¶
Manually grant an achievement to a character.
Returns:
| Type | Description |
|---|---|
bool
|
True if achievement was newly granted |
claim_rewards
async
¶
Claim rewards for a completed achievement.
Returns:
| Type | Description |
|---|---|
list[AchievementReward]
|
List of rewards granted |
clear_character_progress
¶
Clear all achievement progress for a character (for cleanup).
FactionSystem
¶
FactionSystem(world: World)
Bases: System, StorageAware
System for tracking faction reputation.
Manages faction definitions and per-character reputation values.
update
async
¶
Slowly decay reputation toward neutral each tick.
Decay is ~1 point per 10 real-time minutes. We accumulate elapsed time and apply integer decrements when the accumulator exceeds the threshold.
get_reputation
¶
Get a character's reputation with a faction.
get_reputation_level
¶
Get a character's reputation level with a faction.
get_all_reputations
¶
Get all reputations for a character.
modify_reputation
async
¶
modify_reputation(
character_id: UUID,
faction_id: UUID,
amount: int,
propagate: bool = True,
) -> tuple[int, ReputationLevel | None]
Modify a character's reputation with a faction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character whose reputation to modify |
required |
faction_id
|
UUID
|
Faction to modify reputation with |
required |
amount
|
int
|
Amount to add (negative to subtract) |
required |
propagate
|
bool
|
If True, also modify related factions |
True
|
Returns:
| Type | Description |
|---|---|
tuple[int, ReputationLevel | None]
|
Tuple of (new_value, new_level if changed) |
set_reputation
¶
Set a character's reputation to a specific value.
Returns:
| Type | Description |
|---|---|
ReputationLevel
|
The new reputation level |
get_unlocked_rewards
¶
Get rewards a character has unlocked with a faction.
get_npc_reaction
¶
Get how an NPC should react based on reputation.
Returns:
| Type | Description |
|---|---|
str
|
Reaction type: "attack", "refuse", "neutral", "friendly", "eager" |
get_price_modifier
¶
Get shop price modifier based on reputation.
Returns:
| Type | Description |
|---|---|
float
|
Multiplier for prices (1.0 = normal, 0.8 = 20% discount) |
can_access_vendor
¶
can_access_vendor(
character_id: UUID,
faction_id: UUID,
required_level: ReputationLevel = NEUTRAL,
) -> bool
Check if a character can access a faction vendor.
clear_character_reputations
¶
Clear all reputations for a character (for cleanup).
GroupSystem
¶
GroupSystem(
world: World, sessions: SessionManager | None = None
)
Bases: System
Manages player groups/parties.
Features: - Group creation and management - Follow leader movement - XP sharing - Loot distribution modes - Group chat (gtell)
set_sessions
¶
Set the session manager after initialization.
create_group
¶
Create a new group with player as leader.
disband_group
¶
Disband a group. Only leader can disband.
invite_player
async
¶
invite_player(
inviter_id: UUID,
inviter_name: str,
invitee_id: UUID,
invitee_name: str,
) -> tuple[bool, str]
Invite a player to group.
accept_invite
async
¶
Accept a group invitation.
kick_member
async
¶
Kick a member from the group.
promote_member
¶
Promote a member to assistant.
demote_member
¶
Demote an assistant to member.
transfer_leadership
¶
Transfer group leadership to another member.
set_follow
¶
Set a player to follow another.
group_tell
async
¶
Send message to group.
set_loot_mode
¶
Set group loot mode. Leader only.
get_looter
¶
Get the next player who should loot (for round-robin).
set_xp_share
¶
Enable or disable XP sharing. Leader only.
calculate_xp_share
¶
Calculate XP distribution for group members.
get_pending_invite
¶
Get pending invite for a player (group_id, inviter_id).
GuildBankError
¶
Bases: GuildError
Error specific to guild bank operations.
GuildError
¶
Bases: Exception
Base exception for guild operations.
GuildFullError
¶
Bases: GuildError
Guild is at maximum capacity.
GuildNotFoundError
¶
Bases: GuildError
Guild does not exist.
GuildPermissionError
¶
Bases: GuildError
Character lacks permission for operation.
GuildSystem
¶
GuildSystem(world: World)
Bases: System, StorageAware
System for managing player guilds.
Handles guild creation, membership, ranks, and progression.
set_session_provider
¶
Set the function used to retrieve online sessions for chat delivery.
get_guild_by_name
¶
Get a guild by name (case-insensitive).
get_character_guild
¶
Get the guild a character belongs to.
create_guild
async
¶
Create a new guild.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Guild name (must be unique) |
required |
tag
|
str
|
Short guild tag (2-5 chars) |
required |
leader_id
|
UUID
|
Character ID of the founder |
required |
leader_name
|
str
|
Character name of the founder |
required |
Returns:
| Type | Description |
|---|---|
Guild
|
The created Guild |
Raises:
| Type | Description |
|---|---|
GuildError
|
If character already in guild or name taken |
disband_guild
async
¶
Disband a guild.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guild_id
|
UUID
|
Guild to disband |
required |
requester_id
|
UUID
|
Character requesting disbandment |
required |
Raises:
| Type | Description |
|---|---|
GuildNotFoundError
|
If guild doesn't exist |
GuildPermissionError
|
If requester lacks permission |
invite_member
async
¶
Invite a player to the guild.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guild_id
|
UUID
|
Guild doing the inviting |
required |
inviter_id
|
UUID
|
Character sending the invite |
required |
invitee_id
|
UUID
|
Character being invited |
required |
Raises:
| Type | Description |
|---|---|
GuildNotFoundError
|
If guild doesn't exist |
GuildPermissionError
|
If inviter lacks permission |
GuildError
|
If invitee already in a guild or guild full |
get_pending_invites
¶
Get all pending guild invites for a character.
accept_invite
async
¶
Accept a guild invitation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character accepting |
required |
character_name
|
str
|
Character's name |
required |
guild_id
|
UUID
|
Guild to join |
required |
Returns:
| Type | Description |
|---|---|
Guild
|
The joined Guild |
Raises:
| Type | Description |
|---|---|
GuildError
|
If no pending invite or already in guild |
decline_invite
async
¶
Decline a guild invitation.
leave_guild
async
¶
kick_member
async
¶
Kick a member from the guild.
Raises:
| Type | Description |
|---|---|
GuildPermissionError
|
If kicker lacks permission or outranked |
promote_member
async
¶
Promote a member to the next rank.
Returns:
| Type | Description |
|---|---|
str
|
New rank name |
demote_member
async
¶
Demote a member to the previous rank.
Returns:
| Type | Description |
|---|---|
str
|
New rank name |
transfer_leadership
async
¶
Transfer guild leadership to another member.
add_guild_experience
async
¶
Add experience to a guild.
Returns:
| Type | Description |
|---|---|
bool
|
True if guild leveled up |
get_bank_tabs
¶
Get accessible bank tabs for a character.
get_tab_contents
¶
get_tab_contents(
guild_id: UUID, character_id: UUID, tab_index: int
) -> tuple[GuildBankTab, list[UUID]]
Get contents of a specific bank tab.
Returns:
| Type | Description |
|---|---|
tuple[GuildBankTab, list[UUID]]
|
Tuple of (tab, item_ids) |
deposit_item
async
¶
deposit_item(
guild_id: UUID,
character_id: UUID,
character_name: str,
item_id: UUID,
item_name: str,
tab_index: int = 0,
character: Character | None = None,
item_weight: float = 0.0,
) -> None
Deposit an item into the guild bank.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guild_id
|
UUID
|
Guild to deposit into. |
required |
character_id
|
UUID
|
Character depositing. |
required |
character_name
|
str
|
Character's name. |
required |
item_id
|
UUID
|
Item to deposit. |
required |
item_name
|
str
|
Item's name. |
required |
tab_index
|
int
|
Bank tab index. |
0
|
character
|
Character | None
|
Character object for atomic inventory removal. |
None
|
item_weight
|
float
|
Weight of the item for proper weight tracking. |
0.0
|
Raises:
| Type | Description |
|---|---|
GuildBankError
|
If character is not provided. |
withdraw_item
async
¶
withdraw_item(
guild_id: UUID,
character_id: UUID,
character_name: str,
item_id: UUID,
item_name: str,
tab_index: int = 0,
character: Character | None = None,
item_weight: float = 0.0,
) -> None
Withdraw an item from the guild bank.
Raises:
| Type | Description |
|---|---|
GuildBankError
|
If character is not provided. |
deposit_gold
async
¶
deposit_gold(
guild_id: UUID,
character_id: UUID,
character_name: str,
amount: int,
character: Character | None = None,
) -> None
Deposit gold into the guild bank.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guild_id
|
UUID
|
Guild to deposit into. |
required |
character_id
|
UUID
|
Character depositing. |
required |
character_name
|
str
|
Character's name. |
required |
amount
|
int
|
Amount to deposit. |
required |
character
|
Character | None
|
Character object for atomic gold deduction. |
None
|
Raises:
| Type | Description |
|---|---|
GuildBankError
|
If character is not provided. |
withdraw_gold
async
¶
withdraw_gold(
guild_id: UUID,
character_id: UUID,
character_name: str,
amount: int,
character: Character | None = None,
) -> None
Withdraw gold from the guild bank.
Raises:
| Type | Description |
|---|---|
GuildBankError
|
If character is not provided. |
get_bank_logs
¶
Get recent bank transaction logs.
get_gold_balance
¶
Get the guild's gold balance.
send_guild_message
async
¶
send_guild_message(
guild_id: UUID,
sender_id: UUID,
sender_name: str,
message: str,
is_announcement: bool = False,
) -> None
Send a message to the guild chat.
set_motd
¶
Set the guild message of the day.
register_social_commands
¶
register_social_commands(
channels: ChannelSystem,
groups: GroupSystem,
friends: FriendsSystem,
mail: MailSystem,
) -> None
Register all social commands.
register_guild_commands
¶
register_guild_commands(guilds: GuildSystem) -> None
Register all guild-related player commands.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guilds
|
GuildSystem
|
The GuildSystem instance to delegate operations to. |
required |
PvP System¶
Player versus player combat with arenas and rankings.
from maid_classic_rpg.systems.pvp import PvPSystem
# PvP system handles:
# - Duel challenges
# - Arena matchmaking
# - Ranking and leaderboards
# - PvP zones and rules
pvp
¶
PvP systems for player-vs-player combat.
ArenaSystem
¶
ArenaSystem(world: World)
Bases: System
System for managing arena matches and queues.
Features: - Queue system with rating-based matchmaking - Multiple match types (1v1, team, FFA) - Dedicated arena rooms - Rating changes based on match outcome
Arena Lifecycle: 1. QUEUED - Players/teams wait for opponents 2. PREPARING - Match found, players teleport to arena 3. IN_PROGRESS - Match active 4. COMPLETED - Match ends, ratings updated
register_arena_room
¶
register_arena_room(
room_id: UUID, match_types: list[ArenaMatchType]
) -> None
Register a room as an arena for specific match types.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
Room to register |
required |
match_types
|
list[ArenaMatchType]
|
Types of matches this room supports |
required |
join_queue
async
¶
join_queue(
character_ids: list[UUID], match_type: ArenaMatchType
) -> tuple[bool, str]
Join the arena queue.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_ids
|
list[UUID]
|
Characters joining as a team/solo |
required |
match_type
|
ArenaMatchType
|
Type of match to queue for |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
leave_queue
async
¶
Leave the arena queue.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character leaving queue |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
forfeit_match
async
¶
Forfeit an active arena match.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character forfeiting |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
get_queue_position
¶
Get queue position for a character.
Returns:
| Type | Description |
|---|---|
tuple[int, int] | None
|
Tuple of (position, total_in_queue) or None if not queued |
get_active_match
¶
get_active_match(character_id: UUID) -> ArenaMatch | None
Get active match for a character.
get_queue_status
¶
Get current queue sizes for all match types.
DuelSystem
¶
DuelSystem(world: World)
Bases: System
System for managing duels between players.
Duels are consensual PvP fights with special rules: - Both players must agree to fight - Combat stops at a configurable HP threshold (default 1 HP) - No permanent death or item loss - Optional gold betting - Spectators can place bets
Duel Lifecycle: 1. PENDING - Challenger issues challenge, target has time to respond 2. ACCEPTED - Challenge accepted, countdown begins 3. IN_PROGRESS - Duel is active, combat proceeds 4. COMPLETED - Duel ends when HP threshold reached or forfeit
challenge
async
¶
challenge(
challenger_id: UUID,
target_id: UUID,
room_id: UUID,
bet_amount: int = 0,
stop_at_hp: int | None = None,
) -> tuple[bool, str, UUID | None]
Issue a duel challenge.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
challenger_id
|
UUID
|
Character issuing challenge |
required |
target_id
|
UUID
|
Character being challenged |
required |
room_id
|
UUID
|
Room where duel will take place |
required |
bet_amount
|
int
|
Gold to wager (0 for no bet) |
0
|
stop_at_hp
|
int | None
|
HP threshold to stop fight |
None
|
Returns:
| Type | Description |
|---|---|
tuple[bool, str, UUID | None]
|
Tuple of (success, message, duel_id) |
accept
async
¶
Accept a pending duel challenge.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character accepting (must be target) |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
decline
async
¶
Decline a pending duel challenge.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character declining (must be target) |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
forfeit
async
¶
Forfeit an active duel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character forfeiting |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
place_bet
async
¶
Place a bet on an active duel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
duel_id
|
UUID
|
Duel to bet on |
required |
bettor_id
|
UUID
|
Character placing bet |
required |
backed_id
|
UUID
|
Character being bet on |
required |
amount
|
int
|
Gold to wager |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
get_active_duel
¶
get_active_duel(character_id: UUID) -> DuelChallenge | None
Get active duel for a character.
get_pending_challenges
¶
get_pending_challenges(
character_id: UUID,
) -> list[DuelChallenge]
Get all pending challenges for a character (as target).
ArenaMatchEndEvent
dataclass
¶
ArenaMatchEndEvent(
match_id: UUID | None = None,
match_type: ArenaMatchType | None = None,
winning_team: str | None = None,
individual_winner: UUID | None = None,
rating_changes: dict[str, int] = dict(),
)
ArenaMatchFoundEvent
dataclass
¶
ArenaMatchFoundEvent(
match_id: UUID | None = None,
match_type: ArenaMatchType | None = None,
team_a: list[UUID] = list(),
team_b: list[UUID] = list(),
)
ArenaMatchStateChangedEvent
dataclass
¶
ArenaMatchStateChangedEvent(
match_id: UUID | None = None,
old_state: ArenaMatchState | None = None,
new_state: ArenaMatchState | None = None,
)
ArenaQueueJoinEvent
dataclass
¶
ArenaQueueJoinEvent(
character_ids: list[UUID] = list(),
match_type: ArenaMatchType | None = None,
)
ArenaQueueLeaveEvent
dataclass
¶
ArenaQueueLeaveEvent(
character_ids: list[UUID] = list(),
match_type: ArenaMatchType | None = None,
)
DuelBetPlacedEvent
dataclass
¶
DuelChallengeEvent
dataclass
¶
DuelEndEvent
dataclass
¶
DuelResponseEvent
dataclass
¶
DuelStartEvent
dataclass
¶
PvPDeathEvent
dataclass
¶
PvPFlagChangedEvent
dataclass
¶
PvPFlaggedEvent
dataclass
¶
PvPKillEvent
dataclass
¶
RankingChangedEvent
dataclass
¶
SeasonEndEvent
dataclass
¶
TitleEarnedEvent
dataclass
¶
ArenaMatch
¶
Bases: MAIDBaseModel
An arena match instance.
ArenaMatchState
¶
Bases: str, Enum
Arena match lifecycle states.
ArenaMatchType
¶
Bases: str, Enum
Types of arena matches.
ArenaQueueEntry
¶
Bases: MAIDBaseModel
An entry in the arena queue.
DuelBet
¶
Bases: MAIDBaseModel
A bet placed on a duel by a spectator.
DuelChallenge
¶
Bases: MAIDBaseModel
A duel challenge between two players.
DuelState
¶
Bases: str, Enum
Duel lifecycle states.
PvPCharacterState
¶
PvPFlag
¶
Bases: str, Enum
PvP flag states.
PvPLootMode
¶
Bases: str, Enum
Loot rules for PvP death.
PvPSeason
¶
Bases: MAIDBaseModel
A competitive PvP season.
PvPTitle
¶
Bases: BaseModel
A title earned through PvP achievements.
RankingEntry
¶
Bases: MAIDBaseModel
A single ranking entry on the leaderboard.
PvPSystem
¶
PvPSystem(world: World)
Bases: System
System for managing PvP state, rules, and combat modifications.
Responsibilities: - Track PvP flag state per character - Validate PvP combat is allowed - Apply PvP-specific combat modifiers - Handle PvP death consequences - Manage temporary flagging
The PvP system hooks into combat events to enforce rules and track outcomes for the ranking system.
get_state
¶
get_state(character_id: UUID) -> PvPCharacterState
Get or create PvP state for a character.
enable_pvp
async
¶
Enable PvP for a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character to enable PvP for |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if PvP was enabled, False if already enabled or blocked |
disable_pvp
async
¶
Disable PvP for a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character to disable PvP for |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if PvP was disabled, False if flagged or in combat |
can_attack
¶
Check if PvP attack is allowed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attacker_id
|
UUID
|
Character attempting attack |
required |
target_id
|
UUID
|
Target character |
required |
room_id
|
UUID
|
Room where combat would occur |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (allowed, reason_if_denied) |
get_damage_modifier
¶
Get damage modifier for PvP combat.
Returns a multiplier to apply to damage dealt. This allows balancing PvP separately from PvE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attacker_id
|
UUID
|
Character dealing damage |
required |
target_id
|
UUID
|
Character receiving damage |
required |
Returns:
| Type | Description |
|---|---|
float
|
Damage multiplier (e.g., 0.7 for 70% damage) |
is_pvp_combat
¶
Check if combat between two entities is PvP.
is_in_pvp_combat
¶
Check if character is currently in PvP combat.
record_kill
async
¶
Record a PvP kill and update statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
killer_id
|
UUID
|
Character who got the kill |
required |
victim_id
|
UUID
|
Character who died |
required |
room_id
|
UUID
|
Room where kill occurred |
required |
handle_pvp_death
async
¶
Handle PvP death consequences.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
victim_id
|
UUID
|
Character who died |
required |
killer_id
|
UUID | None
|
Character who killed them (if any) |
required |
room_id
|
UUID
|
Room where death occurred |
required |
Returns:
| Type | Description |
|---|---|
list[UUID]
|
List of item IDs that were dropped as loot |
get_protection_remaining
¶
Get remaining protection time in seconds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character to check |
required |
Returns:
| Type | Description |
|---|---|
float
|
Seconds remaining, or 0 if not protected |
get_flag_remaining
¶
Get remaining flag time in seconds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character to check |
required |
Returns:
| Type | Description |
|---|---|
float
|
Seconds remaining, or 0 if not flagged |
RankingSystem
¶
RankingSystem(world: World)
Bases: System, StorageAware
System for managing PvP rankings and leaderboards.
Features: - Arena rating leaderboards - Kill/death rankings - Seasonal resets - Title rewards
Rankings are updated in response to PvP events and periodically persisted to the database.
set_storage
¶
set_storage(store: DocumentStore) -> None
Receive storage from the engine via StorageAware protocol.
get_ranking
¶
get_ranking(character_id: UUID) -> RankingEntry | None
Get ranking entry for a character.
get_leaderboard
¶
get_leaderboard(
offset: int = 0,
limit: int = 10,
sort_by: str = "rating",
) -> list[RankingEntry]
Get leaderboard entries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
offset
|
int
|
Starting position |
0
|
limit
|
int
|
Maximum entries to return |
10
|
sort_by
|
str
|
Field to sort by ('rating', 'wins', 'kills') |
'rating'
|
Returns:
| Type | Description |
|---|---|
list[RankingEntry]
|
List of ranking entries |
get_earned_titles
¶
get_earned_titles(character_id: UUID) -> list[PvPTitle]
Get all titles earned by a character.
get_available_titles
¶
get_available_titles(character_id: UUID) -> list[PvPTitle]
Get titles a character qualifies for but hasn't earned.
claim_title
async
¶
Claim an earned title.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character claiming title |
required |
title_id
|
str
|
Title to claim |
required |
Returns:
| Type | Description |
|---|---|
tuple[bool, str]
|
Tuple of (success, message) |
start_season
async
¶
start_season(
name: str,
duration_days: int = 90,
reward_tiers: dict[str, Any] | None = None,
) -> PvPSeason
Start a new PvP season.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Season name |
required |
duration_days
|
int
|
Length of season |
90
|
reward_tiers
|
dict[str, Any] | None
|
Rewards by rank tier |
None
|
Returns:
| Type | Description |
|---|---|
PvPSeason
|
The new season |
World System¶
Time cycles, weather, and dynamic world events.
from maid_classic_rpg.systems.world import GameTimeSystem
# World system handles:
# - Day/night cycles
# - Weather patterns
# - Seasonal changes
# - World events
world
¶
World dynamics systems for MAID.
This package contains systems for managing dynamic world elements: - Time system: Game clock, day/night cycles, seasons - Weather system: Regional weather patterns with gameplay effects - World events: Random encounters, world bosses, invasions - Area resets: Periodic respawning of monsters and items - Ecosystem: Predator/prey relationships, population dynamics - Ambient messages: Biome flavor text delivery to players - Wilderness spawn: Bridge from biome definitions to real ECS entities
EcosystemSystem
¶
EcosystemSystem(
world: World, config: EcosystemConfig | None = None
)
Bases: System
System for simulating dynamic ecosystems.
Manages predator/prey relationships, resource consumption, reproduction, migration, and population dynamics.
register_species
¶
Register a species definition.
add_resource_node
¶
Add a resource node to the ecosystem.
Resolves the area that contains the resource's room so that resources and populations are indexed under the same key. Falls back to using the room_id directly when no area mapping is available.
remove_resource_node
¶
Remove a resource node from the ecosystem.
initialize_population
¶
initialize_population(
area_id: UUID, species_id: UUID, initial_count: int
) -> PopulationState | None
Initialize a population for a species in an area.
get_population_info
¶
Get population information for an area.
get_resource_info
¶
Get resource information for an area.
WorldEventSystem
¶
WorldEventSystem(world: World)
Bases: System
System for managing world events.
Handles event scheduling, triggering, progression, and rewards.
register_definition
¶
Register an event definition.
get_active_events
¶
Get all currently active events.
get_event
¶
Get a specific event instance.
get_definition
¶
Get an event definition by ID.
trigger_event_by_name
async
¶
Trigger an event by its name (admin command).
cancel_event
async
¶
Cancel an active event (admin command).
record_kill
¶
Record a kill for event progress tracking.
schedule_event
¶
Schedule an event to trigger at a specific game time.
get_event_info
¶
Get detailed information about an active event.
AreaResetSystem
¶
AreaResetSystem(world: World)
Bases: System
System for managing area resets.
Handles periodic respawning of monsters, items, and restoration of room states.
GameTimeSystem
¶
GameTimeSystem(
world: World, config: TimeConfig | None = None
)
Bases: System
System managing game time progression.
The time system advances game time based on real elapsed time, scaled by a configurable ratio. It emits events for significant time changes that other systems can react to.
Example
system = GameTimeSystem(world)
Get current time¶
current = system.current_time print(f"It is {current.format_time()}")
Check time of day¶
if current.is_night: print("Darkness surrounds you.")
update
async
¶
Advance game time based on elapsed real time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
delta
|
float
|
Real seconds since last tick |
required |
set_time
¶
Set the current game time directly.
Use for admin commands or loading saved state.
get_visibility_modifier
¶
Get visibility modifier based on time of day.
Returns:
| Type | Description |
|---|---|
float
|
Multiplier for visibility (1.0 = full, 0.0 = none) |
WeatherSystem
¶
WeatherSystem(world: World)
Bases: System
System for managing weather across regions.
The weather system tracks weather per region and handles: - Weather state progression - Weather change events - Periodic weather effects (damage, messages) - Weather effect queries for other systems
get_weather
¶
Get weather for a region (or global if not specified).
get_weather_effects
¶
Get current weather effects for a region.
get_weather_description
¶
Get a text description of current weather.
set_weather
¶
Manually set weather (admin command).
register_region
¶
Register a region with custom weather configuration.
WildernessSpawnAdapter
¶
WildernessSpawnAdapter(world: World)
Converts biome encounter/resource strings into real ECS entities.
Register this adapter's :meth:on_room_generated method as a callback
on the WildernessManager so that whenever a wilderness room is
created, monsters and resource nodes are spawned automatically.
Example::
adapter = WildernessSpawnAdapter(world)
wilderness_manager.register_room_callback(adapter.on_room_generated)
spawned_entity_count
property
¶
Total number of entities spawned across all rooms.
get_template
¶
Look up a monster template by encounter type string.
teardown
¶
Clean up all tracked spawned entities and internal state.
Iterates every coordinate that still has spawned entities and
destroys them via the existing _cleanup_coord helper, then
clears all internal tracking maps.
on_room_generated
¶
on_room_generated(
room_id: UUID,
coord: tuple[int, int],
biome_name: str,
biome: BiomeDefinition,
spawned_content: SpawnedContent,
) -> None
Callback for WildernessManager room generation.
Spawns monster entities for encounters and resource nodes for
resources listed in the SpawnedContent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
UUID of the generated room. |
required |
coord
|
tuple[int, int]
|
(x, y) coordinate of the room. |
required |
biome_name
|
str
|
Name of the biome. |
required |
biome
|
BiomeDefinition
|
The BiomeDefinition used. |
required |
spawned_content
|
SpawnedContent
|
Resources and encounters rolled by the manager. |
required |
on_room_cleaned_up
¶
Clean up spawned entities when a wilderness room is destroyed.
Destroys all ECS entities that were spawned for the given room and unregisters them from the BehaviorSystem.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
UUID of the room being cleaned up. |
required |
on_room_destroyed
¶
Cleanup callback matching WildernessManager's RoomCleanupCallback.
Called by WildernessManager before a room is destroyed during stale-room cleanup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
UUID of the room being destroyed. |
required |
coord
|
tuple[int, int]
|
(x, y) coordinate of the room. |
required |
NPC System¶
NPC behavior, schedules, and AI-powered dialogue.
from maid_classic_rpg.systems.npc import BehaviorSystem
from maid_classic_rpg.systems.npc.dialogue import NPCDialogueSystem
# NPC system handles:
# - NPC spawning and despawning
# - Behavior patterns
# - Schedules and routines
# - AI-powered conversations
npc
¶
NPC behavior, spawning, dialogue, and autonomy systems.
All public names are lazy-imported to avoid circular dependencies
between this package and maid_classic_rpg.events.
AutonomySystem
¶
AutonomySystem(world: World)
Bases: BaseAutonomySystem
Selects and executes NPC autonomous actions each tick.
Extends BaseAutonomySystem with classic-RPG goal generation,
utility scoring, LLM integration, and game-specific events.
BarkLibrary
¶
BarkSystem
¶
BarkSystem(
world: World,
library: BarkLibrary | None = None,
knowledge_manager: Any = None,
)
BehaviorSystem
¶
BehaviorSystem(world: World)
Bases: BaseBehaviorSystem
System for executing NPC behaviors.
Extends BaseBehaviorSystem with classic-rpg-specific aggro logic, CombatComponent handling, and NPCAggroEvent/DamageDealtEvent subscriptions.
Processes: - Aggression checks (aggressive NPCs attack on sight) - Patrol/wander movement - Flee behavior when low health - Territory defense - Pack/ally assistance
register_npc
¶
register_npc(
entity_id: UUID,
behavior: BehaviorConfig,
territory_center: UUID | None = None,
) -> NPCState
Register an NPC for behavior processing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity_id
|
UUID
|
NPC entity ID |
required |
behavior
|
BehaviorConfig
|
Behavior configuration |
required |
territory_center
|
UUID | None
|
Optional territory center room |
None
|
Returns:
| Type | Description |
|---|---|
NPCState
|
The created NPCState |
check_aggro
async
¶
check_aggro(
npc_id: UUID,
npc_room_id: UUID,
behavior: BehaviorType,
aggro_range: int = 1,
) -> list[UUID]
Check for entities that should trigger aggro.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npc_id
|
UUID
|
NPC checking for targets |
required |
npc_room_id
|
UUID
|
NPC's current room |
required |
behavior
|
BehaviorType
|
NPC's behavior type |
required |
aggro_range
|
int
|
Rooms to check (BFS hops from NPC room) |
1
|
Returns:
| Type | Description |
|---|---|
list[UUID]
|
List of entity IDs to aggro on |
call_for_help
async
¶
call_for_help(
npc_id: UUID,
npc_room_id: UUID,
target_id: UUID,
_call_radius: int = 1,
) -> list[UUID]
Call nearby allies for help.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npc_id
|
UUID
|
NPC calling for help |
required |
npc_room_id
|
UUID
|
NPC's room |
required |
target_id
|
UUID
|
Entity to aggro allies on |
required |
_call_radius
|
int
|
Rooms to check for allies |
1
|
Returns:
| Type | Description |
|---|---|
list[UUID]
|
List of ally IDs that responded |
CacheRefreshSystem
¶
CacheRefreshSystem(
world: World,
refresh_interval: float = DEFAULT_REFRESH_INTERVAL,
)
NPCDialogueSystem
¶
NPCDialogueSystem(world: World)
Bases: System, StorageAware
System for handling AI-powered NPC dialogue.
Manages conversations between players and NPCs, including: - AI provider integration for generating responses - Rate limiting to prevent abuse - Conversation history tracking - Context building from world state
Example
system = NPCDialogueSystem(world)
Process a player's message to an NPC¶
success = await system.process_dialogue( player_entity_id=player.id, npc_entity_id=npc.id, message="Hello, how are you?", session=player_session, )
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
world
|
World
|
The game world instance |
required |
set_storage
¶
set_storage(store: DocumentStore) -> None
Set the document store for conversation persistence.
Called automatically by the engine when the system is registered if the system implements StorageAware.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
DocumentStore
|
The document store instance |
required |
startup
async
¶
Initialize the dialogue system.
Sets up rate limiting and gets provider registry from engine.
shutdown
async
¶
Shut down the dialogue system.
Saves conversations to storage (if persistence enabled) and cleans up. Submits extraction jobs for any remaining conversations so that dialogue is converted into memories before data is discarded.
update
async
¶
Periodic update for cleanup of stale conversations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
delta
|
float
|
Time since last update in seconds |
required |
process_dialogue
async
¶
process_dialogue(
player_entity_id: UUID,
npc_entity_id: UUID,
message: str,
session: Session,
) -> bool
Process a dialogue request from player to NPC.
This is the main entry point for NPC dialogue. It handles: - Validating the NPC has a DialogueComponent - Checking rate limits and cooldowns - Building context from world state - Generating AI response - Sending the complete response to player (buffered for content filtering)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
player_entity_id
|
UUID
|
UUID of the player entity |
required |
npc_entity_id
|
UUID
|
UUID of the NPC entity |
required |
message
|
str
|
The player's message to the NPC |
required |
session
|
Session
|
Player's session for sending responses |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if dialogue was processed, False on error |
find_npc_in_room
¶
find_npc_in_room(
room_id: UUID, keyword: str
) -> Entity | None
Find an NPC in a room by keyword.
Searches for NPCs in the specified room that match the given keyword in their name or keywords list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
room_id
|
UUID
|
The room to search in |
required |
keyword
|
str
|
Keyword to match against NPC names/keywords |
required |
Returns:
| Type | Description |
|---|---|
Entity | None
|
The matching Entity or None if not found |
get_conversation
async
¶
Get an existing conversation between player and NPC.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
player_id
|
UUID
|
UUID of the player |
required |
npc_id
|
UUID
|
UUID of the NPC |
required |
Returns:
| Type | Description |
|---|---|
Conversation | None
|
The Conversation if it exists, None otherwise |
get_player_conversations
async
¶
Get all active conversations for a player.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
player_id
|
UUID
|
UUID of the player |
required |
Returns:
| Type | Description |
|---|---|
list[Conversation]
|
List of Conversation objects for this player |
get_entity_name
¶
Get the display name for an entity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity_id
|
UUID
|
UUID of the entity |
required |
Returns:
| Type | Description |
|---|---|
str
|
Entity's name or "Someone" if not found |
end_conversation
async
¶
End a conversation between player and NPC.
Before removing the conversation, pushes exchanges into the working buffer and submits an extraction job so the dialogue can be converted into episodic memories.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
player_id
|
UUID
|
UUID of the player |
required |
npc_id
|
UUID
|
UUID of the NPC |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if a conversation was ended, False if not found |
enqueue_background_dialogue
¶
enqueue_background_dialogue(
handler: Callable[[], Awaitable[str]],
*,
npc_id: UUID | None = None,
room_id: UUID | None = None,
player_witnessed: bool = False,
) -> UUID | None
Submit an NPC dialogue LLM request to the off-tick queue.
Use this for NPC-initiated dialogue that should not block the tick
loop. Results are dispatched as NPCBarkEvent by the autonomy
system and delivered to players in the NPC's room.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler
|
Callable[[], Awaitable[str]]
|
Async callable that performs the LLM request. |
required |
npc_id
|
UUID | None
|
Optional NPC entity UUID for result routing. |
None
|
room_id
|
UUID | None
|
Optional room UUID for result delivery. |
None
|
player_witnessed
|
bool
|
Bump priority when a player is present. |
False
|
Returns:
| Type | Description |
|---|---|
UUID | None
|
Request UUID if enqueued, None if queue unavailable or full. |
ActionExecutor
¶
Bases: BaseActionExecutor
Executes autonomy actions by mutating intent components.
Extends BaseActionExecutor with classic-rpg-specific action handling: USE_ITEM with ConsumableComponent, SOCIALIZE/GOSSIP with SocialIntent, CRAFT_ITEM, and classic-rpg event emission.
NPCMovementHandler
¶
FallbackResponseProvider
¶
Provides contextually appropriate canned responses when AI is unavailable.
This provider selects responses based on the NPC's personality type (derived from their role) and the interaction context. Responses are chosen randomly within the matching category to avoid repetition.
When a fallback is used, the provider logs the event with the reason for monitoring and debugging AI provider health.
Example
provider = FallbackResponseProvider()
Get a fallback response for a merchant greeting¶
response = provider.get_response( personality="merchant", context="greeting", )
Log the fallback usage¶
provider.log_fallback( npc_name="Grimjaw", reason=FallbackReason.TIMEOUT, personality="merchant", context="greeting", )
get_response
¶
Get a contextually appropriate fallback response.
Resolves the personality type from the NPC role string and the interaction context, then selects a random response from the matching category.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
personality
|
str
|
NPC role/personality string (e.g., "merchant", "guard"). Maps to a PersonalityType via resolve_personality(). |
''
|
context
|
str
|
Interaction context string (e.g., "greeting", "trade"). Maps to an InteractionContext via resolve_context(). |
''
|
Returns:
| Type | Description |
|---|---|
str
|
A fallback response string appropriate for the NPC and context. |
log_fallback
¶
log_fallback(
npc_name: str,
reason: FallbackReason,
personality: str = "",
context: str = "",
error_detail: str = "",
) -> None
Log that a fallback response was used.
This method logs at WARNING level to aid in monitoring AI provider health. The log includes the NPC name, the reason for fallback, and additional context about the failure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npc_name
|
str
|
Display name of the NPC. |
required |
reason
|
FallbackReason
|
Why the fallback was triggered (from FallbackReason). |
required |
personality
|
str
|
NPC personality/role string. |
''
|
context
|
str
|
Interaction context string. |
''
|
error_detail
|
str
|
Additional detail about the error (e.g., exception message). |
''
|
get_response_and_log
¶
get_response_and_log(
npc_name: str,
reason: FallbackReason,
personality: str = "",
context: str = "",
error_detail: str = "",
) -> str
Get a fallback response and log the event in one call.
Convenience method that combines get_response() and log_fallback().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npc_name
|
str
|
Display name of the NPC. |
required |
reason
|
FallbackReason
|
Why the fallback was triggered. |
required |
personality
|
str
|
NPC role/personality string. |
''
|
context
|
str
|
Interaction context string. |
''
|
error_detail
|
str
|
Additional error detail. |
''
|
Returns:
| Type | Description |
|---|---|
str
|
A fallback response string appropriate for the NPC and context. |
MemoryEventBridge
¶
MemoryEventBridge(world: World)
Bases: System
Bridges memory/relationship lifecycle events to NPC subsystems.
Responsibilities:
* Log events at debug level for admin observability.
* Invalidate cached adapters when new data arrives.
* Emit :class:StorySignalEvent for dramatic relationship changes.
SocialFabricSystem
¶
SocialFabricSystem(
world: World,
relationship_provider: RelationshipProvider
| None = None,
resolver: SocialInteractionResolver | None = None,
relationship_manager: RelationshipManager | None = None,
)
Bases: System
Processes social intents and relationship-derived interaction state.
set_relationship_provider
¶
Replace the relationship provider for social lookups.
set_gossip_processor
¶
Replace the gossip reaction processor in the resolver.
set_relationship_manager
¶
Inject a RelationshipManager for NPC→NPC relationship tracking.
get_rivals
¶
Return rival IDs where trust and respect are both low.
get_allies
¶
Return allies based on loyalty relation if available.
reserve_interaction
¶
Reserve interaction target for a duration.
SpawnerSystem
¶
Bases: System
System for spawning and respawning NPCs/monsters.
Handles: - Initial spawning at startup - Respawning after death (with timers) - Population limits per room and area - Spawn conditions (time, player presence)
register_spawn_point
¶
Register a spawn point.
unregister_spawn_point
¶
Unregister a spawn point.
register_template
¶
Register a monster template.
unregister_template
¶
Unregister a monster template.
get_spawn_point
¶
Get a spawn point by ID.
get_template
¶
Get a monster template by ID.
register_spawn_rule
¶
Register a spawn rule that governs spawning behavior.
unregister_spawn_rule
¶
Unregister a spawn rule.
register_spawn_group
¶
Register a coordinated spawn group.
unregister_spawn_group
¶
Unregister a spawn group.
on_entity_death
async
¶
Handle entity death for respawn tracking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity_id
|
UUID
|
Entity that died |
required |
despawn_entity
async
¶
Manually despawn an entity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity_id
|
UUID
|
Entity to despawn |
required |
reason
|
str
|
Reason for despawn |
'cleanup'
|
Returns:
| Type | Description |
|---|---|
bool
|
True if entity was despawned |
get_spawn_point_status
¶
Get status of a spawn point.
Returns:
| Type | Description |
|---|---|
dict[str, object] | None
|
Dict with spawn point status or None |
get_monsters_in_room
¶
Get all monsters in a specific room.
NPC Autonomy¶
NPC autonomy systems providing independent NPC behavior including needs, goals, schedules, social interactions, ambient barks, action scoring, signal processing, gossip propagation, and LLM-driven decision queuing.
Submodules: autonomy, needs, goals, schedule, social, barks, executor, scoring, signals, gossip, llm_queue.
autonomy
¶
Classic RPG autonomy system built on the stdlib base loop.
Quest Generation¶
Automated quest generation integration, connecting world state and NPC needs to the quest generation framework in maid-stdlib.
generation
¶
Automated quest generation package.
QuestHistory
¶
QuestHistory(document_store: DocumentStore | None)
In-memory history index with optional DocumentStore persistence.
mark_offered
¶
Track a pending quest offer for a character.
mark_accepted
¶
Mark quest as accepted by character.
set_outcome
¶
set_outcome(
quest_id: str,
outcome: QuestOutcome,
character_id: UUID | None = None,
) -> None
Set quest outcome and completion timestamp.
recent_quest_from_npc
¶
Return True when NPC gave a quest within cooldown window.
active_generated_quest_ids
¶
Get active generated quest identifiers.
get_chain
¶
Return history entries belonging to a quest chain.
count_active_in_region
¶
Count active generated quests in a region.
count_pending_offers
¶
Count pending generated quest offers for character.
entries_for_character
¶
Return history entries for a specific character.
recent_entries
¶
Return the count most recent history entries.
GeneratedQuest
dataclass
¶
GeneratedQuest(
id: str,
seed_id: UUID,
seed_type: QuestSeedType,
archetype_id: str,
importance: float,
title: str,
summary: str,
detailed_description: str,
objectives: list[QuestObjective],
quest_giver_id: UUID,
quest_giver_motivation: str,
quest_giver_dialogue: QuestDialogue,
involved_npcs: dict[UUID, str],
involved_locations: list[UUID],
rewards: QuestReward,
consequences: list[QuestConsequence],
failure_consequences: list[QuestConsequence],
difficulty: DifficultyTier,
time_limit: float | None,
expiry: datetime,
chain_potential: float,
chain_depth: int = 0,
grounding_score: float = 1.0,
coherence_score: float = 1.0,
novelty_score: float = 1.0,
delivery_method: QuestDeliveryMethod = DIRECT_OFFER,
)
Fully built generated quest payload before conversion to Quest model.
QuestOutcome
¶
Bases: str, Enum
Outcome grade emitted for quest completion/failure.
QuestSeed
dataclass
¶
QuestSeed(
source_signals: list[str],
seed_type: QuestSeedType,
importance: float,
urgency: float,
primary_npc: UUID | None,
primary_npc_motivation: str,
backstory: str,
stakes: str,
location: UUID | None,
threat_source: str,
evidence_location: UUID | None,
involved_npcs: list[UUID],
context_keys: dict[str, str],
created_at: datetime,
expires_at: datetime | None,
attempt_count: int = 0,
chain_depth: int = 0,
seed_id: UUID = uuid4(),
)
Input signal bundle used to generate a quest.
QuestSeedTypes
¶
Known quest seed type identifiers.
Skills System¶
Character skills, experience, and progression.
from maid_classic_rpg.systems.skills import SkillSystem
# Skills system handles:
# - Skill learning
# - Experience tracking
# - Level progression
# - Skill trees and prerequisites
skills
¶
Skill systems for training and skill checks.
CheckDifficulty
¶
Bases: Enum
Difficulty levels for skill checks.
SkillCheckResult
dataclass
¶
SkillCheckResult(
success: bool = False,
roll: int = 0,
target: int = 0,
margin: int = 0,
critical: bool = False,
skill_level: int = 0,
)
Result of a skill check.
SkillLearnedEvent
dataclass
¶
SkillLevelUpEvent
dataclass
¶
SkillSystem
¶
SkillSystem(world: World)
Bases: System, StorageAware
Manages skill training, checks, and progression.
update
async
¶
Process any time-based skill updates and clean up cooldowns.
learn_skill
¶
Teach a skill to a character.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character to teach |
required |
skill_name
|
str
|
Skill internal name |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if skill was learned (not already known) |
get_skill_level
¶
Get a character's level in a skill.
get_character_skill
¶
Get a character's skill data.
get_all_skills
¶
Get all skills for a character.
get_skills_by_category
¶
Get skills in a category for a character.
add_experience
¶
add_experience(
character_id: UUID,
skill_name: str,
amount: float,
respect_cooldown: bool = True,
) -> tuple[float, int]
Add experience to a skill.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character ID |
required |
skill_name
|
str
|
Skill internal name |
required |
amount
|
float
|
Experience to add |
required |
respect_cooldown
|
bool
|
If True, check cooldown (1 second between gains) |
True
|
Returns:
| Type | Description |
|---|---|
tuple[float, int]
|
Tuple of (actual exp added, levels gained) |
train_skill
¶
Train a skill using training points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character_id
|
UUID
|
Character ID |
required |
skill_name
|
str
|
Skill to train |
required |
training_points
|
int
|
Points to spend |
1
|
Returns:
| Type | Description |
|---|---|
tuple[bool, int]
|
Tuple of (success, levels gained) |
skill_check
¶
skill_check(
character: Character,
skill_name: str,
difficulty: CheckDifficulty | int,
stat_bonus: bool = True,
) -> SkillCheckResult
Perform a skill check.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character making the check |
required |
skill_name
|
str
|
Skill being checked |
required |
difficulty
|
CheckDifficulty | int
|
Target number or CheckDifficulty enum |
required |
stat_bonus
|
bool
|
Whether to add stat bonuses |
True
|
Returns:
| Type | Description |
|---|---|
SkillCheckResult
|
SkillCheckResult with outcome details |
opposed_check
¶
opposed_check(
attacker: Character,
defender: Character,
attack_skill: str,
defend_skill: str,
) -> tuple[SkillCheckResult, SkillCheckResult]
Perform an opposed skill check.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attacker
|
Character
|
Character initiating the check |
required |
defender
|
Character
|
Character defending |
required |
attack_skill
|
str
|
Attacker's skill |
required |
defend_skill
|
str
|
Defender's skill |
required |
Returns:
| Type | Description |
|---|---|
tuple[SkillCheckResult, SkillCheckResult]
|
Tuple of (attacker_result, defender_result) |
get_available_skills
¶
Get all skills available to a character based on class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character to check |
required |
Returns:
| Type | Description |
|---|---|
list[SkillDefinition]
|
List of available skill definitions |
get_trainable_skills
¶
Get skills that can be trained at a guild.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
character
|
Character
|
Character to check |
required |
Returns:
| Type | Description |
|---|---|
list[SkillDefinition]
|
List of trainable skill definitions |
Commands¶
Dialogue Commands¶
Commands for interacting with AI-powered NPCs:
talk <npc> <message> - Talk to an NPC
ask <npc> about <topic> - Ask NPC about a topic
greet <npc> - Greet an NPC (aliases: hello, hi)
conversations - List active conversations (alias: convos)
endconversation <npc> - End conversation (aliases: endconv, bye)
dialogue
¶
Dialogue command handlers for AI NPC conversations.
cmd_talk
async
¶
Talk to an NPC using AI dialogue.
Usage: talk
cmd_ask
async
¶
Ask an NPC about a specific topic.
Usage: ask
cmd_conversations
async
¶
List active conversations with NPCs.
cmd_endconversation
async
¶
End a conversation with an NPC.
Usage: endconversation
cmd_greet
async
¶
Greet an NPC to initiate conversation.
This sends a generic greeting to the NPC, which can be useful to start a conversation or see the NPC's introduction.
Examples:
greet blacksmith hello merchant hi guard
Economy Commands¶
Commands for economic activities:
buy <item> [from <npc>] - Purchase an item
sell <item> [to <npc>] - Sell an item
trade <player> - Initiate a trade
bank deposit <amount> - Deposit currency
bank withdraw <amount> - Withdraw currency
auction list - View auction house
auction bid <id> <amount> - Bid on an item
economy
¶
Economy command handlers for shops, banking, and trading.
Information Commands¶
Commands for getting information:
score - View character sheet
skills - List your skills
quests - View quest log
who - List online players
time - View in-game time
weather - View current weather
information
¶
Information command handlers.
cmd_help
async
¶
Show help information.
Displays command documentation using the HelpGenerator system. When called without arguments, lists all available commands grouped by category. When called with a command name, shows detailed help for that specific command.
Examples:
help help look help attack help teleport
See Also
commands
Content Pack¶
The Classic RPG content pack registers all systems, commands, and game content:
from maid_engine import GameEngine
from maid_stdlib import StdlibContentPack
from maid_classic_rpg import ClassicRPGContentPack
engine = GameEngine(settings)
# Load packs in dependency order
engine.load_content_pack(StdlibContentPack())
engine.load_content_pack(ClassicRPGContentPack())
await engine.start()
ClassicRPGContentPack
¶
Classic RPG content pack.
Provides a complete traditional MUD experience with: - Combat system with tactical positioning - Magic system with spells and effects - Crafting and gathering - Economy (shops, trading, banking, auctions) - Social features (guilds, factions, achievements) - Quest system with objectives and rewards - PvP (arenas, duels, rankings) - World dynamics (time, weather, ecosystems)
register_commands
¶
Register commands provided by this pack.
register_document_schemas
¶
register_document_schemas(store: DocumentStore) -> None
Register document schemas used by this pack.
register_component_types
¶
Register component types for persistence serialization.
register_api_routes
¶
Register API routes. Classic RPG has no custom admin routes.
on_load
async
¶
on_load(engine: GameEngine) -> None
Called when pack is loaded.
Initializes game data including: - Quest definitions from data files - Crafting recipes - Default world setup if needed - RPG-specific error patterns for anomaly detection
on_unload
async
¶
on_unload(engine: GameEngine) -> None
Called when pack is unloaded.
Performs cleanup: - Saves any pending data - Releases resources
Configuration¶
The maid-classic-rpg pack does not define its own MAID_-prefixed settings
family. Gameplay tuning values (combat formulas, starting gold, day/night and
weather timings, etc.) live as constants and defaults inside the individual
systems rather than as environment variables. Engine-level settings such as
MAID_GAME_* and MAID_AI_* still apply.
Package API¶
Full package API documentation:
maid_classic_rpg
¶
MAID Classic RPG - Traditional MUD gameplay content pack.
This package provides a complete classic MUD experience:
- Combat system with tactical grid positioning
- Magic system with spells and effects
- Crafting and gathering
- Economy (shops, trading, banking, auctions)
- Social features (guilds, factions, achievements)
- Quest system with objectives and rewards
- PvP (arenas, duels, rankings)
- World dynamics (time, weather, ecosystems)
ClassicRPGContentPack
¶
Classic RPG content pack.
Provides a complete traditional MUD experience with: - Combat system with tactical positioning - Magic system with spells and effects - Crafting and gathering - Economy (shops, trading, banking, auctions) - Social features (guilds, factions, achievements) - Quest system with objectives and rewards - PvP (arenas, duels, rankings) - World dynamics (time, weather, ecosystems)
Source code in packages/maid-classic-rpg/src/maid_classic_rpg/pack.py
get_dependencies
¶
get_systems
¶
Get systems provided by this pack.
Source code in packages/maid-classic-rpg/src/maid_classic_rpg/pack.py
on_load
async
¶
on_load(engine: GameEngine) -> None
Called when pack is loaded.
Initializes game data including: - Quest definitions from data files - Crafting recipes - Default world setup if needed - RPG-specific error patterns for anomaly detection
Source code in packages/maid-classic-rpg/src/maid_classic_rpg/pack.py
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 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 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 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 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 | |
on_unload
async
¶
on_unload(engine: GameEngine) -> None
Called when pack is unloaded.
Performs cleanup: - Saves any pending data - Releases resources
Source code in packages/maid-classic-rpg/src/maid_classic_rpg/pack.py
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 | |
register_api_routes
¶
register_commands
¶
Register commands provided by this pack.
Source code in packages/maid-classic-rpg/src/maid_classic_rpg/pack.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
register_component_types
¶
Register component types for persistence serialization.
Source code in packages/maid-classic-rpg/src/maid_classic_rpg/pack.py
register_document_schemas
¶
register_document_schemas(store: DocumentStore) -> None
Register document schemas used by this pack.