The out-of-tree Bunnyland plugin package bunnyland_aquasim (plugin id bunnyland.aquasim).
Tests run against a sibling bunnyland-server checkout without installing anything —
tests/conftest.py puts both this package's src/ and ../bunnyland-server/src on
sys.path. From this server/ directory:
# uses the sibling bunnyland-server's virtualenv/deps
uv run --project ../../bunnyland-server -m pytest
# or, if bunnyland + relics are already importable:
python -m pytestLint:
uv run --project ../../bunnyland-server ruff check src testsbunnyland serve --module bunnyland_aquasimdefault_enabled=True, so no --plugin flag is required once the module is imported.
Each mechanic lives in its own module with a matching tests/test_*.py:
- Water rooms / submersion (
submersion.py) —SubmergedComponentmarks a room as deep water; aquaticRoomComponent.biomes count too.is_water_room,room_depth, andwater_room_ofanswer the questions the rest of the pack asks. - Breath + drowning (
breath.py) —BreathComponentreuses the shared needsMeteras oxygen debt: a per-tickBreathConsequenceraises it underwater (scaled by depth, slowed by a held rebreather and by swim skill), lowers it at the surface, and appliesHealthComponentdamage once the debt maxes out. EmitsBreathChangedEventandDrowningEvent;breath_fragmentsrender first-person burning-lungs lines. - Diving for treasure (
diving.py) — thediveandsurfaceverbs.deterministic_lootpicks a cache's reward from a hash of the cache id and world epoch, so there is no runtime randomness. EmitsTreasureRecoveredEventandSurfacedEvent. - Currents & hazards (
currents.py) —CurrentComponentdrifts non-mastery swimmers toward anExitTo;HazardComponentdamages the ungeared.CurrentConsequenceandHazardConsequenceemitDriftedEventandHazardStruckEvent. - Swim skill (
swim.py) —SwimSkillComponentimproves viaimprove_swim, reducing breath drain and hazard damage and resisting currents at mastery. EmitsSwimSkillImprovedEvent;swim_fragmentsrender a first-person mastery line.
Shared surfaces: components.py (passive room/item/cache state), spatial.py
(holder_of/room_of), enrichment.py (AquaWorldgenHook), prefabs.py
(spawn_rebreather, spawn_treasure_cache), install.py (registers the consequences), and
plugin.py (the Plugin contribution).