它到底做了什么
当前版本 v0.2.2(预发布测试版),面向 Minecraft 1.20.1 – 26.3, Fabric 与 NeoForge 双平台,纯客户端。 一句话:把 Xaero 世界地图变成一张能规划、能导航的路网。 下面是全部功能,以及每一条背后的取舍——因为「为什么不那样做」往往比功能本身更重要。
画路与维护
在世界地图上直接画折线,六个等级:高速 / 公路 / 小路 / 铁路 / 水路 / 冰道。 颜色与线宽各不相同,一眼就能读出「这是快路还是小路」。下表是默认配色, 想让路网长成别的样子,可以在颜色可以自己定里改。
| 等级 | 颜色 | 标称宽度 | 谁会走 |
|---|---|---|---|
| 高速 | 亮蓝 | 7 格 | 步行、驾车 |
| 公路 | 绿 | 5 格 | 步行、驾车 |
| 小路 | 土黄 | 3 格 | 步行 |
| 铁路 | 橙 | 4 格 | 公共交通 |
| 水路 | 深蓝 | 6 格 | 公共交通(船) |
| 冰道 | 浅蓝 | 5 格 | 步行、公共交通 |
- 吸附:靠近已有节点或路段时自动吸附;按 Alt 自由放置。附近没有手画道路时, 会吸附到自动识别的铁轨上,让你把路正好接在铁轨上。
- 在路段中间落点会真正拆分路段,并在交点建立节点——拓扑是真的,不是看起来像。
- 画出来的是平滑曲线:路段额外带一份只用于显示的平滑折线,先按 0.9 格
容差抽稀(把一格一格的楼梯收成斜线),再对折角按固定 1.25 格半径做圆弧倒角,
首尾仍钉在道路两端。它只影响显示——寻路、测距、选中与存档里的整数顶点一行没动;
道路 JSON 里多一个可选的
curve字段,写了才出现,旧存档照常读,旧版本会忽略它。 - 命名:一条路(含所有转折段)共用一个名字。名字的字号不超过这条路画出来的宽度: 路太细(缩小的远景、小路、铁路)先不写名字,放大到够宽才出现——宽路字大、窄路字小,名字永远落在路面里。 很长的路会沿路每隔约 190 像素写一个(每段最多 8 个),只放在屏幕上的可见段里; 可见段比名字还短时这一段不写。
- 地点标记:四种类别(地点 / 资源点 / 商店 / 站点)。类别只影响显示与缩放取舍,不影响导航; 只有「站点」必须建在道路上。
- 撤销 / 重做 64 步;节点可以拖动,路段可以整体改等级或删除。
- 单行道:O 让选中(或光标所在)的那条路在 双向 / 顺向单行 / 逆向单行之间循环,地图上沿路画出箭头指明方向。 按整条街生效,弯道两侧方向一致,而且步行、驾车、公共交通都遵守它。
- 道路层直接加减:- / + 改的是接下来画在哪一层, 范围 −32 ~ +32,画隧道时按一下就下到地下 1 层,接着画的路都在那一层;当前层一直写在左下角的读数里。 它不动已经画好的路(改已有的路仍用 N 面板),也没有撤销记录——绘制层是一个模式,不写进存档。
- 右键拖地图:编辑模式里、地图上没有正在画的线时,按住右键拖动就是平移地图; 一旦开始画,右键还是「结束这条线」;右键单击不拖照旧清除选中。
- 选中的路会报出层与全长:Shift 选中后左下角读数是 「等级 · 方向 · 道路层 · 全长 N 格」。全长是整条路的——带弯的路在数据里是好几段,报的是它们加起来的总长。
- 把「看着连上」变成真的连上:两条路交叉而过、或差一格没接上,本来是不通的;
开启
repair_road_joins(默认开)会先把这种地方修好再规划。
画好的路在地图上按层叠放:从低层往高层画,高架压在自己跨过去的地面路之上、隧道在地面路之下, 同一层里先画完所有描边再画所有填充,所以路口看起来是一条路从另一条上跨过去。叠放与缩放的规则见 地图显示与缩放。
实时导航
三种交通方式走的道路不同,所以同一组起终点会得到不同的路线。 选好目的地、方式与偏好之后,路线先画在地图上给你看,确认了再出发。
| 交通方式 | 可走的等级 | 速度表(格 / 秒) |
|---|---|---|
| 步行 | 高速、公路、小路、冰道 | 4.0 ~ 5.6 |
| 驾车 | 高速、公路 | 公路 9 |
| 公共交通 | 铁路、水路、冰道 | 铁路 / 水路 8,冰道 40,另加等车时间 |
- 路线偏好:最快时间 ↔ 最短距离;可以避开某些等级(例如不想走水路); 可以「优先大路」——每类道路各有一个权重,只乘在搜索代价上(高速 1.0 / 公路 1.25 / 小路 1.8), 不影响报出来的时间与距离,两种度量走同一条计算。
- 先预览再出发:预览会显示目的地与预计时间;没有可走的连接时直说「没有可用的道路连接」。
- 不绕远、不拉直线:所选方式比走路更慢、或该方式无解时,会说明原因并改为按步行规划。
- 接驳段有上限:步行离开路面最多
walk_offroad_blocks(默认 32 格, 范围 0 ~ 4096),超出的目的地与路尽头直接判「没有路线」;驾车不再越野, 只允许「车还在路面上」的那点距离(最宽路面的半宽)——停在路边可以,停在田里不行; 公共交通只保留站台到轨道的接驳(station_snap_blocks,默认 32 格), 超过就没有这段车程,「全是接驳、没有一节在轨道上」的假乘车会被拒绝。 宁可报「没有路线」,也不画一条横穿地图的直线。 - 主界面(K):世界里按 K 打开,指令一个都不用记—— 标题下是一张只能看的地图(拖动平移、滚轮以光标为中心缩放,点它不会选点也不会开始导航)。 世界地图里按 K 不会触发(地图有自己的按键)。
- 走完最后一段,路线颜色不再倒回去:到达后整条按「已走」处理,不会整条重画成未走的颜色。
- 退出世界不会把上一局的导航带进下一局:世界卸载时就结束导航并写一行日志。
- 转向提示:HUD 显示转向箭头、剩余距离与时间、进度条;播报距离按路况缩放 (步行 50m、公路驾车 100m、高速驾车 300m、铁路 300m、冰道 500m)。
- 转弯判定要求朝向:与路口齐平时,只有大致转向该方向(≤45°)才算转过, 直行穿过路口不会被误判为「转过一个路口」。
- 语音播报(可选):转弯前、现在转弯、到达、偏离路线,使用 Minecraft 原版 TTS。
- 偏航重算:只有离开当前道路超过该等级的容差之后才重新规划,不会每走一步都重算。
公共交通线路
按线路走,而不是按「最近的车站」走。线路配置界面一屏三列:左列线路、中列站点顺序、 右列所有可加进来的站点——一条六站线路不该是十几次界面切换。
- 线路有自己的类型(铁路 / 水路 / 公路 / 冰道),决定它能在哪些道路上跑。 中列里接不上一站的站点会显示为红色,所以在保存之前你就能看见「这条线跑不通」。
- 线路按类型配色:四个类型各有一个颜色,改的是线路本身的线与它名下的每一个站点标记; 它下面的轨道仍按道路等级取色。默认值就是一直使用的配色,不配置时和以前一样,MTR 读进来的线路同样按类型取色。
- 站点有三个来源:自己标记的站点(可改)、机械动力车站(只读)、MTR 车站(只读)。 只读的理由很简单:它们的名字与类型属于那个模组,在这里改会得到一条描述着「不存在的车站」的线路。
- MTR 同名车站合并后,线路里同名的车站只停一次,换乘也按合并后的那个地点算; 合并规则见下面的 MTR 集成。
- 规划:站点是有向图的节点,相邻两站之间是边,用 Dijkstra 求最省时间或最短的走法。
- 没有可用线路就如实回答「没有公共交通路线」,不会假装成公交把你送到最近的一段轨道上。
- 等车时间:每次登乘计一次(首次乘车也算,换乘再计一次),同时参与搜索与预计时间。
- 换乘站:被两条及以上线路共用的站点会画成橙色方块,尺寸与普通站点相同; 只有屏幕上真的重叠时才融合成一个,拉近看就分开。
机械动力铁路(自动识别)
装了 Create,它的铁轨会自己出现在地图上,弯道是曲线而不是阶梯。数据优先来自 Create 自己的轨道网络, 读不到时回退为扫描轨道方块——两种来源同时只有一种生效,不会重复计数。
- 不引用任何 Create 类:靠方块注册名识别,所以 Create 改名或换版本不会让问道编译不过。
日志里的
[HowToGo] Create track layer:会告诉你当前用的是哪种来源。 - 曲线保留原采样:Create 的贝塞尔曲线与 MTR 的小数坐标轨道保留原采样再平滑, 不再先四舍五入到方块;平滑只影响显示,寻路用的顶点没有变。
- 短轨道先拼成长段:端点相接、类型相同的片段拼成「路口到路口」的长折线, 只有岔口(三条以上轨道交汇)和没接上的地方才断开——选中、命名、描边与寻路的边数都跟着变干净。
- 铁路只读,但可以命名:几何属于 Create,动了下一秒就被覆盖;名字是唯一可以改的东西, 存在单独的文件里,并且绑在路段两端坐标上,所以重建与重载都不会丢。
- 整条线一起操作:Shift 点击选中整条铁路线,N 命名时整条线共用一个名字。
- 车站就是目的地:Create 的车站会出现在目的地列表的「机械动力车站」一类里, 站名用玩家给车站起的名字。
- 画路时可以吸附到铁轨,把一条路的端点正好接上去;吸附只取位置,不会拆分铁路。
MTR 集成(自动识别)
装了 MTR(4.0.4 及以上),它的车站与线路会被读成问道自己的站点与公共交通线路: 列车与缆车算铁路,船算水路,其它类型(例如飞机)不猜、直接不处理。
- 读到过的都会被记住:MTR 发给客户端的数据可能只是一个窗口(联机时尤其如此),
问道把每次读到的合并记住,走出同步范围后线路不会凭空消失;
整图读取由
mtr_full_map(默认开)控制。 - 同名车站会合并:同名(忽略大小写与首尾空格)且候车点相距不超过
mtr_station_merge_blocks(默认 256 格)的车站合成一个地点—— 列表里一条、地图上一个标记、线路只停一次,位置取所有站台的中点。无名车站从不合并, 设成0就完全按 MTR 原样;站台认不出所属车站时按「不知道」处理,不再把孤儿站台凑到一起。 - 站点取站台的中点而不是车站区域中心——大站的中心离轨道很远,而车停的是站台。
- 每条线路可以自己决定要不要标记轨道。MTR 的协议里没有「这条线走哪段轨道」这个信息, 问道是反推的:对相邻站点对在 MTR 的轨道上规划一次,走过的轨道就是这条线实际走的轨道, 再以只读的铁路 / 水路道路标上去,让车程沿着 MTR 真正铺的轨道计算。
- MTR Map Overlay 的两个地图开关会被记住:它自己的「线路 / 轨道」开关以前每次开游戏都回到「都画」,
现在问道把它们记在
config/howtogo/mtr_overlay_toggles.json,改了立刻保存、下一局恢复; 它自己的配置文件不动,删掉这个文件就不再记。没装那个模组时整段功能不存在。 - 只读,但能拿走:MTR 的线路在列表里带
[MTR]标记, 按「复制为我的」就得到一份可以随意改的副本。
阡陌交通(RoadWeaver,自动识别)
装了阡陌交通,它自动生成的道路会被读进来、画在世界地图上、参与寻路, 它连接的村落与小屋成为目的地。整个读取是全反射的:没装、版本不合都不会崩。
- 路一律按「小路」读:它铺的是土 / 砂砾 / 木板,路宽表示的是「铺了几格」,不是「能不能开车」。
roadweaver_road_class仍可强制一个等级。 - 路口就是它自己说过的路口:两条路在同一个点才算连通;交叉而过、没有共享点位的不算(可能是立交,不猜)。 路尽头的缺口会补一条同等级的直线连接段(连到结构),画在地图上、参与寻路、随整层替换、不写回。
- 整张路网:单人 / 局域网时直接读它进程内的整个路网(
roadweaver_full_map,默认开), 不用先打开它自己的路网地图;联机在别人的服务器上时只读它发给客户端的那一份, 所以这一局要先按一次它的路网地图(H),之后广播的局部更新会让图层自己更新。 - 参与寻路:步行、驾车(强制成可开等级时)与公交的步行接驳段都会用到它
(
roadweaver_routing,默认开);关掉后照旧画在地图上,只是不参与规划。roadweaver_roads关掉整层,roadweaver_structures关掉结构目的地。 - 结构有别名:目的地列表、地图标签、导航提示都用它的别名,其次翻译名、可读 id。 编辑时可以吸附到它的路与结构上,但只吸位置——不拆分、不连接、不移动它的几何。
- 它从不被写回:这些道路、连接段与结构不写进自己的路网文件、不进编辑器、不随地图导出。
地图显示与缩放
左上角的「地图显示」面板可以逐个开关道路等级、地点类型与公共交通线路,面板本身可以拖着走、可以卷起。 面板是屏幕覆盖层,所以不会被地图画出来的线路、标记与文字盖住。
- 缩小地图时自动取舍:小路 → 公路 → 水路 → 铁路依次被舍去, 高速与冰道永不隐藏——缩小看地图,看的就是「哪儿有快路」。
- 道路按层叠放:路段从低层往高层画, 高架压在自己跨过去的那条地面路之上、隧道在地面路之下——一张平面俯视图里, 这是「谁在谁上面」唯一能画出来的方式。同一层里的先后不变, 浏览器地图与游戏里的地图走的是同一套层序。
- 同一层里先画完所有描边、再画所有填充, 所以十字路口看起来是一条路从另一条上跨过去,而不是两团颜色糊在一起; 单向箭头跟着本层的填充画,桥也盖得住桥下的箭头。
- 地点这边先舍商店,再舍站点,再舍普通地点,资源点最后才舍——它本来就是值得专程去的东西。
- 公共交通线路从不因为缩小而消失:它是地图上唯一不能由道路推出来的东西。
- 名字的字号不超过路的宽度,而不是跟着缩放走:路太细(缩小的远景、小路、铁路)先不写名字, 放大到够宽才出现,所以名字永远落在路面里;宽路字大、窄路字小。 很长的路沿路每隔约 190 像素写一个(每段最多 8 个),只放在屏幕上的可见段里,可见段比名字还短时就不写。
- 名字互不重叠:地点名、铁路名、道路名在同一张「已占位置」表上按这个顺序排,排不下就不画; 两个地点靠近时只显示一个,放大到名字框分开才都显示。地点名与地点标记来自同一份目的地列表 (自己标记的地点、Create 车站、MTR 车站),所以 MTR 站名也会画出来。
- 地点名按类型分缩放出:资源点
0.4、普通地点0.55、 站点0.7、商店1.0(px / 格)。默认写在标记下方, 被占就依次试上方、右方、左方与四个斜角,都不行才退一步。 - 线上名字顺着线的方向写,地点名保持水平——点标签和线的标签不是一回事。
- 开关与缩放规则走同一个入口,所以面板上的开关和缩放规则不可能互相矛盾。
颜色可以自己定
每个道路等级、每种公共交通线路的颜色都能改,不用重新打包,也不用重启游戏。
- 道路等级颜色:
config/howtogo-client.toml新增road_colors一节, 六项各一个颜色,写#RRGGBB或带透明度的#AARRGGBB。 世界地图、导航小地图、目的地选择界面、图例与网页地图读的是同一份设置。 - 公共交通线路颜色:
transit_line_colors,四个类型(铁路 / 水路 / 公路 / 冰道)各一项, 改的是线路本身的线与它名下的每一个站点标记;它下面的轨道仍按道路等级取色。 默认值就是一直使用的配色,不配置时和以前一样,MTR 读进来的线路同样按类型取色。 - 写错的值会被忽略(日志里说一次)并保留原色;改完不用重启。
NeoForge 上在模组列表的「配置」按钮里改最方便——它注册了 NeoForge 自带的配置屏幕,读的是生成
howtogo-client.toml的同一份声明,所以列出的项、默认值、范围与注释都与文件一致,保存后即时生效; Fabric 侧没有这个按钮,配置直接改 TOML 即可,值同样即时生效。
浏览器地图(webmap)
/howtogo webmap 在本机开一个小型 HTTP 服务,把游戏里那张地图
(不只是手画的路:阡陌交通、机械动力、MTR 的只读图层也在里面)送到浏览器里,
画成一张可平移缩放的俯视 2D 地图,并带一个导出 PNG 的按钮。
地址以可点击的链接发在聊天栏,点一下就用浏览器打开——它读的始终是你自己的那份路网。
| 命令 | 作用 |
|---|---|
/howtogo webmap |
启动服务并发出可点击的地址;已经在运行则只报地址。 |
/howtogo webmap stop |
停止服务并放开端口。 |
/howtogo webmap status |
报地址、当前世界与维度,以及路网的节点 / 路段数与总长。 |
- 只在本机可访问:只监听
127.0.0.1与::1, 配置里没有任何能把它放到局域网上的开关——这张图画的是自己世界的坐标与地名。 - 离线可用:页面、样式、五个脚本与 html2canvas 1.4.1(MIT)都打包在 jar 里, 运行期不请求任何外部资源。
- 只认一张固定的路径表:页面、样式、五个脚本、html2canvas 与两个 API, 表以外的路径一律 404——没有目录,就没有目录穿越。
- 端口不是死的:默认
7573,被占用时依次试后面 9 个, 实际绑定的端口写在聊天消息里,书签不会悄悄失效;webmap_port可改,webmap_auto_start(默认关)可在世界加载后自动启动。 - 手动启动不再弹确认框:服务启动成功后直接用系统默认浏览器打开,聊天栏保留纯文本地址。
- 数据只在客户端主线程读:HTTP 线程从不碰路网对象, 请求排进客户端刻的队列,由游戏线程摊平成一份不可变快照。 等待 5 秒超时返回 503,所以「这个世界还没画路」和「游戏还在加载世界」是两个能分辨的答案。
- 平滑曲线来自同一份数据:页面用
curve描边、沿路排路名,并让地点名避开真正画出来的线; 没有curve的手画道路照旧用顶点。载荷里每条路段还多一个可选的source(阡陌交通 / 机械动力 / MTR / 扩展,玩家手画的没有这一项), 页面用它把「只读」和来源写进鼠标读数与统计,侧栏多一行「自动识别」。 - 遮挡按层与描边排:路段按
layer从小到大画, 高架压地面、隧道在最下;同一层先描边后填充,所以十字路口看得出谁跨过谁。 - 文字会挪位置,而不是压住别人:路名沿路旋转且永远不写成倒的, 地点名默认在标记下方,被占了就依次试上方、右方、左方与斜角,都放不下就不画。 排版规则与游戏里的地图是同一套。
- 导出的就是屏幕上那张图:用同一个绘制函数按 2 倍分辨率重画, 带标题栏(世界、维度、时间、统计、图例);html2canvas 不可用时退回直接导出画布。
- 自检覆盖它:
/howtogo selftest会在系统分配的端口上真的把服务开起来, 取回页面、脚本、html2canvas 与/api/roads并核对份数。
主界面与地图存档
世界里按 K 打开主界面:标题下是一张只能看的地图(拖动平移、滚轮以光标为中心缩放, 点它不会选点也不会开始导航),再下面是状态(出行方式、导航目的地与剩余距离 / 时间、路网规模)和按钮—— 选择目的地、结束导航、切换出行方式、地图存档、自检、浏览器地图、关闭。按键可以在「控制」里改。
- 导出:
/howtogo data打开「地图存档」界面,一个按钮把当前世界的道路、 地点、铁路名称、公共交通线路与附属数据打成一个.zip放到config/howtogo/exports/;/howtogo export直接导出。 - 导入:另一个按钮把别人的
.zip导回来,/howtogo import [压缩包]读指定文件,压缩包也可以直接拖进界面。导入无视压缩包名与内部目录名: 目录层级被剥掉,.world记录改写为当前世界,数据写进当前世界目录。 - 覆盖前先说清楚:界面上写明写进哪个世界、来源与时间、文件数,旧数据会先备份;
确认后先备份到
config/howtogo/backups/,再整目录替换——不合并, 包里没有的维度文件会被删掉。备份文件名带-backup,在「可导入的压缩包」列表里单独标黄, 再导入它一次就回到导入之前。 - 只接受认识的文件:只读
.json;__MACOSX/、.DS_Store、.world、*.part、*.corrupt跳过;带..或绝对路径的条目不跟随; 文件数与解压总大小有上限;没有任何可读数据的包被拒绝,当前地图不动。 - 自检也覆盖它:自检里多一项「地图存档压缩包」,真的导出、导入、逐字节核对。
目的地从哪来
选择目的地界面把所有能去的地方汇成一列,按来源分开:
| 来源 | 内容 | 能不能改 |
|---|---|---|
| 你标记的地点 | 任何位置的 POI(含标为「站点」的) | 可以改名、改类别、删除 |
| 机械动力车站 | Create 的车站 | 只读(名字来自 Create) |
| MTR 车站 | MTR 的车站 | 只读 |
| Xaero 路标点 | 小地图上插的路标点(需要装 Xaero's Minimap) | 只读 |
| 阡陌交通结构 | 它连接的村落与小屋 | 只读(名字用它的别名或翻译名) |
列表上方有搜索框;界面里同时可以切换交通方式、路线偏好与语音,改动会记住。 界面不暂停游戏——它是地图,不是菜单。
兼容性与数据
- 纯客户端:服务器上不需要安装,也不会要求服务器装任何东西——唯一一个服务端入口只做一件事, 注册导航仪物品,让配方在服务端也能解析。代价是别的玩家看不到你画的路。
- 可选模组全部是「软」依赖:通过方块注册名或反射读取,没装就是对应图层为空,其它功能照常。
- 数据按存档分开:单人按存档名(
sp_)、多人按服务器地址(mp_), 文件名里带维度,目录里还有一个.world记录指向它属于哪个世界。 - 0.2.2 改了目录命名:中文存档的数据目录改用拼音
(
sp_新世界从sp_____变成sp_xin_shi_jie), 第一次打开某个世界时自动整目录改名,升级不用做任何事;风险在降级: 用 0.2.2 存过档再退回 0.2.1,那个世界的路网会是空的。 维度文件名不再被拼音化(minecraft_overworld.json就是它,不会变成「消失」)。 详见 数据目录与迁移。 - 搬家有两种方式:备份整个
config/howtogo/目录, 或用「地图存档」把当前世界打成.zip导出、再到另一台机器上导入。 - 不写别人的数据:机械动力、MTR 与阡陌交通的图层从不写进你的文件,你的路网也不会被它们改写。