aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-07 23:28:29 -0400
committerhistoria <[not public]>2026-07-07 23:28:29 -0400
commit59a844137138b328cf415d29b8a1bc40c6469a31 (patch)
tree13eaadd7fac06b3fd516ebba69c7a001630957fa
parent74803657d587b1f93b739c1ee25bb8d62df95413 (diff)
downloadthehouseoficarus-59a844137138b328cf415d29b8a1bc40c6469a31.tar.gz
feat: support up/down for insert/remove in admin gui
-rw-r--r--data/.admin_history.json2
-rw-r--r--data/courses/test2.yaml60
-rw-r--r--data/rooms/intro/1005.yaml16
-rw-r--r--data/rooms/intro/1006.yaml16
-rw-r--r--data/rooms/intro/1007.yaml20
-rw-r--r--data/rooms/intro/1008.yaml20
-rw-r--r--data/rooms/intro/1009.yaml12
-rw-r--r--data/rooms/intro/2004.yaml2
-rw-r--r--internal/admin/static/map.js33
-rw-r--r--internal/admin/static/objecteditor.js4
10 files changed, 24 insertions, 161 deletions
diff --git a/data/.admin_history.json b/data/.admin_history.json
index cedb6a1..3f63f44 100644
--- a/data/.admin_history.json
+++ b/data/.admin_history.json
@@ -1 +1 @@
-{"history":[{"time":"2026-07-07T21:21:13-04:00","description":"Updated course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\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: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T21:21:15-04:00","description":"Updated course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T21:21:19-04:00","description":"Updated course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T21:21:40-04:00","description":"create room 1010","file_path":"data/rooms/intro/1010.yaml","old_content":"","new_content":"exits: {}\nid: 1010\nname: 'Room #1010'\n","is_delete":false,"is_create":true,"extra_files":[{"file_path":"data/rooms/intro/1009.yaml","old_content":"exits: {}\nid: 1009\nname: 'Room #1009'\n","new_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1010\n hidden: true\n always_blocked: true\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-07T21:21:40-04:00","description":"attach room 1010 to course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n room_id: 1010\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T21:21:46-04:00","description":"detach room 1010 from course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n room_id: 1010\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T21:21:48-04:00","description":"delete room 1010 (cleaned 1 exits)","file_path":"data/rooms/intro/1010.yaml","old_content":"exits: {}\nid: 1010\nname: 'Room #1010'\n","new_content":"","is_delete":true,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1010\n hidden: true\n always_blocked: true\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]}],"redo":null} \ No newline at end of file
+{"history":[{"time":"2026-07-07T23:12:16-04:00","description":"detach room 1009 from course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - exit_dir: north\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1009\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T23:12:16-04:00","description":"delete room 1009 (cleaned 1 exits)","file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits: {}\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/1008.yaml","old_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1009\n hidden: true\n always_blocked: true\n southwest:\n room: 2004\n hidden: true\n always_blocked: true\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n southwest:\n room: 2004\n hidden: true\n always_blocked: true\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-07T23:12:18-04:00","description":"detach room 1008 from course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - exit_dir: northwest\n fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1008\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T23:12:18-04:00","description":"delete room 1008 (cleaned 1 exits)","file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n southwest:\n room: 2004\n hidden: true\n always_blocked: true\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/1006.yaml","old_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n northwest:\n room: 1008\n hidden: true\n always_blocked: true\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-07T23:12:20-04:00","description":"detach room 1006 from course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - exit_dir: east\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases: []\n room_id: 1006\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T23:12:20-04:00","description":"delete room 1006 (cleaned 1 exits)","file_path":"data/rooms/intro/1006.yaml","old_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits: {}\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/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n hidden: true\n always_blocked: true\n west:\n room: 2004\n hidden: true\n always_blocked: true\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 2004\n hidden: true\n always_blocked: true\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-07T23:12:21-04:00","description":"detach room 1007 from course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - exit_dir: northeast\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: DONEZO\n room_id: 1007\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T23:12:21-04:00","description":"delete room 1007 (cleaned 1 exits)","file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 2004\n hidden: true\n always_blocked: true\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 north:\n room: 2004\n northeast:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 2004\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-07T23:12:22-04:00","description":"detach room 1005 from course test2","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - exit_dir: south\n fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 1\n message: You do it\n room_id: 1005\n verb: jump\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","is_delete":false,"is_create":false},{"time":"2026-07-07T23:12:22-04:00","description":"delete room 1005 (cleaned 1 exits)","file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 2004\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/2004.yaml","old_content":"id: 2004\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 2003\n northwest:\n room: 2002\n south:\n room: 1005\n west:\n room: 2005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 2004\nname: Test Room\ncolor: \"\"\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: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-07T23:12:27-04:00","description":"delete course test2 (last obstacle removed)","file_path":"data/courses/test2.yaml","old_content":"completion_xp: 50\nname: Test 222\nobstacles:\n - fail_damage:\n - 0\n - 0\n phases:\n - delay: 3\n message: Test\n - delay: 2\n message: Test\n room_id: 2004\n verb: climb\n xp: 0\nrequired_level: 1\nstart_room: 2004\n","new_content":"","is_delete":true,"is_create":false}],"redo":null} \ No newline at end of file
diff --git a/data/courses/test2.yaml b/data/courses/test2.yaml
deleted file mode 100644
index 41e59f1..0000000
--- a/data/courses/test2.yaml
+++ /dev/null
@@ -1,60 +0,0 @@
-completion_xp: 50
-name: Test 222
-obstacles:
- - exit_dir: south
- fail_damage:
- - 0
- - 0
- phases:
- - delay: 3
- message: Test
- - delay: 2
- message: Test
- room_id: 2004
- verb: climb
- xp: 0
- - exit_dir: northeast
- fail_damage:
- - 0
- - 0
- phases:
- - delay: 1
- message: You do it
- room_id: 1005
- verb: jump
- xp: 0
- - exit_dir: east
- fail_damage:
- - 0
- - 0
- phases:
- - delay: 1
- message: DONEZO
- room_id: 1007
- verb: climb
- xp: 0
- - exit_dir: northwest
- fail_damage:
- - 0
- - 0
- phases: []
- room_id: 1006
- verb: climb
- xp: 0
- - exit_dir: north
- fail_damage:
- - 0
- - 0
- phases: []
- room_id: 1008
- verb: climb
- xp: 0
- - fail_damage:
- - 0
- - 0
- phases: []
- room_id: 1009
- verb: climb
- xp: 0
-required_level: 1
-start_room: 2004
diff --git a/data/rooms/intro/1005.yaml b/data/rooms/intro/1005.yaml
deleted file mode 100644
index 3d81e8d..0000000
--- a/data/rooms/intro/1005.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-id: 1005
-name: 'Room #1005'
-color: ""
-description: []
-exits:
- north:
- room: 2004
- northeast:
- room: 1007
-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
deleted file mode 100644
index 88ee5dd..0000000
--- a/data/rooms/intro/1006.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-id: 1006
-name: 'Room #1006'
-color: ""
-description: []
-exits:
- northwest:
- room: 1008
- hidden: true
- always_blocked: true
-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
deleted file mode 100644
index 570183b..0000000
--- a/data/rooms/intro/1007.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-id: 1007
-name: 'Room #1007'
-color: ""
-description: []
-exits:
- east:
- room: 1006
- hidden: true
- always_blocked: true
- west:
- room: 2004
- hidden: true
- always_blocked: true
-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
deleted file mode 100644
index 600de4e..0000000
--- a/data/rooms/intro/1008.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-id: 1008
-name: 'Room #1008'
-color: ""
-description: []
-exits:
- north:
- room: 1009
- hidden: true
- always_blocked: true
- southwest:
- room: 2004
- hidden: true
- always_blocked: true
-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
deleted file mode 100644
index 80d1886..0000000
--- a/data/rooms/intro/1009.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-id: 1009
-name: 'Room #1009'
-color: ""
-description: []
-exits: {}
-objects: []
-item_spawns: []
-mobs: []
-on_enter: []
-hazard: ""
-block_transport: false
-triggers: []
diff --git a/data/rooms/intro/2004.yaml b/data/rooms/intro/2004.yaml
index c84ea1d..73d912e 100644
--- a/data/rooms/intro/2004.yaml
+++ b/data/rooms/intro/2004.yaml
@@ -8,8 +8,6 @@ exits:
room: 2003
northwest:
room: 2002
- south:
- room: 1005
west:
room: 2005
objects: []
diff --git a/internal/admin/static/map.js b/internal/admin/static/map.js
index 7cd4430..3507e2d 100644
--- a/internal/admin/static/map.js
+++ b/internal/admin/static/map.js
@@ -20,7 +20,8 @@ var gridDirs = [
var oppositeDir = {
north:'south', south:'north', east:'west', west:'east',
northeast:'southwest', northwest:'southeast',
- southeast:'northwest', southwest:'northeast'
+ southeast:'northwest', southwest:'northeast',
+ up:'down', down:'up'
};
var saveTimer = null;
var upTarget = {}, downTarget = {};
@@ -2215,13 +2216,13 @@ function showRoomContextMenu(x, y, id) {
}
// buildSubmenuItem constructs a parent menu row ("Insert Room"/"Remove Room")
-// that carries a nested submenu of the room's horizontal exits. The submenu is
+// 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
// on mouseleave) and click (keyboard/mobile accessibility), mirroring how
// Windows cascading menus behave. closeAll closes the whole context menu;
// overlay carries the shared hide-timer slot.
function buildSubmenuItem(label, id, mode, closeAll, overlay, menu) {
- var dirs = roomHorizontalDirs(id);
+ var dirs = roomDirs(id);
var empty = dirs.length === 0;
var item = document.createElement('div');
@@ -2239,8 +2240,8 @@ function buildSubmenuItem(label, id, mode, closeAll, overlay, menu) {
// Still surface the "no exits" reason on click so it's discoverable.
btn.onclick = function() {
notify(mode === 'insert'
- ? 'No horizontal exits to insert into from #' + id
- : 'No horizontal exits to remove from #' + id, 'error');
+ ? 'No exits to insert into from #' + id
+ : 'No exits to remove from #' + id, 'error');
};
return item;
}
@@ -2312,31 +2313,39 @@ function buildSubmenuItem(label, id, mode, closeAll, overlay, menu) {
return item;
}
-// roomHorizontalDirs returns the room's outward horizontal exits on the current
-// z-level, in gridDirs order, derived from mapData.links. Empty when the room
-// has no horizontal exits to insert into / remove from.
-function roomHorizontalDirs(id) {
+// roomDirs returns the room's outward exits (horizontal + up/down) derived from
+// mapData.links and mapData.{upLinks,downLinks}. Horizontal exits are ordered by
+// gridDirs; up/down appear last. Empty when the room has no exits.
+function roomDirs(id) {
if (!mapData || !mapData.links) return [];
var horizontal = {};
gridDirs.forEach(function(d) { horizontal[d.dir] = true; });
var seen = {};
- var dirs = [];
+
mapData.links.forEach(function(l) {
if (l.from === id && horizontal[l.dir] && !seen[l.dir]) {
seen[l.dir] = true;
- dirs.push(l.dir);
} else if (l.to === id && l.bidirectional && horizontal[l.dir]) {
var opp = oppositeDir[l.dir];
if (opp && !seen[opp]) {
seen[opp] = true;
- dirs.push(opp);
}
}
});
+
+ if (mapData.upLinks) mapData.upLinks.forEach(function(l) {
+ if (l.from === id) seen['up'] = true;
+ });
+ if (mapData.downLinks) mapData.downLinks.forEach(function(l) {
+ if (l.from === id) seen['down'] = true;
+ });
+
var ordered = [];
gridDirs.forEach(function(d) {
if (seen[d.dir]) ordered.push(d.dir);
});
+ if (seen['up']) ordered.push('up');
+ if (seen['down']) ordered.push('down');
return ordered;
}
diff --git a/internal/admin/static/objecteditor.js b/internal/admin/static/objecteditor.js
index d4cca21..2046f2e 100644
--- a/internal/admin/static/objecteditor.js
+++ b/internal/admin/static/objecteditor.js
@@ -73,8 +73,8 @@ var SECTIONS = [
['respawn_ticks', 'Respawn Ticks', 'number', '50', 'narrow'],
],
subtables: [
- {label:'Levels', key:'levels', fields:[
- ['message', 'Message', 'text'], ['degrade_message', 'Degrade Message', 'text']
+ {label:'Levels of Decay', key:'levels', fields:[
+ ['message', 'Look Message', 'text'], ['degrade_message', 'Degrade Message', 'text']
]}
]
},