aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_room_insert_remove.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/api_room_insert_remove.go')
-rw-r--r--internal/admin/api_room_insert_remove.go54
1 files changed, 3 insertions, 51 deletions
diff --git a/internal/admin/api_room_insert_remove.go b/internal/admin/api_room_insert_remove.go
index 5f03b72..36688dc 100644
--- a/internal/admin/api_room_insert_remove.go
+++ b/internal/admin/api_room_insert_remove.go
@@ -5,11 +5,9 @@ import (
"net/http"
"os"
"path/filepath"
- "regexp"
"strconv"
"strings"
- "gopkg.in/yaml.v3"
"thehouseoficarus/internal/behavior"
"thehouseoficarus/internal/persistence"
"thehouseoficarus/internal/world"
@@ -261,7 +259,7 @@ func (s *AdminServer) handleRoomRemove(w http.ResponseWriter, r *http.Request) {
return
}
// Guard 5: no extra inbound edges to B.
- if extra := s.countExtraInbound(bID, aID, cID, dir, oppositeDir); extra > 0 {
+ if extra := world.CountExtraInbound(s.dataDir, bID, aID, cID, dir, oppositeDir); extra > 0 {
writeJSONError(w, fmt.Sprintf("cannot remove: %d other exit(s) point into %s (it was modified since insertion)", extra, bLabel), http.StatusBadRequest)
return
}
@@ -418,51 +416,5 @@ func (s *AdminServer) formatGridConflicts(cs []world.GridConflict, mode string)
return "cannot " + verb + ": " + strings.Join(parts, "; ")
}
-// countExtraInbound mirrors Game.countExtraInbound for the admin API: it
-// counts exits in rooms other than A and C that point into B, plus any A/C
-// exits to B other than the expected (A→dir→B, C→oppositeDir→B). It walks
-// data/rooms/ and matches \b<id>\b against raw file contents to skip rooms
-// that don't mention bID at all, then unmarshals only the matching files.
-func (s *AdminServer) countExtraInbound(bID, aID, cID int, dir, oppositeDir world.ExitDir) int {
- roomsDir := filepath.Join(s.dataDir, "rooms")
- re := regexp.MustCompile(fmt.Sprintf(`\b%d\b`, bID))
- var extra int
- _ = filepath.WalkDir(roomsDir, func(path string, d os.DirEntry, err error) error {
- if err != nil || d.IsDir() || filepath.Ext(path) != ".yaml" {
- return nil
- }
- data, rerr := os.ReadFile(path)
- if rerr != nil {
- return nil
- }
- if !re.MatchString(string(data)) {
- return nil
- }
- idStr := strings.TrimSuffix(filepath.Base(path), ".yaml")
- rid, serr := strconv.Atoi(idStr)
- if serr != nil || rid == bID {
- return nil
- }
- var room world.Room
- if yerr := yaml.Unmarshal(data, &room); yerr != nil {
- return nil
- }
- if room.Exits == nil {
- return nil
- }
- for ed, exitDef := range room.Exits {
- if exitDef.Room != bID {
- continue
- }
- if rid == aID && ed == dir {
- continue
- }
- if rid == cID && ed == oppositeDir {
- continue
- }
- extra++
- }
- return nil
- })
- return extra
-}
+// countExtraInbound was moved to world.CountExtraInbound so the in-game and
+// admin removal paths share one implementation.