迁移地图数据
问道把「在哪个世界画了什么」记在 config/howtogo/ 下,而目录名是由世界名或服务器地址
算出来的,不是你随手起的名字。所以一改世界名、一换服务器地址、一搬游戏实例,
数据不会自己跟过去——它没有丢,只是模组按新名字去找,没找到。
0.2.2 起这条规则变了一个地方:中文世界名不再变成一串下划线,而是转成拼音
(sp_新世界 → sp_xin_shi_jie);升级时旧目录会自己改名过去,
但降级回去会读不到。这一页讲目录名怎么算、哪些操作其实不用搬、要搬的时候按什么顺序做;
「改名之后路没了」的常见情况都能在这里找回。如果你只是想把一整个世界搬到另一台电脑或发给朋友,
0.2.2 也提供了用压缩包整份导出、导入的办法,见用压缩包搬家。
这里说的是问道自己的数据——路网、地点与公共交通线路;
Xaero 世界地图自己的缓存不在 config/howtogo/ 里,也不该在这里搬。
一句话:名字决定目录,记录决定归属。要搬数据,先让新名字把目录建出来,再把旧目录里的
.json 复制进去——.world 标记留给游戏自己写。0.2.2 起中文名先转拼音;
想整份搬走,也可以直接用压缩包(见用压缩包搬家)。
数据在哪,目录名怎么来的
所有数据都在你这个游戏实例的 config/howtogo/ 下。官方启动器就是
.minecraft/config/howtogo/;用 PCL、HMCL 这类启动器时,是那个实例的「游戏目录」下的
config(开了版本隔离则在对应版本目录里),不是启动器自己的安装目录。
别去存档的 saves 目录里找:联机时客户端读不到服务器存档,所以问道从一开始就把数据放在
config 里,而不是存档旁边。
config/howtogo/ 下再按世界分目录。世界的标识由两样东西算出来:
单人存档用世界名(level.dat 里的 LevelName,就是选存档界面里
显示的那个名字),多人服务器用服务器地址(你填进服务器列表的那一串,不是它上面的显示名)。
算出来的 key 前面再加上 sp_ 或 mp_:
| 你在游戏里看到的 | 世界名(key) | config/howtogo/ 下的目录 |
|---|---|---|
| 单人存档,世界名「新世界」 | sp_新世界 |
sp_xin_shi_jie |
| 单人存档,世界名「江南」 | sp_江南 |
sp_jiang_nan |
| 单人存档,世界名「My World」 | sp_My World |
sp_My_World |
服务器地址填 mc.example.net |
mp_mc.example.net |
mp_mc.example.net |
服务器地址填 mc.example.net:25565 |
mp_mc.example.net:25565 |
mp_mc.example.net_25565 |
算目录名分两步。第一步把中文转成拼音:汉字逐字转写、去掉声调,音节之间留一个空格——
新世界 变成 xin shi jie。第二步只保留 A-Z、a-z、
0-9、.、_、-,其余每个字符各换成一个下划线——
拼音里的空格于是成了分隔用的下划线,sp_新世界 就成了 sp_xin_shi_jie。
纯 ASCII 的名字(英文世界名、服务器地址)不做拼音转写,原样进入第二步:
空格、冒号仍然换下划线。所以对 sp_My World → sp_My_World、
mp_mc.example.net:25565 → mp_mc.example.net_25565 这类名字,
结果和旧版本完全一样。这是 0.2.2 的破坏性变更:
以前中文世界名是纯按字符替换,有几个字就有几个下划线,sp_新世界 是 sp____;
现在换成拼音,既能一眼认出是哪个世界,也让「新世界」和「旧世界」不再指向同一个目录。
名字特别长时会截断到文件系统能接受的长度,剩下的靠短哈希区分。
每个世界目录里再按维度分文件。维度名不参与拼音转写,仍然是老规则:
: 换成下划线,所以 minecraft:overworld 就是 minecraft_overworld。
这是故意的——如果让维度名也跟着转,冒号会被 ICU 改成「冒号加空格」,
文件名就变成了 minecraft__overworld.json,已有路网看起来就像「消失」了。
目录名是给人看的,文件名是模组找自己数据用的,两套规则各管一件事:
| 维度 id | 文件名前缀 |
|---|---|
minecraft:overworld(主世界) |
minecraft_overworld |
minecraft:the_nether(下界) |
minecraft_the_nether |
minecraft:the_end(末地) |
minecraft_the_end |
模组维度,例如 mymod:sky |
mymod_sky |
| 文件 | 内容 |
|---|---|
<维度>.json |
道路网络:节点、路段、道路名称、地点与地点类型。 |
<维度>-lines.json |
公共交通线路:线路名、类型、按顺序的站点。 |
<维度>-rail-names.json |
自动识别铁路的名称(按路段两端坐标记,所以能跟着铁路图层重建)。 |
每个世界目录里还有一个没有扩展名的 .world 文件,内容是「这个目录属于哪个世界」——
写的是原始的世界 key(例如 sp_新世界、sp_My New World,
中文、空格、大小写都原样保留),不是目录名。0.2.1 起就有这个文件;
0.2.2 起它是目录归属的依据:模组先找记录对得上的目录,名字不对就把它改名到算出来的名字,
实在改不了才继续用旧名字——数据跟着记录走,不跟着名字走。
它同时负责区分撞车的名字:两个不同的世界名转写、清洗后相同(例如只差一个标点——A/B 与
A B 都是 A_B;或者长名字截断后前缀相同),后来者会得到
<目录名>-<短哈希>,不会读到别人的路。拼音让「江南」和「江北」这类
同字数的中文名不再撞车(sp_jiang_nan 与 sp_jiang_bei)。
0.2.2 之前留下的目录(0.2.1 的有记录、名字还是下划线;更早的没有记录、靠旧名字认领)
都会在第一次被打开时改名到拼音名,见下一节。
config/howtogo/ 根目录下还有几个与存档无关的文件:
route_preferences.json(上次选的出行偏好与语音开关)、
map_filter.json(地图显示面板的开关与位置)、
mtr_line_marks.json(MTR 线路的逐条轨道标记)。它们不属于任何一个世界,
搬单个世界时不用动;完整清单见 配置与数据文件。
另外根目录下还有两个传输目录:exports/(我的导出)与
backups/(导入前的自动备份),见用压缩包搬家。
升级到 0.2.2:目录会自己改成拼音名
升级不需要做任何事。第一次打开某个世界时,问道按新规则算出拼音目录名,然后看两件事:
- 已经有记录、且
.world内容正是这个世界的目录:只要它的名字还是旧规则算的, 就整目录改名到拼音名,文件跟着走。0.2.1 留下的sp____就是这样变成sp_xin_shi_jie的;名字已经对上的则原地不动。 - 更早的、没有
.world的目录:如果它的名字正好是旧规则算出来的 (中文全是下划线),它就是这个世界的老目录,同样整目录改名到拼音名,并补上记录。
两种情况都有兜底:拼音名已经被别的世界占用、或改名失败时,旧目录继续用,
只补一个 .world 记录——「一个世界不能因为目录名改不好就丢掉它的路」。
所以升级后如果看到目录名没变,不必手动改,它照常能读到。
风险在降级。用 0.2.2 存过档以后再退回 0.2.1,旧版本按老规则(中文全是下划线)
去找目录,找不到拼音名,那个世界的路网就是空的——文件还在,只是没人读。
要退版本,先在 0.2.2 里导出压缩包(见用压缩包搬家)或复制整个
config/howtogo/,再把 JSON 放进旧规则会读的目录。
哪些操作要搬,哪些不用
先分清一件事:问道认的是世界名,不是存档文件夹名。
世界名存在 level.dat 里,改文件夹不会改它。
| 操作 | 数据会怎样 | 要做什么 |
|---|---|---|
在 saves/ 里把存档文件夹改名(level.dat 不动) |
世界名没变,目录也没变,照常读到 | 什么都不用做 |
改世界的显示名(level.dat 里的 LevelName;有些工具的重命名会连它一起改) |
它会去找按新名字算出的目录(旧目录不会自动跟过去) | 按下面「搬运步骤」搬 |
| 在服务器列表里改「服务器名称」 | 只是显示名,地址没变 | 不用搬 |
| 改服务器地址、域名、端口,或从 IP 换成域名 | 目录从 mp_旧地址 换成 mp_新地址 |
按下面「搬运步骤」搬 |
| 换电脑、换整合包、换游戏实例 | 数据还在旧实例的 config 里 | 复制整个 config/howtogo/ |
| 复制存档做备份,然后打开了副本 | 两个世界名相同,共用同一份数据 | 想让副本独立就先改名再搬 |
| 更新模组、删掉模组 jar | 文件原样保留;升级到 0.2.2 时目录名会在第一次打开时改成拼音 | 不用搬(升级自动改名;降级见上一节) |
两个世界名一字不差时,问道分不开它们,会共用同一个目录——这是它唯一
不打算区分的撞车。名字不同、但转写清洗后相同的(只差标点,或长名字截断到同一前缀)
由 .world 与短哈希处理,不需要你动手。所以「两个不同的存档共用了路」只可能是同名;
如果确实不同名却共用,那个目录大概是 0.2.2 之前留下、还没被新版本打开过(没有 .world 记录)。
搬运步骤:备份 → 先建新目录 → 只复制 JSON
下面这套顺序适用于所有人手搬运的场景(改世界名、换服务器地址、换电脑), 不要反过来做。单纯升级到 0.2.2 不用做这些——目录会自己改名:
- 备份。把整个
config/howtogo/复制一份到桌面或别的盘。 这里没有校验和、也没有自动备份,复制是唯一的后悔药。 - 完全退出游戏。修改会在停手约 3 秒后自动写盘,离开世界时还会再存一次; 游戏开着时替换文件,退出时可能被内存里的旧路网写回去。
- 用新名字进一次目标世界(或目标服务器)。这一步会让问道按新名字建好目录、
写好
.world。地图上会空无一物,这是正常的——它现在找的是新目录。 - 再退出游戏,打开
config/howtogo/。旧目录还在,新目录已经出现。 - 把旧目录里的
.json复制到新目录。包括<维度>.json、<维度>-lines.json、<维度>-rail-names.json。不要复制.world, 也不要动根目录那几个文件。 - 进游戏验证。地图上应该有路、地点与线路;可选
/howtogo webmap再/howtogo webmap status,状态行里的sp_.../mp_...就是现在认的世界;/howtogo selftest的「世界数据」一项也会把路网读一遍。
只有同一维度的文件会互相覆盖:旧世界的主世界文件对上新世界的
minecraft_overworld.json,下界、末地同理;旧世界没有的维度不用管,
新目录里也就不会有那个文件。
场景一:世界改名
单人存档的目录由 sp_<世界名> 算出来。再强调一次:世界名是
level.dat 里的名字,不是 saves/ 下的文件夹名。
只改文件夹不用搬;改了世界名才需要。
- 新名字是英文时,目录通常是
sp_NewName(空格换下划线)。 - 新名字是中文时,目录是拼音:例如「新世界」→
sp_xin_shi_jie、 「江南」→sp_jiang_nan。 - 拼音名先到先得:如果新名字转写出来正好是另一个世界占着的目录名,问道会给新世界一个
<拼音名>-<短哈希>目录,把数据搬到那个目录里。 - 操作就是上一节的六步:进一次新世界 → 退出 → 把旧目录的 JSON 复制进新目录。
- 反悔很容易:旧目录没有被删,把 JSON 复制回去、或者把世界名改回去即可。
场景二:服务器地址变了
多人目录是 mp_<服务器地址>,取的是你在「服务器地址」框里填的那串字符:
域名、IP、端口都算,大小写也算;: 会被换成下划线。例如填
mc.example.net:25565,目录是 mp_mc.example.net_25565。
服务器列表里那个「服务器名称」不参与目录名,改它没有影响。
服务器地址是纯 ASCII,0.2.2 的拼音规则不影响它——这里的规则和以前完全一样。
换地址(换域名、换端口、从 IP 换成域名、合租服换了入口)时,按通用步骤做:
用新地址进一次服务器让 mp_新地址 出现,退出,把 mp_旧地址 里的
JSON 复制进去。反过来也一样:把地址改回旧的那串,旧目录立刻又能读到。
如果两个地址下都已经有路(你在两个地址都玩过),问道没有合并功能: 同一维度只有一个 JSON,后复制的覆盖先复制的。先各自备份,再决定以哪份为准, 缺的那部分只能补画。
场景三:换电脑、换整合包、给朋友
数据是客户端本地的,不跟着存档走,也不跟着服务器走。换电脑、换整合包、
换游戏实例时,把整个 config/howtogo/ 复制到新实例的同一位置即可:
目录名、.world 都照原样过去,游戏目录的绝对路径变了也没关系——
问道只认 config 下的相对结构。
只搬一个世界,也可以只复制对应的 sp_... / mp_... 目录:
世界名没变、.world 也对得上,放进去就能读。如果目标实例里已经有同名世界目录,
就按「搬运步骤」只复制 .json,别覆盖它的 .world。
想把客户端设置也带走,再加上 config/howtogo-client.toml。
route_preferences.json、map_filter.json、mtr_line_marks.json
都在 config/howtogo/ 里,会跟着整个目录一起走。
给朋友同理:打包 config/howtogo/ 发过去,解压到他游戏目录的 config/ 下。
最好两边用同一个模组版本;跨大版本搬之前先备份。真的读不回来时(例如文件被改坏),
道路文件会被改名为 .corrupt 放到一边,不会静默消失。
更省事的是用压缩包:在旧实例里导出 .zip 发给对方,他打开对应世界后导入即可
(见用压缩包搬家)——他不用关心目录名怎么算,也不用改任何文件名。
场景四:复制存档以后,两个世界共用一份路
把存档文件夹复制一份,两个世界的 LevelName 通常还是同一个,
所以问道看它们是同一个世界,读写同一个数据目录。在副本里画的路,原世界也看得见;
反过来也一样。这不是 bug,是「按世界名区分」这条规则直接推出来的结果。
想让副本拥有独立的数据,可以这样拆开:
- 退出游戏,先备份当前共用的那个数据目录。
- 给副本改一个世界名(改
level.dat里的LevelName;只改文件夹名没有用), 让两个世界的 key 不同——中文名会得到一个新的拼音目录。 - 打开改名后的副本一次,让它建立自己的新目录,然后退出。
- 把原目录里的 JSON 复制到副本的新目录。此后的修改就各记各的了。
用压缩包搬家
0.2.2 新增了「地图存档」界面:/howtogo data 打开它,一个按钮把当前世界的道路、地点、
铁路名称、公共交通线路与附属数据打成一个 .zip 放进 config/howtogo/exports/;
另一个按钮把别人的 .zip 导入回来。指令也能做同样的事:/howtogo export 直接导出,
/howtogo import [压缩包] 读指定文件;压缩包也可以直接拖进那个界面。
它的好处是不用碰目录名:导出的是「这个世界的数据」,导入的是「你现在打开的世界」, 中间那套世界名 → 拼音目录名的算法完全不用管。换电脑、给朋友、整份备份都适用。
导出与导入各做了什么
- 导出只打包当前世界目录里的数据文件,不碰
config/howtogo/根目录那几个偏好文件, 也不碰别的世界。 - 导入无视压缩包名与内部目录名:目录层级被剥掉,包里的
.world记录改写成当前世界, 数据写进当前世界的目录——所以收到别人发来的包,打开自己的世界导入就行。 - 覆盖前有警告:写明写进哪个世界、来源与时间、文件数、旧数据会先备份。
确认后先备份到
config/howtogo/backups/,再整目录替换。 - 是替换,不是合并:包里没有的维度文件会被删掉。两份数据都想留,得先各自备份、选定一份, 缺的部分重画。
- 备份能一键回滚:自动备份的文件名带
-backup,在「可导入的压缩包」列表里单独标黄, 再导入它一次就回到导入之前。 - 替换是一次目录改名:新数据先在旁边建好再改名到位;旧目录先改名成
<存档>.replaced-<时间>,删掉它的.world记录后再删除—— 万一删不掉,留下来的目录也不会冒充当前世界的数据。
它只接受认识的文件
导入时只读 .json:__MACOSX/、.DS_Store、.world、
*.part、*.corrupt 会被跳过;带 .. 或绝对路径的条目不跟随;
文件数与解压总大小有上限;没有任何可读数据的包会被直接拒绝,当前地图不动。
列表里的来源分三种:导入文件夹、我的导出、备份。
自检里也多了一项「地图存档压缩包」——它真的导出、导入一次并逐字节核对。
压缩包是整目录替换,适合「整份搬走 / 整份恢复」。如果你只想把主世界的几份 JSON
挪到另一个实例、又不想动那个世界原有的数据,仍然用上面的「搬运步骤」只复制 .json。
手工改目录名,与 .world 的坑
先记住一条:目录名不是自由命名的。它是按世界 key 算出来的(中文转拼音、其余非法字符换下划线),
而 0.2.2 起真正决定归属的是目录里的 .world 记录。
所以手工改名字通常不会丢数据——模组会按记录把目录找回来,并在下次打开时把它改回按名字算出的那个。
但没有好处,而且改名过程中如果目标名字已被占用,它会停在旧名字上,白折腾一趟。
0.2.2 的规则是「记录优先」:先找 .world 内容等于当前世界 key 的目录,
找到就用它(名字不对就改名);找不到记录,才按名字算、并按旧规则兜底认领。由此有三条:
- 推荐:按「搬运步骤」来,让游戏自己建目录、自己写
.world,你只复制.json。 - 不要删
.world:删掉以后目录就「没有归属」了。它的名字如果正好是旧规则算出来的 (中文全是下划线),第一个打开的世界会认领它;如果它是拼音名,问道不会自动认领 (那可能是别的世界改名后留下的旧数据),宁可为当前世界另建一个带短哈希的目录—— 看起来就是「数据还在,但没了」。 - 整个目录改名可以,但没必要:带记录的目录改名后能被找回来; 更稳的做法是别动它,想要一个好看的名字就在游戏里改世界名。
目录名后面带一段 -1a2b3c4d 这样的短哈希,不是坏了,是「这个名字已经被另一个世界认领了」。
短哈希由世界名算出来,同一个名字每次算出的后缀都一样,所以它不会天天变。
想知道哪个目录是游戏正在用的,看每个目录里的 .world:内容等于当前世界 key 的那一个才是。
用不到的哈希目录可以备份后删掉,但别在没确认之前删。
出错了怎么找回
改名后进游戏,路全没了——数据丢了吗?
通常没丢。新目录是空的,旧目录还完整地待在旁边。退出游戏,按「搬运步骤」把旧目录里的
.json 复制进新目录即可。注意先别在新世界继续画:复制旧文件会覆盖同名的道路文件,
如果已经画了新路,先把新文件备份出来再决定留哪份。
单纯升级到 0.2.2 不会遇到这种情况——旧目录会自动改名到拼音名; 这一条说的是你手工改了世界名、换了服务器地址之后。
为什么多了一个带短哈希后缀的目录?
名字撞车了:另一个世界已经占着不带哈希的那个目录名。0.2.2 里常见的是「转写清洗后相同」——
两个名字只差一个标点(A/B 与 A B),或者长名字截断到同一前缀。
看两个目录里的 .world,把「属于当前世界」的那一个作为目标,数据搬进去。
旧的那份先留着,确认不需要再删。
我把整个文件夹复制过去了,为什么还是读不到?
多半是把旧的 .world 也一起复制了。它写着旧世界名,游戏因此认为这个目录属于别人,
转而新建了一个哈希目录。保留目标目录自己的 .world,只复制 .json;
拿不准的话,就按「搬运步骤」让游戏自己把目录建出来。
两个不同名字的世界,却共用同一份路?
先确认「不同名字」是不是只改了存档文件夹。文件夹名的不同不改变世界名;两个世界名完全一样时,
共用是预期的(见场景四)。转写清洗后相同的名字会各自得到短哈希目录,不会共用;
如果确实不同名却共用,那多半是 0.2.2 之前留下的旧目录还没被新版本打开过(没有 .world 记录),
升级后第一次打开时就会按记录分开。
数据能合并吗?
不能自动合并。同一维度只有一个 <维度>.json,两张路网没有「取并集」的入口。
如果两边都有想保留的路,先各自备份,选一份作底,再把缺的路重画一遍。
想让整份数据直接替换,可以用压缩包导入——但那是替换,不是合并(见用压缩包搬家)。
目录里出现了 .part 或 .corrupt 文件
.part 是保存中途留下的半成品,正常退出后一般不会留着;
.corrupt 是道路文件读不回来时被改名放到一边的原文件,可能还能手工救回一部分。
两者都先别删,备份整份目录再排查。
几条规矩
- 先备份。复制整个
config/howtogo/;想把设置一起带走,再加config/howtogo-client.toml。只想整份搬走的话,导出压缩包更省事。 - 关游戏再动文件。路网会在停手后自动写盘、离开世界时再存一次, 开着游戏替换文件可能被旧数据盖回去。
- 复制
.json,不复制.world;不要整个文件夹覆盖。 - 0.2.2 起中文目录名是拼音。升级时旧目录会自动改名,不用管; 但用 0.2.2 存过档的别直接降级回 0.2.1——那边按老的下划线规则找目录,找不到。
- 服务器地址要一字不差。大小写、端口、写 IP 还是写域名,都算不同的世界。
- 数据只在客户端。服务器上没有你的路,换电脑不会自动同步,也不会从服务器下回来。
- 删模组 jar 不会删数据。反过来说,删掉
config/howtogo/才会; 误删先看回收站和之前的备份。