diff options
Diffstat (limited to 'internal/game/cmd_dig.go')
| -rw-r--r-- | internal/game/cmd_dig.go | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/internal/game/cmd_dig.go b/internal/game/cmd_dig.go index c58ba63..ff33490 100644 --- a/internal/game/cmd_dig.go +++ b/internal/game/cmd_dig.go @@ -127,7 +127,7 @@ func (g *Game) executeDig(sess *net.Session, args []string, rawInput string) { return } - newID, err := findNextRoomID(curPath) + newID, err := findNextRoomID(filepath.Dir(curPath), g.World.RoomIndex()) if err != nil { sess.WriteLine("Error scanning room directory.") return @@ -222,14 +222,22 @@ func (g *Game) executeDig(sess *net.Session, args []string, rawInput string) { g.checkAggro(sess) } -func findNextRoomID(currentRoomPath string) (int, error) { - dir := filepath.Dir(currentRoomPath) - entries, err := os.ReadDir(dir) +// findNextRoomID returns the first free room ID at or above localDir's +// minimum, checked against every room ID in the world (globallyUsed). The +// admin allocator (admin/id_alloc.go) does the same. A directory-scoped scan +// could hand out an ID that already exists in another area, and +// World.AddRoomPath would then silently shadow that room for the rest of the +// process while leaving a duplicate file on disk. +func findNextRoomID(localDir string, globallyUsed map[int]bool) (int, error) { + entries, err := os.ReadDir(localDir) if err != nil { return 0, err } - used := make(map[int]bool) + used := make(map[int]bool, len(globallyUsed)+len(entries)) + for id := range globallyUsed { + used[id] = true + } minID := 0 first := true for _, entry := range entries { @@ -248,11 +256,11 @@ func findNextRoomID(currentRoomPath string) (int, error) { } } - if first { - return 1, nil + start := 1 + if !first { + start = minID } - - for id := minID; ; id++ { + for id := start; ; id++ { if !used[id] { return id, nil } |
