aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-09 17:12:03 -0400
committerhistoria <[not public]>2026-07-09 17:12:03 -0400
commitb888414c63c0e5fae0d33b3c5faea8a604d195fa (patch)
tree1c5a54101c774d6126c3d08fa5b6e9b44d0c3c04
parentb8c90886ef1f3afb8d908aac89028bd177836cae (diff)
downloadthehouseoficarus-b888414c63c0e5fae0d33b3c5faea8a604d195fa.tar.gz
feat(admin): multi-select and delete rooms
-rw-r--r--building_guide/admin.md3
-rw-r--r--data/.admin_history.json2
-rw-r--r--data/courses/test.yaml13
-rw-r--r--data/courses/testcourse.yaml38
-rw-r--r--data/rooms/intro/1005.yaml18
-rw-r--r--data/rooms/intro/1006.yaml14
-rw-r--r--data/rooms/intro/1007.yaml18
-rw-r--r--data/rooms/intro/1008.yaml16
-rw-r--r--data/rooms/intro/1009.yaml20
-rw-r--r--data/rooms/intro/1010.yaml16
-rw-r--r--data/rooms/intro/2001.yaml22
-rw-r--r--data/rooms/intro/2002.yaml21
-rw-r--r--data/rooms/intro/2003.yaml19
-rw-r--r--data/rooms/intro/2004.yaml19
-rw-r--r--data/rooms/intro/2005.yaml23
-rw-r--r--internal/admin/api_rooms_bulk_delete.go132
-rw-r--r--internal/admin/server.go1
-rw-r--r--internal/admin/static/map.js87
18 files changed, 338 insertions, 144 deletions
diff --git a/building_guide/admin.md b/building_guide/admin.md
index d66aabe..951d4eb 100644
--- a/building_guide/admin.md
+++ b/building_guide/admin.md
@@ -270,7 +270,8 @@ even across sessions.
The map page (`/`) is the main navigation hub:
- Rooms are displayed as colored nodes on a 3D grid, connected by links (bars for two-way, arrows for one-way, X for blocked).
- Click a room node to edit its properties (name, description, color, exits, objects, mobs, spawns).
-- **Drag** connections between rooms to create reciprocal exits. **Shift+drag** to create a one-way exit (only the exit from the source room is written; the target room is not modified).
+- **Drag** connections between rooms to create reciprocal exits. **Ctrl+drag** to create a one-way exit (only the exit from the source room is written; the target room is not modified).
+- **Shift+drag** draws a selection box to multi-select rooms (Shift+right-drag subtracts). **Right-click** any selected room for a context menu with **Delete** to remove all selected rooms at once. While a multi-selection is active, right-drag link removal is disabled; clear the selection first by clicking elsewhere or pressing Escape.
- **Right-drag** between rooms to delete the exit (full reciprocal; the sidebar Exits tab has a "Remove reverse" button to convert a two-way exit to one-way).
- If deleting an exit severs a room from the seed grid, the room moves to the "Disconnected Rooms" sidebar. Relink it via the Exits tab "Add" form with its ID and direction.
- Right-click (or long-press) a room to delete it or access advanced options.
diff --git a/data/.admin_history.json b/data/.admin_history.json
index 9562261..caadf98 100644
--- a/data/.admin_history.json
+++ b/data/.admin_history.json
@@ -1 +1 @@
-{"history":[{"time":"2026-07-09T16:06:25-04:00","description":"bulk edit 2 rooms","file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: solar_radiation\nblock_transport: false\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2004.yaml","old_content":"id: 2004\nname: Test Room\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: solar_radiation\nblock_transport: false\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:06:29-04:00","description":"bulk edit 4 rooms","file_path":"data/rooms/intro/2002.yaml","old_content":"id: 2002\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2005.yaml","old_content":"id: 2005\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:06:35-04:00","description":"bulk edit 4 rooms","file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"03\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:06:50-04:00","description":"bulk edit 4 rooms","file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:06:57-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"id: 2001\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nobjects:\n - name: hidden guy\n hidden: true\n description:\n - text: YOU FOUND HIM\n - id: tree\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"name: \"Test Room\"\ndescription:\n - text: \"It's a test room\"\nexits:\n east:\n room: 2005\n north:\n room: 2001\n","new_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:06:59-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n","new_content":"block_transport: false\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:00-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"block_transport: false\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n","new_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:00-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n","new_content":"block_transport: false\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:01-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"block_transport: false\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n","new_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:02-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n","new_content":"block_transport: false\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:03-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"block_transport: false\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n","new_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:05-04:00","description":"bulk edit 6 rooms","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2006.yaml","old_content":"block_transport: true\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n","new_content":"block_transport: false\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2005\n north:\n room: 2001\nname: Test Room\n"},{"file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: true\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:41-04:00","description":"bulk edit 4 rooms (move to example_unused)","file_path":"data/rooms/intro/2002.yaml","new_file_path":"data/rooms/example_unused/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2005.yaml","new_file_path":"data/rooms/example_unused/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","new_file_path":"data/rooms/example_unused/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","new_file_path":"data/rooms/example_unused/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:07:50-04:00","description":"bulk edit 4 rooms (move to intro)","file_path":"data/rooms/example_unused/2002.yaml","new_file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/example_unused/2005.yaml","new_file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/example_unused/2003.yaml","new_file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/example_unused/2004.yaml","new_file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:08:27-04:00","description":"bulk edit 4 rooms","file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]},{"time":"2026-07-09T16:08:28-04:00","description":"bulk edit 4 rooms","file_path":"data/rooms/intro/2002.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2003\n south:\n room: 2005\n southeast:\n room: 2004\n west:\n room: 2001\nhazard: solar_radiation\nid: 2002\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2005.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2004\n north:\n room: 2002\n northeast:\n room: 2003\n northwest:\n room: 2001\n west:\n room: 2006\nhazard: solar_radiation\nid: 2005\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: solar_radiation\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"},{"file_path":"data/rooms/intro/2004.yaml","old_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"31\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n west:\n room: 2005\nhazard: solar_radiation\nid: 2004\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n"}]}],"redo":null} \ No newline at end of file
+{"history":[{"time":"2026-07-09T16:59:13-04:00","description":"create room 1006","file_path":"data/rooms/intro/1006.yaml","old_content":"","new_content":"exits:\n west:\n room: 1005\nid: 1006\nname: 'Room #1006'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1005.yaml","old_content":"exits:\n west:\n room: 2001\nid: 1005\nname: 'Room #1005'\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T16:59:13-04:00","description":"create room 1007","file_path":"data/rooms/intro/1007.yaml","old_content":"","new_content":"exits:\n south:\n room: 1006\nid: 1007\nname: 'Room #1007'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1006.yaml","old_content":"exits:\n west:\n room: 1005\nid: 1006\nname: 'Room #1006'\n","new_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1007\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T16:59:14-04:00","description":"create room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"","new_content":"exits:\n east:\n room: 1007\nid: 1008\nname: 'Room #1008'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1007.yaml","old_content":"exits:\n south:\n room: 1006\nid: 1007\nname: 'Room #1007'\n","new_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1006\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T16:59:14-04:00","description":"link 1008 south 1005","file_path":"data/rooms/intro/1008.yaml","old_content":"exits:\n east:\n room: 1007\nid: 1008\nname: 'Room #1008'\n","new_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1007\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-09T16:59:14-04:00","description":"link 1005 north 1008 (reverse)","file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n north:\n room: 1008\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-09T16:59:15-04:00","description":"create room 1009","file_path":"data/rooms/intro/1009.yaml","old_content":"","new_content":"exits:\n south:\n room: 1008\nid: 1009\nname: 'Room #1009'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1007\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1007\n north:\n room: 1009\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T16:59:15-04:00","description":"create room 1010","file_path":"data/rooms/intro/1010.yaml","old_content":"","new_content":"exits:\n west:\n room: 1009\nid: 1010\nname: 'Room #1010'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1009.yaml","old_content":"exits:\n south:\n room: 1008\nid: 1009\nname: 'Room #1009'\n","new_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1010\n south:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T16:59:16-04:00","description":"link 1010 south 1007","file_path":"data/rooms/intro/1010.yaml","old_content":"exits:\n west:\n room: 1009\nid: 1010\nname: 'Room #1010'\n","new_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1007\n west:\n room: 1009\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-09T16:59:16-04:00","description":"link 1007 north 1010 (reverse)","file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1006\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1010\n south:\n room: 1006\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-09T16:59:34-04:00","description":"delete 4 rooms (cleaned 2 exits)","file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1010\n south:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n north:\n room: 1008\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"},{"file_path":"data/rooms/intro/1006.yaml","old_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1007\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"},{"file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1007\n north:\n room: 1009\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true},{"file_path":"data/rooms/intro/1010.yaml","old_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1007\n west:\n room: 1009\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true},{"file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1010\n south:\n room: 1006\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true}]},{"time":"2026-07-09T17:09:03-04:00","description":"create room 1007","file_path":"data/rooms/intro/1007.yaml","old_content":"","new_content":"exits:\n south:\n room: 1005\nid: 1007\nname: 'Room #1007'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n north:\n room: 1007\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T17:09:03-04:00","description":"create room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"","new_content":"exits:\n south:\n room: 1007\nid: 1008\nname: 'Room #1008'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1007.yaml","old_content":"exits:\n south:\n room: 1005\nid: 1007\nname: 'Room #1007'\n","new_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1008\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T17:09:04-04:00","description":"create room 1009","file_path":"data/rooms/intro/1009.yaml","old_content":"","new_content":"exits:\n west:\n room: 1008\nid: 1009\nname: 'Room #1009'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1008.yaml","old_content":"exits:\n south:\n room: 1007\nid: 1008\nname: 'Room #1008'\n","new_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1009\n south:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T17:09:04-04:00","description":"create room 1010","file_path":"data/rooms/intro/1010.yaml","old_content":"","new_content":"exits:\n north:\n room: 1009\nid: 1010\nname: 'Room #1010'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1009.yaml","old_content":"exits:\n west:\n room: 1008\nid: 1009\nname: 'Room #1009'\n","new_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1010\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-09T17:09:04-04:00","description":"link 1010 west 1007","file_path":"data/rooms/intro/1010.yaml","old_content":"exits:\n north:\n room: 1009\nid: 1010\nname: 'Room #1010'\n","new_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1009\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:09:04-04:00","description":"link 1007 east 1010 (reverse)","file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1008\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1010\n north:\n room: 1008\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:09:09-04:00","description":"attach room 1007 to course testcourse","file_path":"data/courses/testcourse.yaml","old_content":"completion_xp: 0\nname: Test Course\nobstacles:\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 2005\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: west\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 2003\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2002\n","new_content":"completion_xp: 0\nname: Test Course\nobstacles:\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 2005\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 2003\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n room_id: 1007\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2002\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:09:51-04:00","description":"Created course test","file_path":"data/courses/test.yaml","old_content":"","new_content":"completion_xp: 0\nname: test\nobstacles:\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":true},{"time":"2026-07-09T17:09:57-04:00","description":"Updated course test","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:09:57-04:00","description":"attach room 1008 to course test","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:09:59-04:00","description":"attach room 1009 to course test","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:10:01-04:00","description":"Updated course test","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:10:01-04:00","description":"link 1009 southwest 1007","file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1010\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1010\n southwest:\n room: 1007\n hidden: true\n always_blocked: true\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:10:01-04:00","description":"Updated course test","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:10:07-04:00","description":"detach room 1008 from course test","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"completion_xp: 0\nname: test\nobstacles:\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":false},{"time":"2026-07-09T17:10:07-04:00","description":"detach room 1007 from course test","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 0\n message: \"\"\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","is_delete":false,"is_create":false}],"redo":[{"time":"2026-07-09T17:10:07-04:00","description":"delete 4 rooms (cleaned 1 exits)","file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1009\n south:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n north:\n room: 1007\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n west:\n room: 2001\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"},{"file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1010\n north:\n room: 1008\n south:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true},{"file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1010\n southwest:\n room: 1007\n hidden: true\n always_blocked: true\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true},{"file_path":"data/rooms/intro/1010.yaml","old_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1009\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true}]},{"time":"2026-07-09T17:10:07-04:00","description":"delete course test (last obstacle removed)","file_path":"data/courses/test.yaml","old_content":"completion_xp: 0\nname: test\nobstacles:\n - exit_dir: southwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 1007\n","new_content":"","is_delete":true,"is_create":false}]} \ No newline at end of file
diff --git a/data/courses/test.yaml b/data/courses/test.yaml
new file mode 100644
index 0000000..f10c80d
--- /dev/null
+++ b/data/courses/test.yaml
@@ -0,0 +1,13 @@
+completion_xp: 0
+name: test
+obstacles:
+ - exit_dir: southwest
+ fail_damage:
+ - 0
+ - 0
+ phases: []
+ room_id: 1009
+ verb: climb
+ xp: 0
+required_level: 1
+start_room: 1007
diff --git a/data/courses/testcourse.yaml b/data/courses/testcourse.yaml
deleted file mode 100644
index a6b44b2..0000000
--- a/data/courses/testcourse.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-completion_xp: 0
-name: Test Course
-obstacles:
- - exit_dir: south
- fail_damage:
- - 0
- - 0
- phases:
- - delay: 0
- message: ""
- room_id: 2002
- verb: climb
- xp: 0
- - exit_dir: east
- fail_damage:
- - 0
- - 0
- phases: []
- room_id: 2005
- verb: climb
- xp: 0
- - exit_dir: north
- fail_damage:
- - 0
- - 0
- room_id: 2004
- verb: climb
- xp: 0
- - exit_dir: west
- fail_damage:
- - 0
- - 0
- phases: []
- room_id: 2003
- verb: climb
- xp: 0
-required_level: 1
-start_room: 2002
diff --git a/data/rooms/intro/1005.yaml b/data/rooms/intro/1005.yaml
new file mode 100644
index 0000000..271870e
--- /dev/null
+++ b/data/rooms/intro/1005.yaml
@@ -0,0 +1,18 @@
+id: 1005
+name: 'Room #1005'
+color: ""
+description: []
+exits:
+ east:
+ room: 1006
+ north:
+ room: 1007
+ west:
+ room: 2001
+objects: []
+item_spawns: []
+mobs: []
+on_enter: []
+hazard: ""
+block_transport: false
+triggers: []
diff --git a/data/rooms/intro/1006.yaml b/data/rooms/intro/1006.yaml
new file mode 100644
index 0000000..3f8aa24
--- /dev/null
+++ b/data/rooms/intro/1006.yaml
@@ -0,0 +1,14 @@
+id: 1006
+name: 'Room #1006'
+color: ""
+description: []
+exits:
+ west:
+ room: 1005
+objects: []
+item_spawns: []
+mobs: []
+on_enter: []
+hazard: ""
+block_transport: false
+triggers: []
diff --git a/data/rooms/intro/1007.yaml b/data/rooms/intro/1007.yaml
new file mode 100644
index 0000000..bc05da9
--- /dev/null
+++ b/data/rooms/intro/1007.yaml
@@ -0,0 +1,18 @@
+id: 1007
+name: 'Room #1007'
+color: ""
+description: []
+exits:
+ east:
+ room: 1010
+ north:
+ room: 1008
+ south:
+ room: 1005
+objects: []
+item_spawns: []
+mobs: []
+on_enter: []
+hazard: ""
+block_transport: false
+triggers: []
diff --git a/data/rooms/intro/1008.yaml b/data/rooms/intro/1008.yaml
new file mode 100644
index 0000000..d8dd6c9
--- /dev/null
+++ b/data/rooms/intro/1008.yaml
@@ -0,0 +1,16 @@
+id: 1008
+name: 'Room #1008'
+color: ""
+description: []
+exits:
+ east:
+ room: 1009
+ south:
+ room: 1007
+objects: []
+item_spawns: []
+mobs: []
+on_enter: []
+hazard: ""
+block_transport: false
+triggers: []
diff --git a/data/rooms/intro/1009.yaml b/data/rooms/intro/1009.yaml
new file mode 100644
index 0000000..f75cd82
--- /dev/null
+++ b/data/rooms/intro/1009.yaml
@@ -0,0 +1,20 @@
+id: 1009
+name: 'Room #1009'
+color: ""
+description: []
+exits:
+ south:
+ room: 1010
+ southwest:
+ room: 1007
+ hidden: true
+ always_blocked: true
+ west:
+ room: 1008
+objects: []
+item_spawns: []
+mobs: []
+on_enter: []
+hazard: ""
+block_transport: false
+triggers: []
diff --git a/data/rooms/intro/1010.yaml b/data/rooms/intro/1010.yaml
new file mode 100644
index 0000000..57610a4
--- /dev/null
+++ b/data/rooms/intro/1010.yaml
@@ -0,0 +1,16 @@
+id: 1010
+name: 'Room #1010'
+color: ""
+description: []
+exits:
+ north:
+ room: 1009
+ west:
+ room: 1007
+objects: []
+item_spawns: []
+mobs: []
+on_enter: []
+hazard: ""
+block_transport: false
+triggers: []
diff --git a/data/rooms/intro/2001.yaml b/data/rooms/intro/2001.yaml
index 0f56257..2cfcd83 100644
--- a/data/rooms/intro/2001.yaml
+++ b/data/rooms/intro/2001.yaml
@@ -1,18 +1,23 @@
-block_transport: false
+id: 2001
+name: Test Room
color: ""
description:
- text: It's a test room
exits:
east:
- room: 2002
+ room: 1005
south:
room: 2006
southeast:
room: 2005
west:
room: 1001
-hazard: ""
-id: 2001
+objects:
+ - name: hidden guy
+ hidden: true
+ description:
+ - text: YOU FOUND HIM
+ - id: tree
item_spawns:
- id: bronze_axe
quantity: 1
@@ -25,12 +30,7 @@ item_spawns:
respawn_ticks: 1
mobs:
- id: man
-name: Test Room
-objects:
- - description:
- - text: YOU FOUND HIM
- hidden: true
- name: hidden guy
- - id: tree
on_enter: []
+hazard: ""
+block_transport: false
triggers: []
diff --git a/data/rooms/intro/2002.yaml b/data/rooms/intro/2002.yaml
deleted file mode 100644
index cb7fc97..0000000
--- a/data/rooms/intro/2002.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-block_transport: false
-color: "31"
-description:
- - text: It's a test room
-exits:
- east:
- room: 2003
- south:
- room: 2005
- southeast:
- room: 2004
- west:
- room: 2001
-hazard: solar_radiation
-id: 2002
-item_spawns: []
-mobs: []
-name: Test Room
-objects: []
-on_enter: []
-triggers: []
diff --git a/data/rooms/intro/2003.yaml b/data/rooms/intro/2003.yaml
deleted file mode 100644
index fa7855b..0000000
--- a/data/rooms/intro/2003.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-block_transport: false
-color: "31"
-description:
- - text: It's a test room
-exits:
- south:
- room: 2004
- southwest:
- room: 2005
- west:
- room: 2002
-hazard: solar_radiation
-id: 2003
-item_spawns: []
-mobs: []
-name: Test Room
-objects: []
-on_enter: []
-triggers: []
diff --git a/data/rooms/intro/2004.yaml b/data/rooms/intro/2004.yaml
deleted file mode 100644
index 4426c98..0000000
--- a/data/rooms/intro/2004.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-block_transport: false
-color: "31"
-description:
- - text: It's a test room
-exits:
- north:
- room: 2003
- northwest:
- room: 2002
- west:
- room: 2005
-hazard: solar_radiation
-id: 2004
-item_spawns: []
-mobs: []
-name: Test Room
-objects: []
-on_enter: []
-triggers: []
diff --git a/data/rooms/intro/2005.yaml b/data/rooms/intro/2005.yaml
deleted file mode 100644
index a5368c5..0000000
--- a/data/rooms/intro/2005.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-block_transport: false
-color: "31"
-description:
- - text: It's a test room
-exits:
- east:
- room: 2004
- north:
- room: 2002
- northeast:
- room: 2003
- northwest:
- room: 2001
- west:
- room: 2006
-hazard: solar_radiation
-id: 2005
-item_spawns: []
-mobs: []
-name: Test Room
-objects: []
-on_enter: []
-triggers: []
diff --git a/internal/admin/api_rooms_bulk_delete.go b/internal/admin/api_rooms_bulk_delete.go
new file mode 100644
index 0000000..6aa0181
--- /dev/null
+++ b/internal/admin/api_rooms_bulk_delete.go
@@ -0,0 +1,132 @@
+package admin
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+
+ "thehouseoficarus/internal/world"
+)
+
+type bulkDeleteRequest struct {
+ IDs []int `json:"ids"`
+}
+
+func (s *AdminServer) handleBulkDelete(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ body, readErr := io.ReadAll(r.Body)
+ r.Body.Close()
+ if readErr != nil {
+ writeJSON(w, map[string]any{"error": fmt.Sprintf("read body: %v", readErr)})
+ return
+ }
+
+ var req bulkDeleteRequest
+ if err := json.Unmarshal(body, &req); err != nil {
+ writeJSON(w, map[string]any{"error": fmt.Sprintf("invalid json: %v", err)})
+ return
+ }
+
+ if len(req.IDs) == 0 {
+ writeJSON(w, map[string]any{"error": "no room ids"})
+ return
+ }
+
+ type roomSnapshot struct {
+ id int
+ path string
+ oldContent []byte
+ }
+
+ snapshots := make([]roomSnapshot, 0, len(req.IDs))
+ for _, id := range req.IDs {
+ path, ok := s.world.GetRoomPath(id)
+ if !ok {
+ writeJSON(w, map[string]any{"error": fmt.Sprintf("room %d not found", id)})
+ return
+ }
+ oldContent, snapErr := snapshotFile(path)
+ if snapErr != nil {
+ writeJSON(w, map[string]any{"error": fmt.Sprintf("snapshot room %d: %v", id, snapErr)})
+ return
+ }
+ snapshots = append(snapshots, roomSnapshot{id: id, path: path, oldContent: oldContent})
+ }
+
+ deletedSet := make(map[int]bool, len(req.IDs))
+ for _, snap := range snapshots {
+ s.detachRoomFromCourse(snap.id)
+ if err := os.Remove(snap.path); err != nil {
+ writeJSON(w, map[string]any{"error": fmt.Sprintf("delete room %d: %v", snap.id, err)})
+ return
+ }
+ deletedSet[snap.id] = true
+ }
+
+ s.world.RebuildRoomIndex(s.dataDir)
+ for _, snap := range snapshots {
+ s.world.ClearRoomState(snap.id)
+ }
+
+ allIDs, _ := listRoomIDs(s.dataDir)
+ var extraFiles []ExtraFile
+ var exitCleaned int
+ for _, otherID := range allIDs {
+ if deletedSet[otherID] {
+ continue
+ }
+ otherRoom, loadErr := s.world.LoadRoom(otherID)
+ if loadErr != nil {
+ continue
+ }
+ changed := false
+ for _, dir := range world.ExitOrder {
+ exit, exists := otherRoom.Exits[dir]
+ if !exists || !deletedSet[exit.Room] {
+ continue
+ }
+ delete(otherRoom.Exits, dir)
+ changed = true
+ }
+ if changed {
+ otherPath, pathOk := s.world.GetRoomPath(otherID)
+ if pathOk {
+ oldExtra, _ := snapshotFile(otherPath)
+ newContent, writeErr := writeYAMLFile(otherPath, otherRoom)
+ if writeErr != nil {
+ continue
+ }
+ extraFiles = append(extraFiles, ExtraFile{
+ FilePath: otherPath,
+ OldContent: oldExtra,
+ NewContent: newContent,
+ })
+ exitCleaned++
+ }
+ }
+ }
+
+ for i := 1; i < len(snapshots); i++ {
+ extraFiles = append(extraFiles, ExtraFile{
+ FilePath: snapshots[i].path,
+ OldContent: snapshots[i].oldContent,
+ IsDelete: true,
+ })
+ }
+
+ s.undoStack.Push(ChangeDesc{
+ Description: fmt.Sprintf("delete %d rooms (cleaned %d exits)", len(req.IDs), exitCleaned),
+ FilePath: snapshots[0].path,
+ OldContent: snapshots[0].oldContent,
+ IsDelete: true,
+ ExtraFiles: extraFiles,
+ })
+
+ writeJSON(w, map[string]any{"ok": true, "count": len(req.IDs)})
+}
diff --git a/internal/admin/server.go b/internal/admin/server.go
index c33bd21..67de0ab 100644
--- a/internal/admin/server.go
+++ b/internal/admin/server.go
@@ -126,6 +126,7 @@ func NewServer(cfg *config.Config, useTLS bool, accountStore *player.AccountStor
apiMux.HandleFunc("/api/rooms/move", s.handleRoomMove)
apiMux.HandleFunc("/api/rooms/rename", s.handleRoomRename)
apiMux.HandleFunc("/api/rooms/bulk-edit", s.handleBulkEdit)
+ apiMux.HandleFunc("/api/rooms/bulk-delete", s.handleBulkDelete)
apiMux.HandleFunc("/api/rooms", s.handleRooms)
apiMux.HandleFunc("/api/rooms/new-empty", s.handleCreateEmptyRoom)
apiMux.HandleFunc("/api/rooms/", s.handleRoomByID)
diff --git a/internal/admin/static/map.js b/internal/admin/static/map.js
index 1f67275..e053dda 100644
--- a/internal/admin/static/map.js
+++ b/internal/admin/static/map.js
@@ -42,7 +42,7 @@ function onMapMouseMove(e) {
if (!dragging) return;
var moved = Math.abs(e.clientX - startX) >= 4 || Math.abs(e.clientY - startY) >= 4;
- if (delFromId && moved && !delDrag) { delDrag = true; }
+ if (delFromId && moved && !delDrag && multiSelectedIds.size === 0) { delDrag = true; }
if (delDrag && moved) {
delOneWay = e.ctrlKey;
updateDelDragTarget(e);
@@ -81,7 +81,11 @@ function onMapMouseUp(e) {
var moved = Math.abs(e.clientX - startX) >= 4 || Math.abs(e.clientY - startY) >= 4;
if (delFromId && !delDrag && !moved) {
- showRoomContextMenu(startX, startY, delFromId);
+ if (multiSelectedIds.size > 0) {
+ showBulkDeleteContextMenu(startX, startY, delFromId);
+ } else {
+ showRoomContextMenu(startX, startY, delFromId);
+ }
clearDelHighlight();
dragging = false; dragRoom = false; delFromId = null; delTargetId = null; delDrag = false;
if (document.activeElement && document.activeElement.blur) document.activeElement.blur();
@@ -368,7 +372,7 @@ function renderMap(data) {
var onUdBtn = e.target.classList.contains('ud-btn');
var onNavBtn = e.target.classList.contains('nav-btn');
- if (!e.shiftKey && multiSelectedIds.size > 0) {
+ if (e.button === 0 && !e.shiftKey && multiSelectedIds.size > 0) {
clearMultiSelect();
}
@@ -2263,6 +2267,58 @@ function showRoomContextMenu(x, y, id) {
clampMenuToViewport(menu);
}
+function showBulkDeleteContextMenu(x, y, clickedId) {
+ var overlay = document.createElement('div');
+ overlay.className = 'cm-overlay';
+ var closeAll = function() {
+ if (overlay._subHideTimer) { clearTimeout(overlay._subHideTimer); overlay._subHideTimer = null; }
+ overlay.remove(); menu.remove();
+ };
+ overlay.onclick = closeAll;
+ overlay.addEventListener('contextmenu', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ closeAll();
+ });
+
+ var menu = document.createElement('div');
+ menu.className = 'cm-menu';
+ menu.style.left = x + 'px';
+ menu.style.top = y + 'px';
+ menu.oncontextmenu = function(e) { e.preventDefault(); };
+
+ var n = multiSelectedIds.size;
+ var delBtn = document.createElement('button');
+ delBtn.textContent = 'Delete ' + n + ' room' + (n !== 1 ? 's' : '');
+ delBtn.className = 'danger';
+ delBtn.onclick = function() {
+ closeAll();
+ deleteMultiRooms();
+ };
+ menu.appendChild(delBtn);
+
+ document.body.appendChild(overlay);
+ document.body.appendChild(menu);
+
+ clampMenuToViewport(menu);
+}
+
+function deleteMultiRooms() {
+ var n = multiSelectedIds.size;
+ var cb = document.getElementById('confirmDelete');
+ if (!cb || cb.checked) {
+ if (!confirm('Delete ' + n + ' room' + (n !== 1 ? 's' : '') + '?')) return;
+ }
+ var ids = Array.from(multiSelectedIds);
+ API.post('/api/rooms/bulk-delete', {ids: ids}).then(function(res) {
+ var msg = 'Deleted ' + n + ' room' + (n !== 1 ? 's' : '');
+ notify(msg, 'success');
+ updateUndoBar();
+ clearMultiSelect();
+ loadMap();
+ }).catch(function(e) { notify('Delete failed: ' + extractError(e), 'error'); });
+}
+
// buildSubmenuItem constructs a parent menu row ("Insert Room"/"Remove Room")
// that carries a nested submenu of the room's exits. The submenu is
// revealed by both hover (Windows-style: mouseenter with a small dismiss delay
@@ -2572,6 +2628,19 @@ function applyLinkHighlight(fromId, toId) {
g.appendChild(line);
}
+function restoreRoomStroke(el, id) {
+ if (multiSelectedIds.has(id)) {
+ el.setAttribute('stroke', '#5cf');
+ el.setAttribute('stroke-width', '3.5');
+ } else if (selectedRoom === id) {
+ el.setAttribute('stroke', '#fff');
+ el.setAttribute('stroke-width', '3');
+ } else {
+ el.setAttribute('stroke', el.getAttribute('fill') || '#3a3a6a');
+ el.setAttribute('stroke-width', '1.5');
+ }
+}
+
function clearLinkHighlight() {
var line = document.getElementById('__hl_line');
if (line) line.remove();
@@ -2579,15 +2648,13 @@ function clearLinkHighlight() {
if (linkFromId) {
var el = document.querySelector('.rm[data-id="'+linkFromId+'"]');
if (el) {
- el.setAttribute('stroke', selectedRoom === linkFromId ? '#fff' : (el.getAttribute('fill') || '#3a3a6a'));
- el.setAttribute('stroke-width', selectedRoom === linkFromId ? '3' : '1.5');
+ restoreRoomStroke(el, linkFromId);
}
}
if (linkTargetId) {
var el = document.querySelector('.rm[data-id="'+linkTargetId+'"]');
if (el) {
- el.setAttribute('stroke', selectedRoom === linkTargetId ? '#fff' : (el.getAttribute('fill') || '#3a3a6a'));
- el.setAttribute('stroke-width', selectedRoom === linkTargetId ? '3' : '1.5');
+ restoreRoomStroke(el, linkTargetId);
}
}
}
@@ -2666,15 +2733,13 @@ function clearDelHighlight() {
if (delFromId) {
var el = document.querySelector('.rm[data-id="'+delFromId+'"]');
if (el) {
- el.setAttribute('stroke', selectedRoom === delFromId ? '#fff' : (el.getAttribute('fill') || '#3a3a6a'));
- el.setAttribute('stroke-width', selectedRoom === delFromId ? '3' : '1.5');
+ restoreRoomStroke(el, delFromId);
}
}
if (delTargetId) {
var el = document.querySelector('.rm[data-id="'+delTargetId+'"]');
if (el) {
- el.setAttribute('stroke', selectedRoom === delTargetId ? '#fff' : (el.getAttribute('fill') || '#3a3a6a'));
- el.setAttribute('stroke-width', selectedRoom === delTargetId ? '3' : '1.5');
+ restoreRoomStroke(el, delTargetId);
}
}
}