aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_rooms.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-30 03:57:52 -0400
committerhistoria <[not public]>2026-06-30 03:57:52 -0400
commit712072209ab5e3b3a14ebc0c770b020afe544560 (patch)
treef5247fa8e03ed327ecb6cbff622bf6bdccb2066c /internal/admin/api_rooms.go
parent7a4b91304061777e7b3365b505d1e74878043d35 (diff)
downloadthehouseoficarus-712072209ab5e3b3a14ebc0c770b020afe544560.tar.gz
feat: all admin mapping features working
Diffstat (limited to 'internal/admin/api_rooms.go')
-rw-r--r--internal/admin/api_rooms.go177
1 files changed, 128 insertions, 49 deletions
diff --git a/internal/admin/api_rooms.go b/internal/admin/api_rooms.go
index 4075534..b60aefc 100644
--- a/internal/admin/api_rooms.go
+++ b/internal/admin/api_rooms.go
@@ -228,8 +228,36 @@ func (s *AdminServer) handleRoomByID(w http.ResponseWriter, r *http.Request) {
s.world.RebuildRoomIndex(s.dataDir)
s.world.ClearRoomState(id)
+ allIDs, _ := listRoomIDs(s.dataDir)
+ var exitCleaned int
+ for _, otherID := range allIDs {
+ if otherID == id {
+ 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 || exit.Room != id {
+ continue
+ }
+ delete(otherRoom.Exits, dir)
+ changed = true
+ }
+ if changed {
+ otherPath, pathOk := s.world.GetRoomPath(otherID)
+ if pathOk {
+ writeYAMLFile(otherPath, otherRoom)
+ exitCleaned++
+ }
+ }
+ }
+
s.undoStack.Push(ChangeDesc{
- Description: fmt.Sprintf("delete room %d", id),
+ Description: fmt.Sprintf("delete room %d (cleaned %d exits)", id, exitCleaned),
FilePath: path,
OldContent: oldContent,
IsDelete: true,
@@ -477,25 +505,29 @@ func (s *AdminServer) handleRoomLink(w http.ResponseWriter, r *http.Request) {
roomA, errA := s.world.LoadRoom(body.From)
roomB, errB := s.world.LoadRoom(body.To)
- if errA != nil || errB != nil {
- writeJSON(w, map[string]any{"error": "one or both rooms not found"})
+
+ if errA != nil && errB != nil {
+ writeJSON(w, map[string]any{"error": "both rooms not found"})
return
}
- if roomA == nil || roomB == nil {
- writeJSON(w, map[string]any{"error": "one or both rooms not found"})
- return
+ if (errA != nil && roomA == nil) {
+ roomA = nil
+ }
+ if (errB != nil && roomB == nil) {
+ roomB = nil
}
var dir, oppDir world.ExitDir
- for _, d := range world.ExitOrder {
- if exit, ok := roomA.Exits[d]; ok && exit.Room == body.To {
- dir = d
- break
+ if roomA != nil {
+ for _, d := range world.ExitOrder {
+ if exit, ok := roomA.Exits[d]; ok && exit.Room == body.To {
+ dir = d
+ oppDir = world.OppositeExit[d]
+ break
+ }
}
}
- if dir != "" {
- oppDir = world.OppositeExit[dir]
- } else {
+ if dir == "" && roomB != nil {
for _, d := range world.ExitOrder {
if exit, ok := roomB.Exits[d]; ok && exit.Room == body.From {
oppDir = d
@@ -505,49 +537,58 @@ func (s *AdminServer) handleRoomLink(w http.ResponseWriter, r *http.Request) {
}
}
- if dir == "" && oppDir == "" {
- writeJSONError(w, "no exit found between these rooms", http.StatusNotFound)
- return
- }
-
- if roomA.Exits != nil {
+ if roomA != nil && roomA.Exits != nil {
delete(roomA.Exits, dir)
}
- if roomB.Exits != nil {
+ if roomB != nil && roomB.Exits != nil {
delete(roomB.Exits, oppDir)
}
- pathA, okA2 := s.world.GetRoomPath(body.From)
- pathB, okB2 := s.world.GetRoomPath(body.To)
- if !okA2 || !okB2 {
- writeJSON(w, map[string]any{"error": "room path not found"})
- return
- }
+ var pushEntries []ChangeDesc
- oldA, _ := snapshotFile(pathA)
- oldB, _ := snapshotFile(pathB)
- newA, err := writeYAMLFile(pathA, roomA)
- if err != nil {
- writeJSON(w, map[string]any{"error": "write A: " + err.Error()})
- return
+ if roomA != nil {
+ pathA, okA2 := s.world.GetRoomPath(body.From)
+ if !okA2 {
+ writeJSON(w, map[string]any{"error": "room A path not found"})
+ return
+ }
+ oldA, _ := snapshotFile(pathA)
+ newA, err := writeYAMLFile(pathA, roomA)
+ if err != nil {
+ writeJSON(w, map[string]any{"error": "write A: " + err.Error()})
+ return
+ }
+ pushEntries = append(pushEntries, ChangeDesc{
+ Description: fmt.Sprintf("unlink %d %s %d", body.From, dir, body.To),
+ FilePath: pathA,
+ OldContent: oldA,
+ NewContent: newA,
+ })
+ }
+
+ if roomB != nil {
+ pathB, okB2 := s.world.GetRoomPath(body.To)
+ if !okB2 {
+ writeJSON(w, map[string]any{"error": "room B path not found"})
+ return
+ }
+ oldB, _ := snapshotFile(pathB)
+ newB, err := writeYAMLFile(pathB, roomB)
+ if err != nil {
+ writeJSON(w, map[string]any{"error": "write B: " + err.Error()})
+ return
+ }
+ pushEntries = append(pushEntries, ChangeDesc{
+ Description: fmt.Sprintf("unlink %d %s %d (reverse)", body.To, oppDir, body.From),
+ FilePath: pathB,
+ OldContent: oldB,
+ NewContent: newB,
+ })
}
- newB, err := writeYAMLFile(pathB, roomB)
- if err != nil {
- writeJSON(w, map[string]any{"error": "write B: " + err.Error()})
- return
+
+ for _, entry := range pushEntries {
+ s.undoStack.Push(entry)
}
- s.undoStack.Push(ChangeDesc{
- Description: fmt.Sprintf("unlink %d %s %d", body.From, dir, body.To),
- FilePath: pathA,
- OldContent: oldA,
- NewContent: newA,
- })
- s.undoStack.Push(ChangeDesc{
- Description: fmt.Sprintf("unlink %d %s %d (reverse)", body.To, oppDir, body.From),
- FilePath: pathB,
- OldContent: oldB,
- NewContent: newB,
- })
writeJSON(w, map[string]any{"ok": true})
default:
@@ -631,12 +672,19 @@ func (s *AdminServer) handleRoomRename(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]any{"error": "room not found"})
return
}
+
+ if _, ok := s.world.GetRoomPath(body.NewID); ok {
+ writeJSON(w, map[string]any{"error": fmt.Sprintf("room %d already exists", body.NewID)})
+ return
+ }
+
dir := filepath.Dir(oldPath)
newPath := filepath.Join(dir, strconv.Itoa(body.NewID)+".yaml")
if _, err := os.Stat(newPath); err == nil {
writeJSON(w, map[string]any{"error": fmt.Sprintf("room %d already exists", body.NewID)})
return
}
+
data, err := os.ReadFile(oldPath)
if err != nil {
writeJSON(w, map[string]any{"error": "read: " + err.Error()})
@@ -650,10 +698,41 @@ func (s *AdminServer) handleRoomRename(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]any{"error": "remove old: " + err.Error()})
return
}
+
s.world.RebuildRoomIndex(s.dataDir)
s.world.ClearRoomState(body.ID)
+
+ allIDs, _ := listRoomIDs(s.dataDir)
+ var exitUpdates int
+ for _, otherID := range allIDs {
+ if otherID == body.NewID {
+ 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 || exit.Room != body.ID {
+ continue
+ }
+ exit.Room = body.NewID
+ otherRoom.Exits[dir] = exit
+ changed = true
+ }
+ if changed {
+ otherPath, pathOk := s.world.GetRoomPath(otherID)
+ if pathOk {
+ writeYAMLFile(otherPath, otherRoom)
+ exitUpdates++
+ }
+ }
+ }
+
s.undoStack.Push(ChangeDesc{
- Description: fmt.Sprintf("rename room %d to %d", body.ID, body.NewID),
+ Description: fmt.Sprintf("rename room %d to %d (updated %d exits)", body.ID, body.NewID, exitUpdates),
FilePath: oldPath,
NewFilePath: newPath,
OldContent: data,