aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_swapid.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-28 02:40:30 -0400
committerhistoria <[not public]>2026-06-28 02:40:30 -0400
commita1b6613c6c6a2f8d6e1ecd47e766bd40f92ac295 (patch)
tree4ff8fefb029c93f2aa3db7361658b0b4e9805b66 /internal/game/cmd_swapid.go
parent87dacfbb3dd16e7f55a82361eace98f9a39d75c8 (diff)
downloadthehouseoficarus-a1b6613c6c6a2f8d6e1ecd47e766bd40f92ac295.tar.gz
feat: admin accounts, god mode, OLC commands like dig/room, 'inline' objects changed to 'local' objects
Diffstat (limited to 'internal/game/cmd_swapid.go')
-rw-r--r--internal/game/cmd_swapid.go126
1 files changed, 126 insertions, 0 deletions
diff --git a/internal/game/cmd_swapid.go b/internal/game/cmd_swapid.go
new file mode 100644
index 0000000..6ee1118
--- /dev/null
+++ b/internal/game/cmd_swapid.go
@@ -0,0 +1,126 @@
+package game
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strconv"
+
+ "thehouseoficarus/internal/net"
+)
+
+func (g *Game) executeSwapID(sess *net.Session, args []string, rawInput string) {
+ if !g.checkAdmin(sess) {
+ sess.WriteLine("Unknown command.")
+ return
+ }
+ p := sess.Player
+ if p == nil {
+ return
+ }
+
+ var id1, id2 int
+ switch len(args) {
+ case 1:
+ id1 = p.RoomID
+ var err error
+ id2, err = strconv.Atoi(args[0])
+ if err != nil {
+ sess.WriteLine("Invalid room ID.")
+ return
+ }
+ case 2:
+ var err error
+ id1, err = strconv.Atoi(args[0])
+ if err != nil {
+ sess.WriteLine("Invalid room ID.")
+ return
+ }
+ id2, err = strconv.Atoi(args[1])
+ if err != nil {
+ sess.WriteLine("Invalid room ID.")
+ return
+ }
+ default:
+ sess.WriteLine("Usage: swapid <id> or swapid <id1> <id2>")
+ return
+ }
+
+ if id1 == id2 {
+ sess.WriteLine("Cannot swap a room with itself.")
+ return
+ }
+
+ path1, ok1 := g.World.GetRoomPath(id1)
+ path2, ok2 := g.World.GetRoomPath(id2)
+ if !ok1 {
+ sess.WriteLine(fmt.Sprintf("Room %d not found.", id1))
+ return
+ }
+ if !ok2 {
+ sess.WriteLine(fmt.Sprintf("Room %d not found.", id2))
+ return
+ }
+
+ roomsDir := filepath.Join(g.DataDir, "rooms")
+ re1 := regexp.MustCompile(fmt.Sprintf(`\b%d\b`, id1))
+ re2 := regexp.MustCompile(fmt.Sprintf(`\b%d\b`, id2))
+ placeholder := fmt.Sprintf("__SWAPID_TEMP_%d__", id1^id2)
+
+ var modified []string
+ err := filepath.WalkDir(roomsDir, func(roomPath string, d os.DirEntry, err error) error {
+ if err != nil || d.IsDir() || filepath.Ext(roomPath) != ".yaml" {
+ return nil
+ }
+ data, rerr := os.ReadFile(roomPath)
+ if rerr != nil {
+ return nil
+ }
+ text := string(data)
+ if !re1.MatchString(text) && !re2.MatchString(text) {
+ return nil
+ }
+ text = re1.ReplaceAllString(text, placeholder)
+ text = re2.ReplaceAllString(text, strconv.Itoa(id1))
+ text = regexp.MustCompile(placeholder).ReplaceAllString(text, strconv.Itoa(id2))
+ if werr := os.WriteFile(roomPath, []byte(text), 0644); werr != nil {
+ return werr
+ }
+ modified = append(modified, roomPath)
+ return nil
+ })
+ if err != nil {
+ sess.WriteLine(fmt.Sprintf("Error updating room files: %v", err))
+ return
+ }
+
+ tempPath := path1 + ".swapid-tmp"
+ if rerr := os.Rename(path1, tempPath); rerr != nil {
+ sess.WriteLine(fmt.Sprintf("Error renaming room %d: %v", id1, rerr))
+ return
+ }
+ if rerr := os.Rename(path2, path1); rerr != nil {
+ os.Rename(tempPath, path1)
+ sess.WriteLine(fmt.Sprintf("Error renaming room %d: %v", id2, rerr))
+ return
+ }
+ if rerr := os.Rename(tempPath, path2); rerr != nil {
+ os.Rename(path2, path1)
+ os.Rename(tempPath, path1)
+ sess.WriteLine(fmt.Sprintf("Error finishing rename: %v", rerr))
+ return
+ }
+
+ g.World.RebuildRoomIndex(g.DataDir)
+ g.World.LoadRoom(id1)
+ g.World.LoadRoom(id2)
+
+ if p.RoomID == id1 {
+ p.RoomID = id2
+ } else if p.RoomID == id2 {
+ p.RoomID = id1
+ }
+
+ sess.WriteLine(fmt.Sprintf("Swapped room IDs %d and %d (%d files updated).", id1, id2, len(modified)))
+}