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 or swapid ") 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))) }