星露谷联机 bug “这个角色属于另一位玩家” 解决方案

0. 发现问题

前几天联机的时候发现了一个 bug : 联机后的第二天再次联机时,无法选择之前创建的角色,会弹出 “这个角色属于另一位玩家” 的提示(当时是拍屏,就不放图了)

1. 解决方案

打开目录 C:\Users\你的用户名\AppData\Roaming\StardewValley\Saves ,打开你的存档所在的文件夹,找到那个和文件夹名字一样的文件(不是 SaveGameInfo ,也不以 _old 结尾),编辑它(可以使用 VS Code ,也可以用记事本)。

Ctrl+F ,输入 userID ,找到类似这样的内容:

<userID>1145141919810</userID>

将这一段整体替换成 <userID />

然后寻找下一处,把所有这种带数字的都替换掉。替换完全部后,保存,重开游戏,解决。

这种解决方案并不稳定,似乎有概率复现,更强大的解决方案见下一小节:

2. 终极方案

写了个程序自动解决这个问题:

源码解析

获取当前用户的工作路径:

auto home_path = std::string{std::getenv("USERPROFILE")};

扫描存档文件夹的所有存档:

auto reg_find = std::regex{R"(^(?!SaveGameInfo)(?!.*(_old|\.vdf|\.bak)$).+$)"};
auto path     = std::format(R"({}\AppData\Roaming\StardewValley\Saves)", home_path);
auto saves    = std::vector<fs::path>{};
for (auto& dir_entry : fs::recursive_directory_iterator(path)) {
    if (!dir_entry.is_regular_file()) {
        continue;
    }
    if (!regex_match(dir_entry.path().filename().string(), reg_find)) {
        continue;
    }
    saves.emplace_back(dir_entry.path());
}

修复存档:

for (auto&& path : saves) {
    auto reg_fix  = std::regex{R"(<userID>\d*</userID>)"};
    auto bak_path = format("{}.bak", path.string());
    fs::copy_file(path, bak_path, fs::copy_options::overwrite_existing);

    using is_it = std::istreambuf_iterator<char>;
    using os_it = std::ostreambuf_iterator<char>;

    auto fin = std::ifstream{bak_path};
    auto beg = is_it{fin};
    auto end = is_it{};
    auto ctx = std::string{beg, end};

    auto fout = std::ofstream{path};
    auto it   = os_it{fout};

    std::regex_replace(it, ctx.begin(), ctx.end(), reg_fix, "<userID />");
}

在这里找到全部的源代码: Github Repo