Skip to content

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 14 Sep 06:51
d3b779a

新增

  • 「启动方式」从「实例设置」里分出来,成为实例下的独立页面。 那一页原本一个表单装了六段,其中
    「启动方式」自己占掉三分之二——而它也是唯一一段你会反复打开的:挑一次核心,之后每次调堆内存和 GC
    参数都要再来。现在它在侧栏有自己的入口,地址是 /i/<id>/startup。旧书签 /settings 照常打得开,
    只是里面不再有启动设置;实例起不来时那一页顶部会出现一条横幅,一句话说明原因并指过来。

  • 页面右侧常驻「实际执行的命令」。 左边改任何一项,右边那条命令立刻跟着变,启动时执行的就是它。

    命令由守护进程算出来再发给浏览器,而不是前端自己拼——因为面板会往命令行里加东西:控制台的编码参数
    (-Dfile.encoding=UTF-8 那一组)、以及管道模式下强制彩色的两个 -Dterminal.*。它们来自「实例设置
    → 控制台」的开关,前端拼不出来,硬拼出来的命令就是假的。现在它们压暗显示、在图例里标成「面板注入」,
    该看见的时候看得见。

    拼装逻辑因此在后端只留了一份:启动走它压平的结果,预览走它分段的结果,两边不可能长出对方没有的参数。

  • 新增「启动前检查」,并且能自动改好一部分。 检查跑在你正在编辑的草稿上而不是已保存的配置上,所以
    改一半就能看到结论。能自动修的直接给按钮——比如选了 Aikar's Flags 但最小内存和最大内存不一样时,
    会出现「把 Xms 改成 4096」,按一下左边就变了。

    新增四项:Java 版本是否配得上这个游戏版本、内存上下限是否符合所用预设的要求、实例目录下有几个 jar、
    端口是否和其他实例撞。

    Java 那条两个方向都查:版本太低会在加载类时直接退出,太高则是 1.16.5 之前那一代服务端的老问题——能
    启动,然后在加载世界时死于反射。登记表里已经有合适的 Java 时,直接给一个「改用 Java 21」的按钮;没有
    就说明要装哪个。它只对已发布的版本说话,因为那些版本的 Java 要求是不会再变的事实;遇到面板没见过
    的新版本它保持沉默,而不是猜一个出来。

    端口那条是只读的跨页核对——字段在「服务器配置」,这里只负责说出撞了,不给修改入口。

  • 内存一栏加了「锁定 Xms = Xmx」开关和宿主机内存分配条。 分配条按「其他实例 / 本实例 / 剩余」分段,
    填上限时终于有个参考系。它数的是各实例配置的上限,不是实时占用,所以写的是「已分配」;加起来超过物理
    内存时那一段会变色。用参数文件启动的实例上限在它们自己的文件里,面板不知道,会单独说明有几个没算进来。

变化

  • 服务端参数改成和 JVM 参数一致的卡片编辑,卡片与文本两种视图互斥。 此前 --nogui 胶囊和下面的
    文本框同时显示同一份数据,改哪个都生效,于是没人知道该改哪个。

  • JVM 参数的三个预设现在看得出选了哪个。 选中项是从参数本身认出来的,所以刷新之后、以及参数是从
    别人的启动脚本读进来的时候,它都还是对的。

  • 新增「下载」页和右上角的下载入口。 面板正在下的东西——服务端核心、Java 环境、数据库引擎、插件——
    以前分散在四个页面上各看各的,其中三个还只记得最后一次:核心下载凌晨失败了,下一个一开始,那条记录
    就没了。现在它们是同一个队列,右上角随时能瞟一眼还剩多久,/downloads 上能读到失败原因和历史。

    顺带解决一个看不见的浪费:此前四个页面各自每 800 毫秒拉一遍自己那份完整清单,装一个 Java 就要把整个
    运行时列表重新取八十次,只为读一个字节数。现在是一个只带任务的请求,空闲时完全停掉。

    插件库的「下载队列」页移到了面板级的 /downloads,旧链接会自动跳转。

  • 服务端核心的下载多了一条镜像线路。 核心此前是面板里唯一连加速选项都没有的下载,而一个 Paper jar
    有 50MB,每建一个实例就要下一次。新增的 FastMirror 是加入前逐字节比对过的:Paper 1.21.4 build232
    从它取回的文件与官方同 SHA-256、同 51437498 字节。校验用的始终是 PaperMC 官方元数据里的那个
    SHA-256——镜像自己发布的 SHA-1 不采信——所以走镜像拿到的一定是官方那份,否则下载直接失败。

    一并查过但没有采用的:清华和南大都不提供 papermc 镜像;华为云看似有,实际是它的镜像门户对任意
    路径都回 200,并不存在那棵树。

  • 服务端核心、Java 环境、数据库引擎的下载改为排队。 此前这三处各自只有一个槽位,上一个没下完,
    下一个直接被拒。现在排队等,同时装两个 Java 大版本这种事不再需要守着。插件库本来就是队列,不变。

  • 实例的 Java 环境改为只能从面板登记过的里面选。「资源库 → Java 环境」现在除了下载安装,还能登记
    本机已有的 Java:填 java 可执行文件的路径,面板跑一次 java -version 问出版本再记下来 —— 问不出来的
    不会被登记,因为一条没有版本号的记录,面板没法拿它讲任何道理。PATH 上探到的 Java 会单独列出来问要不要
    登记,确认之后才进列表:探测是面板在猜,而这张表里的每一条都该是人为决定过的。

    升级时面板会把各实例正在使用的 Java 路径自动登记进来,不问 —— 那些路径不是猜的,是这台机器上的
    服务器此刻正在用的东西,比任何探测都确凿。所以现有实例不受影响,照常启动。探不出版本的也照样记下来,
    标成「路径已失效」并原样保留路径,好过编一个版本号。java(跟随 PATH)保留成一条合法记录,不会被钉死
    成某个绝对路径。

    实例设置和创建向导里的「自定义路径」输入框随之移除。全新安装时如果 PATH 上有 Java,创建向导里一键即可
    「登记并选中」,不用先跳去 Java 环境页再走回来。

  • 文件页多了一个编辑模式,专门用来读和改一个文件。 标题右上角点「编辑模式」(或 Esc 退出):左侧导航
    折成图标条,中间那栏文件列表让位,目录树带上文件顶上来,编辑器铺满剩下的整屏。三栏排版是为「管文件」
    设计的 —— 上传、批量勾选、按大小和时间排序 —— 但改一个配置时,它把编辑器压到六百多像素宽,一行中文
    注释就要横向滚动。两件事,两种排法。

    编辑模式下目录树自己带上传、新建文件、新建文件夹、刷新,每一行悬停出现「⋯」,里面是重命名、复制路径、
    下载、删除;改名和删除会跟着落到已经打开的标签页上,不会留下一个指向不存在文件的编辑器。上面还有一个
    筛选框,只筛已经展开过的目录 —— 为一次按键去遍历没展开的目录是请求风暴,不是搜索。

    顶栏的面包屑、状态灯和「启动」按钮不藏:改完配置要能立刻重启。1024 以下不提供这个模式,那里本来就是
    一次只显示一栏;1200 以下目录树默认收起,需要时盖在编辑器上滑出。

  • 编辑器认得配置文件的语法了。 YAML / JSON / TOML / Properties / INI / Markdown / Shell 会按注释、
    键、字符串、数字、布尔上色,明暗两种模式和四套配色各有一组。四十万字符以上的文件自动关掉高亮并在
    状态栏说明原因 —— 打开一个半兆的日志仍然要跟以前一样快(能打开的上限还是 1 MiB,没有变)。

  • JVM 参数可以一个一个地调,不用再对着一整块文本改。 实例设置的「JVM 参数」多了一个「卡片」视图:
    一个参数一张小卡,一行放两张。卡片从上到下是参数名、一句中文说明、以及这个参数该用的控件 ——
    -XX:+UseG1GC 这种开关给一个 switch,-XX:MaxGCPauseMillis=200 这种给数字框并在后面标出单位,
    -XX:G1HeapRegionSize=8M 还多一个 K / M / G 下拉,-Dfile.encoding=UTF-8 给文本框。右上角的 ✕
    删掉这个参数,末尾的虚线卡片加一个。

    开关关掉不等于删掉:参数仍然在命令行上,写成 -XX:-Name,用来明确关掉某个默认或前面的参数打开的
    东西 —— 要整个去掉得点 ✕,卡片上也这么写着。

    加参数时下面会浮出候选,一条一个参数名加一句说明,方向键选、回车确认。候选能用中文搜:打「停顿」
    找得到 MaxGCPauseMillis,打「线程」找得到 ParallelGCThreads。

    类型是从参数本身的写法推出来的,不是查表查出来的,所以面板没听说过的参数照样能加、能编辑、能原样
    保存 —— 这种参数占满一整行,点参数名也能把任何一张卡片变回纯文本改。右上角可以随时切回「文本」
    视图,两边是同一份数据,预设按钮和「从启动脚本读…」也还是照常用。没动过的参数保存时逐字不变。

  • 文件页改成目录树 / 列表 / 编辑器三栏,而且能同时开几个文件。 点一个文件在右边直接打开,列表还在
    旁边,不用退出去再进来;上面一排标签管着所有打开的文件,改过没保存的标签带一个小圆点,关它会先问。
    左边是目录树,展开过的目录会记住,点「刷新」才重新读。

    编辑器底下多了一条状态栏:文件类型、编码、换行符、光标在第几行第几列,以及大小、行数和有没有未保存的
    改动 —— 把人送到这个框里的,通常就是控制台里一行「at line 42」。

    窄屏(1024 以下)一次只显示一栏:开着文件就是编辑器,没开就是列表,编辑器上面有一个「← 文件列表」
    回去。目录树在窄屏下不出现 —— 列表自己的面包屑和「返回上一级」本来就能走目录树,树是增益不是替代。

    三栏下列表那一栏比整页窄得多,所以「修改时间」这一列在三栏布局里也跟着收掉了(窄屏本来就会收),
    具体时间还在每一行的 tooltip 上。

  • 插件页收成三个标签:已安装 / 可更新 / 市场。「可更新」原来是一枚筛选 chip,用得够多,给了它自己
    的位置;「市场」是插件市场直接嵌在这一页,兼容性徽章按当前这台服的核心和版本算,不用先跳出去再回来。

    下载和安装仍然是两件事,页面上把这句话写在了市场标签的最上面:插件库是这台机器上所有服务器共用的
    一份收藏,从市场下载的东西进的是插件库,装到某一台服要回「已安装」里用「从插件库安装」挑版本。这条
    分层没有被合并 —— 运维面板最常见的困惑就是分不清改的是哪一层。

    加载失败的横幅提到了标签栏上面:插件没加载成功是这一页上唯一「现在就是错的」那件事,切到市场不
    应该成为看不见它的办法。横幅上有一个按钮直接跳回已安装并筛出异常的行。

  • 监控页先给结论,再给过程。 曲线上面多了一排读数卡:CPU、内存、进程数,每张卡上是当前值 +
    一句结论(正常 / 偏忙 / 偏高 / 接近上限)+ 一行脚注写明它是拿什么比出来的。判据只有一处,写在
    instanceEvents.ts 里,连同为什么是这个阈值 —— CPU 看的是所选时间范围的平均而不是最新一个点
    (一次尖峰不是结论),内存拿的是真正会生效的那个 -Xmx,没设置就不给结论。

    右边多了一栏「这段时间」,把这页已有的数据归成几条可读的判断:异常退出(带退出码)、CPU 持续跑满
    (附一句「先看视距和模拟距离,加核心对单线程没有帮助」)、内存贴近上限、服务器没在运行、以及什么都
    没发生。1280 以下它落到曲线下面 —— 和控制台右栏用的是同一档断点。

    服务器没在运行时不再显示 0% 和「正常」:停机的实例没有 CPU 读数,不是读数为零,卡上显示「—」。

    这一栏没有做成事件时间线,也没有「点告警跳回对应时刻的控制台」:守护进程没有按实例存事件日志,
    控制台也没有按时间寻址的接口,两样都只能编。插件加载失败仍然在「插件」页 —— 那页本来就是先把失败
    摆在最上面的。

  • 服务器配置页现在说得清你改了什么。 server.properties 那一页重排成三段:左边是分组锚点
    (基础 / 世界与生成 / 玩家与权限 / 网络与端口 / 性能 / 未分类,各带条数)加一个「仅看已修改」开关;
    中间每一项旁边多了真正的键名,改过的行左侧有色条、挂「已修改」徽章、下面把原值划掉写出来;底下是一条
    常驻保存条,写着「N 项更改待保存 · 重启服务器后生效」,右边是放弃更改和保存。

    高风险项现在写后果,不只是一个开关:关掉正版验证会让任何人冒用他人 ID 进入、极限模式对已有存档
    不可逆、改存档名会直接生成新世界 —— 这三项都用红字写在控件下面。

    没有做成逐行「需重启」徽章:服务端是启动时把这个文件读一遍,所以这页每一项都要重启,逐行挂等于
    每行都挂、也就等于没挂。改成反过来说 —— 白名单、难度、默认游戏模式这三项有等效的控制台指令,改了之后
    那一行会告诉你敲哪条可以立即生效。

    bukkit.yml / spigot.yml / paper-global.yml / paper-world-defaults.yml 也是同一套:分组锚点、
    「仅看已修改」、逐项键名和原值、常驻保存条,五个文件一模一样。之前只有 server.properties 改了,
    其余几个还是一摞面板加底下一个按钮 —— 同一页两种做法,看你点的是哪个文件。

    代理转发那两项现在写明后果:settings.bungeecord 和 proxies.velocity.enabled 打开之后,
    这台服会无条件相信连接里带的玩家身份,端口必须只对代理端开放,否则谁都能绕过代理直连冒用 UUID。

    保存的行为没有变:仍然只写你改动过的键,文件里的注释、顺序和面板不认识的键原样保留。往一个还没
    生成的文件里保存会创建它,只写你改的那几项 —— 保存之后卡片上的「未创建」也会跟着消失。

  • 配置文件的选择器从一排小胶囊改成了卡片。 每张卡上是文件名 + 一句话「这个文件管什么」
    (生物上限与自动保存 / 代理转发与实体优化 / Velocity 转发与踢出提示 / 性能调优与反矿透),
    服务端还没生成的文件标「未创建」。五个文件名挤成一排同样的胶囊时,看起来像一个长词,而且没有
    任何一处回答「我要改的东西在哪个文件里」。

  • 顶栏常驻服务器状态和启停。 进了某台实例之后,顶栏一直显示它在不在跑、已经跑了多久、CPU 和内存
    吃了多少,旁边就是启动/停止 —— 在「文件」「插件」「服务器配置」这些页面上不用再退回控制台看一眼或者
    重启一次。停机时只留状态和启动按钮,不显示三个「—」。

    窄屏逐级往回收:1240 以下先收掉「已运行」,1024 以下只留状态点和启停 —— 手机上收到告警要做的就是
    确认死没死、按一下重启,其余的数字在控制台上还有。同一档宽度下面包屑整条收起,因为每个页面自己的
    标题已经写着同一个词了。

    没有显示 TPS 和在线人数:守护进程读的是服务端的 stdout,它既没有玩家名册也没有 tick 计时,这两个
    数只能编,而编出来的数字比没有数字更糟。

    启停从控制台页的标题栏搬到了顶栏,所以控制台页不再重复一份状态徽章和一排按钮。启动失败的报错改在
    内容区顶上常驻显示,要手动关掉 —— 它可能是从「文件」页按出来的,不能只往控制台页的角落里写。

  • 面板多了三套配色可以换。「面板设置 → 外观」新增配色一栏:除了出厂的樱花,还有松绿、杏黄、
    碧蓝。每套都有浅色和深色两份,换配色不动明暗 —— 顶栏那个开关照旧管深浅,跟随系统也照旧。选择
    只存在这台设备的浏览器里,不跟着账号走,也不影响别人看到的面板;和明暗、像素字体一样在首帧之前就
    定下来,刷新不会先闪一下旧配色。浏览器标签页上那个图标也跟着换,标签栏没有明暗之分,所以它
    在深色下用的还是浅色那版渐变。

    两样东西故意不跟着配色走。一是两块终端:服务器控制台和主机 shell 在任何配色下都保持深色、而且
    互相不同色 —— 那是防止把危险命令敲进另一块终端的唯一屏障(碧蓝下主机 shell 会改成深绿,因为这套
    配色自己的深色表面正好落在 shell 原来的石板蓝上,再不挪就真看不出区别了)。二是状态色和图表曲线
    色
    :「运行中」「启动中」要在扫一眼的时候还认得出来,图表的四条曲线是按「彼此在色觉障碍下也分得开」
    校验过的,跟着品牌色走反而会失效。

  • JVM 参数有现成的几套可以直接点了。「启动设置 → JVM 参数」上面多了三个按钮:Aikar's Flags、
    G1GC 保守、ZGC 低延迟,点一下把整套参数填进下面那个框,填完照样能自己改。Aikar 那套会按你填的最大
    内存自动切数值(12 GB 是分界线),它要求最小内存和最大内存一样大,不一样的时候面板会直接说出来。

    做成整套替换而不是一个参数一个开关,是因为这些参数只在成套时才成立 —— 半套 G1 调参拌半套 ZGC 不是
    第三套调参,是个故障。框还是那个框,预设填不出任何你自己打不出来的东西。

  • 服务端参数里的 --nogui 有了一个开关,点一下加上、再点一下去掉。--forceUpgrade、--eraseCache
    这类一次性操作故意没做成开关 —— 记得住的开关意味着下次重启还会再跑一遍。

  • 读启动脚本多了两个来源。 除了实例目录里那个,现在还能读面板本机的任意路径,或者直接从你自己
    电脑上传一个
    。上传的脚本只在浏览器里读一遍、内容发过来解析完就丢,不会存进服务器目录 ——
    免得目录里多出一个面板永远不会执行的脚本,让下一个人以为那才是真正的启动方式。

  • 面板能读你原来的启动脚本了。 手工搭的服目录里一般躺着写好的 run.sh / 启动.sh / start.bat,
    里面 -Xmx、GC 参数、核心文件名一应俱全。导入目录时面板会把这些脚本列出来,选一个就把里面的参数
    读出来填进表单
    ;已经建好的实例在「启动设置 → 从脚本读启动参数」里也能随时读一个。

    读出来的是草稿:每一项都摆出来给你看,改完自己点保存才算数。拆不出来的脚本面板直接说拆不了、并指出
    是哪一行 —— 循环重启包装、条件分支、$(…)、重定向、-cp 加主类这些一律不猜。半条命令行比拆不出来
    糟得多,因为它能启动。

    认得出的脚本名也不只 run.sh 了:start.sh、startup.sh、start_server.sh、启动.sh、
    开服.bat、start.cmd 都在内,而 install.sh、更新.sh、backup.sh 这类一律不进候选。

  • Forge / NeoForge 1.17+ 的启动方式(@参数文件)现在是面板自己的一种启动目标。 那些版本的安装器
    不产可运行的 jar,启动是 java @user_jvm_args.txt @libraries/…/unix_args.txt。以前这只能靠跑它们的
    run.sh,现在面板直接拼这条命令行,于是 Java 选择、服务端类型、开服前检查对它们同样生效。

  • Java 运行环境可以选发行版了,默认改成 Azul Zulu。「Java 环境 → 下载设置」多了一个发行版选择,
    Azul Zulu 和 Eclipse Temurin 都在,新装的 Java 默认走 Zulu。已经装好的 Temurin 一个都不受影响,
    照常能用、能删、能在启动设置里选;想继续装 Temurin,在那一页切回去就行,选择会被面板记住。

    换默认的理由是下载:Temurin 的包在 GitHub 的发布存储上,国内要靠镜像才下得动;Zulu 的包在
    cdn.azul.com,是商业 CDN,直连通常好得多。代价是国内没有能用的 Zulu 镜像(南大、阿里、北外、
    腾讯的 /zulu/ 都是 404),所以 Zulu 只有官方 CDN 一个源 —— 反过来 Temurin 那五个镜像一个没删,
    Azul 的 CDN 要是反而更慢,切回去就是两次点击。

    Zulu 还多三个 Adoptium 没有的大版本(13、14、15),所以可装版本列表现在跟着发行版走。

  • Alpine 之类的 musl 系统头一回能直接装 Java 了。 以前面板只能弹一句「Temurin 是 glibc 构建,
    装上也跑不起来,请自己用包管理器装 OpenJDK 再手填路径」。Zulu 有 musl 构建,面板检测到 musl 会
    自动挑对应的包。选着 Temurin 时那句警告还在,但结尾从「自己想办法」改成了「换成 Zulu 就能装」。

  • Zulu 的下载源支持自己填镜像地址。 知道哪个加速地址能用就填在下载设置页,面板把文件名接在后面
    下载,校验和照样卡 Azul 官方的,下不到会自动退回官方 CDN。给自建镜像和国内新出的加速站用。

  • 更新页可以装任意一个历史版本了。 「其他版本」折叠开之后,列出当前通道里还在的所有版本,每行
    一个按钮直接装 —— 新版有 bug 想退回去、或者想装某个特定的快照,不用再 SSH 上去手动换二进制。

    列表是展开时才去 GitHub 拉的,不在首屏联网。能不能装由面板对着通道自己的列表判定,不是信请求里
    的版本号:否则从列表里挑一个就绕开了更新通道。往回装同样算降级,同样会先把面板配置备份一份。

    和「退回上一版」的区别:那条路不联网、秒级、不受 releases 清理影响,但只有一份,连退两版做不到;
    这条路能跳着装,但得那一版还在 GitHub 上(快照只留 3 份)。

  • 更新页可以退回上一版了。 面板更新时被换下去的那个二进制一直留在原地(<可执行文件>.old),
    注释里早就写着「留着好让人手动回退」—— 但没人知道那个文件是哪一版,也就没有按钮可按。现在它记在
    panel.json 里,更新页上多一节「回退」。

    这条路是纯本地的:不下载、不联网,哪怕那一版已经从 releases 页上被清理掉(快照只留 3 份)也照样
    能退。按之前面板会先把 .old 跑起来问它 -version,跟记录对不上或者跑不起来就不给按钮并说明原因 ——
    把面板换成一个起不来的文件,之后连修它的面板都没有了。退回去之后 .old 就是刚才那一版,改主意还能
    再换回来。

    任何一次降级之前,面板会先备份自己的配置。 这不只是回退,从快照切回正式版也算。原因是旧版本
    读不懂新版本写进配置的字段,而 Go 只写它声明过的字段 —— 旧版本一保存,那些字段就永久没了(登录
    凭据、GitHub token、角色权限都可能中招)。所以 panel.json、users.json 等八个文件会原样复制到
    data/rollback-<时间戳>-<from>-to-<to>/,保留最近 3 份。这份备份是给「再升回来」用的:回退本身
    不碰那些文件,损失发生在旧版本跑起来回写之后。确认框里把这些、以及 -reset-password 能救登录,
    都写明白了。

    装任意历史版本还不行,见 docs/proposal-rollback.md 的第 2 期。

  • 面板可以用 Minecraft 味的像素字体了。「面板设置 → 外观」新增像素字体开关,默认开着。
    英文和数字用 Monocraft(照着游戏字形做的开源字体),
    汉字用缝合像素字体补上 —— 前者一个汉字都没有,
    而面板界面几乎全是中文。两个都是 SIL Open Font License,随二进制一起发(多 633 KB),
    不连外网也能用。Minecraft 自己那套字体是 Mojang 的资产,不能进开源仓库,所以是这两个替身。

    控制台和主机 shell 那两块画布不跟着变,面板里的路径、SHA、配置 diff 这些等宽位置也不变 ——
    它们是一个字符一个字符去认的东西,换成点阵只会更难读。开关存在浏览器本地,不跟着账号走,
    和深浅色一样在首屏之前就定好,刷新不会闪一下再换字体。

  • 用自己的启动脚本开服(Forge / NeoForge 等)。 「实例设置 → 启动方式」现在是两选一:
    面板拼命令(java -Xmx… -jar server.jar,原来的样子)和用我的脚本。后者本来就能用
    —— 底下一直有个「自定义启动命令」的框 —— 但它写着「可选」、填了就把上面六个字段灰掉,
    说的是「高级逃生口」。而 Forge 从 1.17 起根本没有能直接跑的 jar:安装器留下的是一个
    libraries/ 目录、一个 run.sh 和 user_jvm_args.txt,脚本启动对这些服是唯一的路,
    不是例外情况。

    真正要紧的不是「能不能跑起来」,而是交给脚本之后面板还剩下什么,所以这次补的是那几处:

    • Java 选择对脚本生效了。 脚本里那句裸 java 走的是 PATH,所以面板把选中的 JDK 放到
      PATH 最前面并设好 JAVA_HOME,脚本一个字都不用改。以前面板装了 JDK 21、实例也选了它,
      脚本照样跑在系统那个 JDK 8 上,报错是一句不认得的 class file version。
    • 控制台编码参数通过 JAVA_TOOL_OPTIONS 传进去。 面板没法往你的命令行里加参数,
      中文乱码基本都是少了 -Dfile.encoding=UTF-8 那一组。代价是启动时控制台会多出一行
      Picked up JAVA_TOOL_OPTIONS,所以做成了开关,默认开。
    • 内存设置改到 user_jvm_args.txt。 脚本自己决定 -Xmx,面板那个数根本到不了 JVM。
      Forge 的 run.sh 读的就是这个文件,所以内存框在脚本模式下直接写它 —— 文件里的注释和
      其他参数原样保留,Forge 默认那行注释掉的 # -Xmx4G 会被就地改成真的设置。
    • 内存图不再画一条编出来的线。 首页卡片、实例列表、监控图、主机页的「已分配 -Xmx」
      以前一律取实例配置里的那个数;脚本模式下那个数和真实堆上限没有任何关系。现在取的是
      真正会生效的上限(user_jvm_args.txt 里的 -Xmx),读不出来就记作「未知」并且不画
      参考线 —— 一条来自 JVM 从没见过的字段的参考线,比没有线更糟。
  • 实例可以记住自己是什么服务端。 「实例设置 → 基本信息」多了服务端类型和游戏版本。
    面板仍然优先从目录和 jar 名认,认不出来才用这里填的。脚本启动的服基本都认不出来 ——
    没有 jar 名可读,version_history.json 又只有 Paper 系才写。认不出来的后果不是难看而是会出错:
    mod 会被装进 plugins/ 而不是 mods/,插件市场里每一条也都标成「未知」。

  • 开服前检查。 「实例设置」里多了一块,开服之前先看一眼这个实例能不能起来、以及
    起来之后面板还抓不抓得住它。后半句是这块的主要用处:一个 nohup java … & 的脚本会
    把服务器开得好好的,然后在一秒内把进程还给面板 —— 面板显示「已停止 exit 0」,控制台发不出
    命令,停止按钮停不掉,崩溃自动重启还会在同一个世界上再开一个。这条链上没有任何一环会说
    「你的脚本把 JVM 放到后台了」,所以改成在开服之前就说。会点名的有:nohup、行尾的 &、
    screen、tmux、systemctl、docker,每一条都附上脚本里那一行原文和行号。

    另外两件确定性的事会直接给出修法:脚本没有执行位(上传压缩包、从 Windows 拷过来都会丢掉
    这一位,症状是 permission denied)旁边就是「加上执行位」;把 ./run.sh 写成 run.sh
    会被当成 PATH 里的命令去找,面板会直接说「目录里有 run.sh,但得写成 ./run.sh」,
    而不是转达一句「run.sh: not found」。

  • 导入现有目录认得出 Forge。 指到一个 Forge / NeoForge 目录,面板从 libraries/ 的
    布局认出它是什么、是哪个游戏版本,并且默认按它原来的方式启动(勾选「用目录里的 run.sh 启动」)。
    以前这样的目录会因为「没找到 jar」被当成一个还没装核心的空实例导进来,导完也起不来。

  • 账号与角色:面板不再只有一个操作者。 以前面板只有一份凭据,谁拿到谁就是服主。现在有账号、
    有角色,一个账号持有一个角色,角色是一组能力的集合。

    升级无感:第一次启动会把原来那份凭据变成第一个管理员账号写进 users.json,用户名和密码都
    不变,已配对的设备原样归到这个账号名下。忘记密码仍然是 hypercraft -reset-password。

    能力是面板定义的固定词表(26 条),操作者不能发明新的,但可以随意组合成角色。出厂带三个:
    管理员(全部能力,内置,改不了也删不掉)、运维(看状态、开关机、控制台、配置历史)、
    开发(运维的全部,再加改配置、传文件、装插件、调启动参数和三个共享库)。预设建好之后就是
    普通角色,随便改随便删。

    还可以把一个账号限定在几个服上。 授权是和角色正交的第二个维度:角色说「能做什么」,授权说
    「对哪些服」,两样都要满足才放行。没设置授权就是全部实例(升级上来的账号都是这样),设成空就是
    一个都碰不到。没被授权的实例返回 404 而不是 403 —— 403 等于告诉对方「这个 id 是个真实存在
    的服务器」,而这正是授权要挡住的事。列表、搜索、插件总览、仪表盘计数,看到的也都只有自己那几个。

    控制台还分了读写:只有「查看服务器」没有「发送控制台命令」的角色,连上控制台是只读的 ——
    看得到输出,敲进去会被拒。不是握手失败,因为他确实有权看。

    界面在「面板设置 → 账号与角色」。 建账号、改角色、勾实例授权都在这一页。角色编辑器里的能力
    列表是面板给的而不是前端写死的,所以以后版本新增一条能力,这里会自己多出一行。

    还可以把一个角色的文件管理器限制在某个目录下。 角色编辑器里填 plugins/MyPlugin,这个角色就
    只能读写那个目录 —— 文件列表里,通往它的上级目录只显示这一条路,别的一概不列;不在范围内的地方,
    上传和新建是灰的,重命名和删除也是。它只管文件管理器:编辑服务器配置、导入建筑、换核心各有
    各的能力,不受这里限制。

    这条限制有一个前提,角色编辑器会当场说出来:只要这个角色同时持有任何一项能决定服务端跑什么
    代码的能力(装插件、改启动设置……),目录限制对它就没有意义
    —— 能执行代码就能绕开任何目录规则。
    勾上这类能力时会直接弹出提示,点名是哪几项。

    面板也按能力隐藏入口。 侧栏、命令面板、「新建实例」按钮、实例页的分区、开关机按钮、控制台
    输入框,看不到的就是用不了的 —— 但隐藏不是屏障,拦截在服务端按路由、按字段、按 WebSocket
    消息做,前端少判一处只是毛刺,不是漏洞。

    有一件事特意说清楚,因为它决定了这套东西值多少钱:「开发」这个角色不是安全边界。 服务端进程
    和面板跑在同一个系统用户下,所以传一个 jar、改启动参数、改实例目录,这三件事都等于在宿主机上
    执行任意代码 —— 能读到面板的密码哈希、数据库明文密码和别人的实例目录。这个角色防的是误操作和
    职责混乱,不是防人。角色编辑器把这类能力单独放在「高危」一组里,上面写着这句话。真正挡得住
    的是「运维」:它碰不到宿主机文件系统(但控制台等于游戏内最高权限,能 /op 任何人)。

    另外有一处例外要知道:「代理连线」不受实例授权限制。一条链路是关于两个实例的事实,哪一端都
    不拥有它,所以它是面板级能力 —— 给出这项能力,等于允许对方改动任意两个实例的那几个配置文件。
    半张图比没有图更容易让人配错,所以这里选了不过滤。

    顺带修正了两个原来「只有一个人」时才成立的行为:改密码只会让自己的会话和设备失效,不再
    把所有人一起踢下线;设备令牌属于配对时用的那个账号,继承该账号的角色,「我的设备」列表
    里也只看得到自己的。停用或删除一个账号会立刻生效 —— 账号状态是每个请求都重新读的,不是
    等会话过期。

    详见 安全与访问控制。

  • 代理连线:把服务端挂到代理端后面,拖一条线就行。 侧栏「实例」组下多了一页代理连线:
    左边是代理端,右边是服务端,从一边的接口拖到另一边(或者点一下这边的接口再点那边)就连上。

    这件事本来是一个决定、六处修改,散在两个目录的四个文件里,而且漏掉任何一处的报错都长得
    像别的问题:漏了子服的 online-mode 所有人被当成盗版号踢出去;漏了转发密钥代理端说子服拒绝
    它;漏了 [servers] 里的一行,/server 说这个服不存在。现在连线一次做完:代理端那边写
    [servers] 和登录顺序、必要时把转发模式设好并生成密钥;服务端那边关掉自己的正版验证(验证
    交给代理端做)、按转发模式打开 paper-global.yml 的 Velocity 转发并填上同一个密钥,或者打开
    spigot.yml 的 bungeecord。改了哪几处会原样列出来,两端各打一次配置快照。

    反过来读同样重要:链路不记录在面板的任何地方,而是从配置文件本身认出来的 —— 代理端
    [servers] 里的地址对上各子服自己 server.properties 里的监听地址(localhost、0.0.0.0、
    127.0.0.1 算同一台机器)。所以以前手动配过的人打开这一页看到的是同一张图,配了一半的地方
    显示成它本来的问题
    ,旁边就是「修复」。指向别的机器的子服也照常显示,只是标成「面板外」。

    会点名的问题不只是「少填了什么」,还包括那几种两边都没报错、进服才发现的:代理端和子服
    对「代理端开没开正版验证」的看法不一致(proxies.velocity.online-mode 和代理端的 online-mode
    对不上),玩家拿到的 UUID 就是错的 —— 在游戏里看起来是所有人的背包和床都没了,不是一条报错;
    代理端选了 modern 却没有密钥文件,Velocity 是拒绝启动的,这时该改的是代理端而不是子服,
    所以话也说在代理端头上;代理端的登录顺序(try)空着又没有域名映射,玩家一连上来就被踢,
    和每条链路本身配得对不对无关。

    几条不会让人踩空的规矩:第一个连上的子服自动成为玩家的落点,「修复」也会把空掉的落点补回来;
    重复连线不会多出一行,也不会把子服改名 —— /server lobby 写在传送牌和插件配置里;
    Spigot 系核心不支持 modern 转发,代理端还没选模式时自动用 legacy,已经在用 modern 的则直接
    拒绝并说清楚原因,而不是配出一个登录时才失败的链路。两个实例占着同一个地址时连线会被拒绝 ——
    [servers] 一行只写得下一个地址,硬连的话这条线到底通向哪一台,面板和代理端都答不上来;
    两台服务器本来也不可能同时监听一个端口,所以这句话在连线时就说,而不是等开服失败。

    断开会把子服的正版验证开回来(前面没有代理端挡着,关着验证谁都能顶号进来),顺手清掉指向它的
    域名映射;要是被断开的正好是玩家的落点,落点会交给剩下的子服,并写在改动清单里 —— 断开一台
    服务器不该把整个网络一起带下线。

    窄屏不画线:手机上两列卡片加曲线是看不了的,换成每个代理端一张卡片、下面列着它的子服和各自
    的问题,连接是一个下拉加一个按钮。

  • 服务端的 bukkit.yml、spigot.yml、Paper 配置终于有表单了。 「服务器配置」页顶上多了一排
    文件切换:server.properties、bukkit.yml、spigot.yml,以及这台服真正读的那套 Paper 配置。
    在此之前这些只能去文件管理里翻 —— 三个文件加起来上千行,改一个布尔值要先读九百行注释。

    能改的是常改的那些:生物生成上限和刷新间隔、实体活动范围、掉落物与经验球的合并与消失、
    刷怪笼无 AI、漏斗与爆炸的优化开关、反矿透、玩家被拦下来时看到的那几句话、代理转发相关的项。
    Paper 的两套布局(1.19 之前的 paper.yml、之后的 config/paper-global.yml 与
    paper-world-defaults.yml)按磁盘上实际存在的那套走 —— 两套都摆出来的话,页面上会有两个
    反矿透开关而只有一个生效。

    和另外两个配置页一样的规矩:注释、空行、缩进和键的顺序在保存后原样保留(Paper 的配置大半是
    文档,丢了就没法看了);只写你改过的那几项,打开页面按一下保存不会把四十个默认值灌进
    一个本来跑得好好的文件;列表、块字符串这类面板读不动的值一律不碰;文件还不存在也能填,保存
    时按正确的层级建出来,剩下的等服务端启动时自己补齐。

  • 代理端多了「域名映射」。 就是 velocity.toml 的 [forced-hosts]:玩家从
    creative.example.com 连进来直接落到创造服,主域名进大厅 —— 对玩家来说像两个服务器,其实是
    同一个代理端。这是 velocity.toml 里唯一不是「设置」而是「路由表」的部分。

  • 新建实例向导:选中代理端核心时,内存预设跟着换。 默认 512 MB,可选到 1 GB / 2 GB,而不是
    继续给出 2/4/6/8 GB 这种按世界大小算的档位 —— 代理端不加载世界,给多了只会让它的 GC 停顿变长,
    而代理端一停顿,后面所有子服的玩家一起卡。自己填过数字之后就不再跟着核心变。

  • 实例分代理端和服务端了,代理端有自己的配置页。 之前面板只有一种实例:一台 Velocity 也被
    当成 Minecraft 服务端管 —— 启动参数带着它不认识的 --nogui、停服敲它没有的 stop、「服务器
    配置」页给它开 server.properties 和 EULA,而这两个文件 Velocity 一个都不读。配对了也没用,
    配错了还看不出来:一个不生效的设置和一个没保存的设置长得一模一样。

    现在实例上记着它是什么。代理端(目前只支持 Velocity)默认不带 --nogui、停服命令是
    end、默认堆内存 512 MB(Velocity 官方的建议,堆大了 GC 停顿反而拖累后面所有子服);从核心库
    装一个 Velocity 核心、或者导入一个有 velocity.toml 的目录,实例会自动切成代理端——你自己改过
    的停服命令和启动参数不会被覆盖。

    侧栏那一页也跟着换成**「代理配置」**,编辑的是 velocity.toml:

    • 子服务器排在最前面,因为这是代理端唯一没有可用默认值的东西。一行一个名称和地址,能排序、
      能勾「登录顺序」(写进 try)。本机的其它实例直接一键添加 —— 地址是从那台服务器自己的
      server.properties 读出来的,不用再翻五个页面抄端口。
    • 玩家信息转发单独一栏,带转发密钥:可以一键生成、一键复制,页面上写清楚要粘到子服的
      哪个文件里。选了 modern 却没有密钥时会直接警告 —— 那种情况下 Velocity 是拒绝启动的。
    • 监听地址、MOTD、压缩、超时、Query 等常用项都有对应的控件,注释、空行、键的顺序在保存后原样
      保留(和 server.properties 一样的规矩),面板不认识的键留在文件里不动。

    新建实例时选中 Velocity 核心,向导会多一步**「代理端设置」**(监听端口、转发模式、MOTD),
    创建时直接把 velocity.toml 和 forwarding.secret 写好 —— 代理端第一次启动之前就能配完。
    控制台的快捷命令、连接地址、实例列表上的「代理端」标记也都跟着换。

  • 建筑库:.schem 现在是面板级的资产,和插件库同级。 在此之前一个建筑只有一个家 —— 某台服的
    schematics 目录,只能从那台服的文件管理器进去,别处看不见。可建筑不是这么用的:出生点要贴进下个
    赛季的世界,商店街每台生存服都要一套,三年攒下来的那一堆是服主的东西,不是「谁先收到就归谁」。
    所以它成了一层货架:存一份,装到哪台服都是从这里复制过去。

    入库时文件就解析过了,所以列表上直接读得到尺寸、方块总数、种类数,还有一条按用量排序的颜色带 ——
    一眼能分出「这个是花园」和「那个是石堡」。点开就是之前那套预览:同一个解析、同一个渲染器,不管
    文件在实例目录里还是在库里。

    四条进库的路:拖一批文件上传(一个文件一个结果,坏掉的两个不连累另外二十八个);在文件管理器
    里预览一个 schematic 后点加入建筑库(服务器上那份原地不动);从建筑市场下载;或者把文件
    直接复制进 <数据目录>/schematics/ 再点扫描目录 —— 从别的面板搬家走这条。

    装到实例这一步不让人猜目录。//schem load 只读一个文件夹,是哪个取决于服务器装的是 WorldEdit、
    FastAsyncWorldEdit 还是 Fabric/Forge 版本,而放错了不会报任何错:服务器照常启动,进游戏才发现
    「找不到这个建筑」。面板会先看这台服到底装了什么再决定目录,并把该敲的 //schem load xxx 写在
    安装结果里。

    同一份文件按 SHA-256 认,不会入库两次。改名字、写备注、打标签都不动磁盘上的文件名 —— 那是进服之后
    要打出来的名字。

  • 建筑市场:从 GitHub 仓库和 JSON 索引里找建筑。 schematic 没有 Modrinth 那样的中央仓库 ——
    发插件的几个站都不发建筑,发建筑的几个站没有能用的 API,去爬页面等于把面板的可用性挂在别人的改版
    计划上。所以市场是联邦式的,两种源:

    GitHub 仓库填 owner/name(可带分支和子目录,粘仓库链接也行),仓库里每个 .schem 都会列
    出来,目录名当标签用 —— 不需要对方做任何配合,这也是今天建筑实际的分享方式。JSON 索引是一份
    手写的清单,放在任何能 HTTPS 访问的地方就行,不用跑服务;一个服务器群可以把自己的建筑发给自己的
    几台面板,和别的源并排显示。

    下载和插件共用一套代理设置(同一个 GitHub CDN,同一种网络问题)。存进库前一律先解析,读不出来的
    不收;索引写了 sha256 的会校验,对不上就回滚,不留半个文件。某个源读不到只是它自己那一行的提示,
    不会把整页变成一条报错 —— 别的源已经答上来了。

  • .schem / .schematic 可以在文件管理器里直接预览了。 一个 schematics 目录里躺着三十个
    build_final_v2.schem,在此之前分辨它们的唯一办法是进服找块空地一个个粘 —— 面板对这类文件只
    能说「不支持在线打开」。

    现在点文件名就出图:立体图是等轴测渲染,可以左右各转 90°;高度滑块只显示到第 N 层,
    屋顶挡住内部的时候就靠它往里看;俯视图是从上往下的平面,下面的楼层淡出,用来看格局;右边
    是按用量排序的方块清单,带颜色和占比,「这栋楼要备多少云杉木」直接读数。尺寸、方块总数、
    格式版本、作者、保存时间、方块实体和实体数量列在最上面一栏。

    三种格式都认:Sponge v1/v2(WorldEdit 7 的默认)、Sponge v3(1.20+)、以及 1.13 之前的 MCEdit
    .schematic。旧格式存的是数字方块 ID,面板会把它翻成现在的名字(35:14 → red_wool),所以
    老图和新图在清单里是同一套词汇。

    解析在守护进程里做,不在浏览器里做 —— 文件本来就在服务器上,为了回答「哪个是城堡」把
    40 MB 的 gzip NBT 推到面板去是反过来的。渲染用每种方块一个近似颜色而不是材质包:那意味着几十兆
    贴图、一个版本矩阵和一个授权问题,只为了让 400px 的预览好看一点。不认识的方块(模组、老 ID)会
    按名字散列出一个稳定的颜色,至少两种不同的方块不会长成同一个。

    有几道闸:单文件 64 MB、解压后 96 MB、标签数 200 万,防的是「几百 KB 的 gzip 解出一个世界」这种
    文件把守护进程的内存吃光。选区超过 800 万格时只返回数据不返回图形,尺寸和方块清单仍然是完整的,
    页面会写明原因。

  • 插件可以同时下载了,并且有了「下载队列」页。 之前面板全局只有一个下载槽位:第二个下载会被
    直接拒绝(一个插件下载正在进行中),于是「把这五个插件都更新入库」是五次点击,每次都得等上
    一次下完。更糟的是失败记录只留最后一条 —— 半夜失败的那次,会被早上的第一次下载冲掉,等你想起来
    看的时候已经没有了。

    现在是队列:最多同时下 3 个,多出来的排队。上限是上游定的不是磁盘定的 —— 每个任务开头都要
    向 GitHub API 问一次 Release,匿名一小时只有 60 次,二十个并发能一口气把配额打光,连带着之后的
    更新检查也一起被限流。

    「下载队列」在 插件库 下面,跟「插件列表」「插件市场」并列。分成「进行中」和「历史」两段,每行
    都能单独取消,失败的那行会把原因写在行里而不是塞进 tooltip。历史保留最近 30 条,可以手动清空;
    清空只是清记录,不会停掉正在跑的任务。「插件列表」上原来那条下载状态换成了一行提示,指向队列页
    —— 一个会随着下载数量长高的区块,会在你最需要看表格的时候把表格推下去。

    重复请求同一个 jar 不会开第二个任务,会返回正在跑的那个。之前这件事是靠「拒绝第二次点击」顺带
    保证的,队列化之后必须显式去重,否则两个 worker 会写同一个 .part 文件。另外,因为排队的任务
    可能几分钟后才轮到,「这个 tag 不存在」这类上游错误不再是同步返回的 400,而是落在任务上 ——
    队列页会写出来。

  • 插件库的列表现在会读 jar 自己的 plugin.yml 并展示出来。 这个列表以前完全是照着来源拼
    出来的:名字是仓库名或者商店名,而 GitHub 仓库名往往不是插件名(EssentialsX 仓库里的 jar 声明
    的是 Essentials,服务端也是按这个名字加载和查重的),并且哪一栏都没说这插件到底是干什么的。

    现在行上会补两条 jar 自己声明的信息:声明名(只在和列表里的名字不一致时显示,一致的时候
    重复它只是噪音)和 api-version(「升级服务端之后这插件为什么不加载了」的答案)。描述和作者
    放在插件抽屉里而不是行上 —— 描述是段落,段落塞进 52px 的行里要么被截断成没用的一截,要么把整张
    表的行高毁掉。

    面板会在启动后台补读一遍库里所有还没读过的 jar,所以 0.3 之前下载的、以及手动导入的插件也会有
    这些信息,不需要重新下载。读不出描述符的 jar(比如 Forge 模组的描述符是 TOML)会记一次「读过了」
    ,不会每次启动重读。

  • 从实例移除插件时可以选择一并删掉配置目录。 之前配置目录是硬编码保留的,想彻底删干净得自己
    去文件管理器里翻,还得猜哪个目录是它的 —— Bukkit 用的是 plugin.yml 里声明的名字建目录,不是
    jar 的文件名。现在移除确认框里多了一个默认不勾的选项,勾了才删,并且面板会把要删的目录路径
    写在选项上。

    面板拿不准的时候不提供这个选项,而不是猜:读不出描述符的 jar 没有名字可依据;跟目录里另一个 jar
    声明了同名的(页面上标着「重名」的那种),删掉的可能是另一个插件的数据。选项的说明里也写清了
    这个目录里通常不只是设置 —— 经济余额、领地、权限组都在里面。

  • 实例多了一个「配置历史」页:配置文件的时间线、diff 和还原。 回答的是那两个最费时间的问题 ——
    「昨天还能启动,今天不行了,中间改了什么」,和「这次升级插件自己往配置里补了哪些键」。每个实例
    一个 Git 仓库,但对外只有时间线、diff 和「还原这个文件」三件事,Git 只是实现。

    它不是备份,页面上也这么写。 世界、玩家数据、数据库全部不在收录范围内,全量备份策略还是要
    单独准备 —— 「有历史了」的错觉不能替代真正的备份。

    几个值得说的取舍:

    • 收录靠白名单加签名探测,不是黑名单。 撑爆仓库的从来不是一眼就该排除的东西,而是
      plugins/Essentials/userdata/*.yml(几万个玩家文件,扩展名是 .yml,就在 plugins/ 底下)
      这类长得像配置、本质是运行时状态的文件。世界目录靠里面有没有 level.dat / region/ 判断,
      所以叫 survival 或 生存服 的存档一样认得出来,只收它根层的 paper-world.yml。
      ops.json / whitelist.json / banned-*.json 收录 —— 那是运维意图,不是运行时状态。
    • 提交发生在语义边界,不监听文件。 插件在启服和关服时会重写自己的配置,文件监听会把这些变成
      一串没人看得懂的提交。触发点是:创建实例、启服前、停服后、插件事务前后、切换核心、在面板里
      保存配置、手动打快照。副产品是「启动前」和「停止后」两个快照之间的 diff —— 那正好就是这次
      运行中插件自己改了哪些配置项。没有变更就不提交。
    • 三道硬闸门,超限直接中止并报出来。 单文件 512 KB、单次 500 个文件、仓库 200 MB,都可以按
      实例调。中止不是静默跳过:漏一次 gitignore 只是仓库脏一点,但把一个 2 GB 的世界提交进去,
      仓库就永久性地胖了。
    • 还原只往前走。 还原 = 用旧内容写一个新提交,永不 reset / revert,所以「还原之后发现
      更糟」永远有路回去。默认是单文件还原;整树还原是高级操作,要求服务器已停止、看完完整预览、
      再确认一次。还原前会自动打一次快照,目标快照与当前的插件 / 核心版本不一致时会列出差异并要求
      显式确认 —— 配置是旧版的、jar 是新版的,服务器可能直接起不来。
    • 不提供推送到远程仓库,也不提供下载整个仓库。 server.properties 里有 rcon 密码,
      DiscordSRV 有 bot token,数据库凭据也都在里面。仓库不出这台机器,是这个模块唯一的硬性红线;
      单文件、单 diff 的导出可以有。面板内看 diff 时,密码 / token / secret 这类值默认打码,点一下
      才展开。
    • 仓库放在面板数据目录,不放在服务器目录里(git-dir 与 work-tree 分离)。SFTP 里乱翻删不掉
      它,打包搬服不会把历史一起带走,实例目录被 rm -rf 之后历史还在。删除实例时历史一并删除,
      确认框里会说这件事。
    • 行尾规范化整个关掉(core.autocrlf=false、* -text)。有些插件写 CRLF、有些带 BOM,让 Git 去
      做规范化会把两行的改动变成整个文件的 diff,历史就失去可读性了。
  • 插件升级事务的配置备份换成了一个 commit ref。 原先每次升级都要把插件的整个配置目录复制一份
    (上限 256 MB);现在配置那半边由配置历史承担,去重之后基本不占空间,jar 仍然按哈希单独备份。
    配置历史没启用、或是升级前记录失败时,自动回落到原来的目录复制,老快照照旧能回滚。

  • 配置历史多了一条「当前改动」。 排在时间线最上面,写着「未记录」,点开就是磁盘上比最近一次
    快照多出来的那些文件:改了什么、多了什么、少了什么,每个文件都能展开看逐行 diff,也能单独
    「撤销这次改动」(就是把最近一次快照里的那一版写回去,和还原走同一个预览确认)。之前这件事只有
    一个「有 N 个文件的改动还没有记录」的提示,N 是几没人知道是哪几个 —— 而「我刚才动了什么」恰恰是
    服务器起不来时第一个要问的问题。

  • 配置历史和文件管理打通了。 变更列表里每个文件都有「在文件里打开」,直接跳到文件管理并把那个
    文件打开在编辑器里;反过来,文件管理的编辑器里多了一个「配置历史」,把当前编辑的文件送去配置
    历史比较 —— 如果它正好是一个还没记录的改动,落在「当前改动」上,否则落在最近一次快照上。两个页面
    看的是同一个目录,一个是它现在的样子,一个是它以前的样子。

  • 配置历史多了「刷新」按钮。 时间线、变更列表和打开着的 diff 一起重读。服务器和别人都在写这个
    目录,之前要看到新状态只能切走再切回来。

  • 点开文件是「预览」,双击才固定成一个标签。 跟编辑器里的习惯一样:单击打开的标签名字是斜体的,
    再单击下一个文件就顶掉它,一直只占一个位置;双击文件、或者在里面敲第一个字,这个标签就留下来,
    后面再点别的文件会开在它旁边。在插件的 lang 目录里挨个点开找那一行中文,以前是十几个标签要回头
    一个一个关掉。已经开着的标签双击它自己也能固定。

变更

  • 文件页去掉了「编辑模式」开关,布局跟着「有没有打开文件」自己变。 那个开关同时做了三件不相关的
    事——把外壳收成导轨、把目录树从「只有文件夹」换成「文件夹加文件」、把宽度从列表挪给编辑器——于是
    「想把这段配置看清楚」这件事,第一步是去按一个以状态命名的按钮。现在没开文件就是「树 + 列表」,
    点开任何一个文件自动变成「树 + 窄列表 + 编辑器」,不需要任何点击;栏与栏之间可以拖拽调宽,宽度按
    实例记住。1600px 视口下编辑器拿到 780px 以上——Paper 自己的 bukkit.yml 开头那行注释有 85 个字符,
    再窄一点这个文件一打开就带着横向滚动条。

  • 目录树和文件列表叠成了一列。 原来它们是并排两栏,而在一个深层插件目录里,这意味着 264px 的一栏
    只装一个文件,旁边那棵树却要 780px 高、只有 740px 可用——已经在滚了。这两者是反相关的:树越深,
    叶子里的文件越少。叠起来共用一列之后,编辑器在 1600px 视口下从 800px 涨到 914px,1440px 下从
    640 涨到 754。

    叠放的代价是高度,答案是两块各自的标题栏:点「目录」或「文件」就把那一块收成一条 28px 的横栏,
    把高度整个让给另一块——改一个已经找到的文件时收起目录,要换地方时收起文件。中间的分界线可以拖,
    双击复位,位置和收放状态都按实例记住。

  • 目录树只列文件夹了,展开状态按实例保留。 同一个控件在两个模式下含义不同要学两遍;而且在这条
    216px 的边栏里,它多出来的那些文件名是预先截断好的(banned-players...),比它临时顶替的那份列表
    还难读。树回答「我在哪」,列表回答「这里有什么」。原来那个「筛选已展开的目录」输入框一并去掉,
    目录过滤由顶栏搜索覆盖。

  • 文件列表加了「紧凑 / 详情」两种密度,列的增减只由这个开关控制。 此前打开一个文件,列表会静默把
    「修改时间」抽掉——从真正要紧的那个视角看(找服务器最后动过哪个文件),这就是一秒钟前还在的列没了。
    行尾的下载 / 重命名 / 删除三个常驻图标改成 hover 才出现,删除收进 ⋯ 菜单里、红色、末项;删除文件夹
    现在要求把文件夹名字打出来才能提交,world、plugins、libraries 这类目录还会多一条警告。
    选中任意一项后,列表头会换成批量操作条。

  • 编辑器支持多标签与左右分屏。 页面上一直写着「可以同时开着几个对照」,实现却只有一个标签。标签
    带未保存圆点、中键可关、⌘/Ctrl+W 关当前、上限 12 个(超出时只淘汰已保存的),右键有关闭 / 关闭
    其他 / 关闭右侧 / 复制路径。「配置历史」从底部按钮条挪到标签栏右侧——它是「关于这个文件」的入口,
    不是编辑动作;底部只剩「还原」和「保存」两个按钮,Ctrl+S 那行说明改成了保存按钮的提示气泡。

  • 改动过的行在编辑器里看得见,也能逐行还原。 与上次保存的版本逐行比对,改动行的行号上警告色底、
    正文左侧一条竖条,鼠标停在行号上会出现「还原此行」。这和「配置历史」是同一件事的两端:改之前看得见,
    改之后回得去。另外补上了查找替换、自动换行开关、只读模式,以及日志文件按 INFO / WARN / ERROR 着色。

  • 面包屑每一段都可以点,末段右边留了一块可点区域。 点下去整条面包屑变成输入框,可以直接粘贴一条
    从日志里复制出来的路径回车跳转;路径不存在会在原地说明并且不跳。深层目录下中间省略,不换行也不溢出。

  • 保存前会先比对磁盘上的修改时间。 文件在面板外被改过时,保存会停下来问:用我的覆盖、放弃我的改动
    重新加载、还是并排看看差异。编辑器在前台时每十秒查一次,磁盘变了而本地没有改动就直接静默重载,
    有改动则在顶部挂一条提示。服务器运行中保存 server.properties 这类配置,保存成功后会提示需要重启
    并给一个「重启」按钮。

    这里要说清楚的是:面板的读接口不返回修改时间、写接口也不接受条件写,所以这个比对是在浏览器这一侧
    做的,有竞态——两次请求之间仍然可能被写入。它比不看强(窗口从「标签开着多久」缩到毫秒级),
    但不是保证,等接口带上 mtime 或 ETag 之后应当换掉。

  • 通知、警告和报错现在有了统一的去处。 面板里「给人看一句话」这件事此前由一个样式类兼职了五种
    语义,用在 45 个文件里的 141 处:页面加载失败、表单实时校验、保存成功、下载进度、主机巡检告警,
    长得一模一样。现在它们分成三个面——刚才发生了什么弹在右下角(多条向上堆叠,各自计时),
    现在是什么情况留在页面里,这一页没能加载紧贴页头。判据是「能用 if (条件) 渲染的不是消息」。

    对操作者最直接的三个变化:失败提示不再顶着绿色对勾弹出(此前下载失败、上传失败、入库失败都是
    绿的);失败提示不再六秒后自己消失,要点「知道了」才走;开关机失败切换页面后仍然看得见——而开关机
    正是最可能立刻切走去看别处的操作,此前一走那条失败就没了。

    Java 页和数据库页的平台说明改回黄色警示,此前被误画成红色出错。

  • 全部页面的排版重做了一轮,这次是把「同一件事只有一种写法」落到代码里。 改之前,一个卡片段的
    标题有五种写法、列表上方的工具行有七种、「这里没有东西」有六种、卡片里的行列表有六套逐字节相似的
    样式,页头右边的按钮从 0 个到 4 个不等。每一种单看都没错,凑在一起就是「越改越乱」:一页页读下来,
    面板像七个人各拼一块。

    现在每个页面读起来都是同一句话:页头(标题、一句说明、常驻事实、最多两个按钮加一个溢出菜单)→
    错误 → 页内切换 → 列表的工具行 → 若干个段 → 空状态或骨架屏。段一律是 <Section>,工具行一律是
    <Toolbar>,空状态一律是 <EmptyState>,卡片里的行一律是 .rowlist > .row。

    看得见的变化:页头的元数据 chips 从右边挪到说明下面(它们在右边会被挤到第二行,悬空在标题旁边);
    插件页原来一行四个按钮加一个链接、配置历史一行四个其中一个是危险操作,现在都是「两个按钮 + ⋯」,
    少用的和危险的进溢出菜单;文件页的查找框挪到工具行最右端,伸手去按「上传」不会落进过滤框。

    断点从九档(560/780/820/900/1024/1200/1240/1280/1300,好几档只差二三十像素)收敛到四档:
    1240 侧栏收窄、1024 侧栏变抽屉且所有「侧栏 + 正文」的两栏布局都在这一档收成一栏、780 表格开始
    丢列、560 手机。所有「侧栏 + 正文」的布局现在在同一个数字上收拢,而不是各收各的。

    这套语法有守卫看着:panel--form / panel__head / panel__body 只许 Section.tsx 写,
    empty__* 只许 EmptyState.tsx 写,构建时直接卡。样式表顺带瘦了约 900 行 —— 删的全是迁移后
    再没有任何组件引用的规则。

  • 一屏只留一个实心按钮。 实心按钮是一句断言——「这一屏,你要做的是这件事」;一屏两个就是两句,
    读的人两个都得看一遍。这次收掉 13 个:概览页、数据库页、文件页、插件页、网络页、创建向导、插件库
    列表和抽屉。

    最明显的是列表:插件库里每一行的「更新入库 / 对齐 / 处理」、插件抽屉矩阵里每行的「恢复库内版本 /
    升到 X」、网络页每个代理端卡片上的「连接」——一个行内动作只要是实心的,它就每行实心一次,而一屏里
    每行都实心,等于一个实心按钮都没有。这些全部改成描边。

    留下的那个给「这一屏此刻在要你做的事」:表单的提交、向导页脚的下一步、空状态的 CTA、素色段头里那个
    唯一的主入口。告警横幅里的按钮反而降成描边——横幅本身已经有警示色的底和描边,再实心是同一句话说两遍。
    概览页的「+ 新建实例」和数据库页的「新建数据库」会在空状态/表单展开时自动让位,两种状态下都恰好一个。

  • 「新建数据库」的表单改成左右两栏。 左边一句话说明这一段是干什么的,右边是字段,跟实例设置、
    Velocity 配置那几处一致。字段也按宽度分档了:引擎、库名、显示名、用户名、密码都收到 380px —— 一个
    库名的输入框没有理由铺满 880px,看一眼就该知道要填多长。用户名和密码并排成一行——它们是一套账号的
    两半,分两行读着像两件事。窄屏放不下时各占一行。库名和密码那两段超过一句的说明折进了可展开的
    「为什么」里:留在外面的是填的时候要遵守的规则(「字母开头,只能用字母、数字和下划线」),
    展开才看的是背后的道理。

  • 设置类表单的段标题回到卡片头的位置。 实例设置、Velocity 配置、创建向导、新建数据库这四处的
    表单原本是左右两栏:段标题和一句话说明站在字段左边。实际效果是一句两行的说明占着一个三百像素宽、
    四百像素高的格子,那片空白读起来是卡片上的一个洞,而不是留白。现在标题、说明、字段从上到下排,
    跟面板里其他卡片一个形状;字段仍然封顶 880px,多出来的宽度留在右边。

  • 「服务端 jar」的下拉框换成面板自己画的那一个。 实例设置、创建向导和导入实例这三处的 jar 文件名
    用的还是浏览器原生的补全列表 —— 那个弹窗是系统画的,读不到面板的任何一个配色令牌,所以在一个精修过
    的表单中间掉出一块方角白底的列表,明暗主题都不跟着走。面板早就为「选 Java 环境」写过自绘的下拉,
    这三处是漏下的。

    换过来之后:明暗两种主题都对,弹窗跟其他浮层一样淡入淡出,方向键 / Enter / Esc 都在,屏幕阅读器
    能念出当前高亮的是哪一行。并且每个 jar 后面多了一行文件大小 —— 原生补全列表只能显示一列文本,
    放不下它,而这正是从一堆名字相近的 jar 里认出服务端那个的依据。想填一个目录里还没有的名字照样可以
    直接输,跟以前一样。

    插件源对话框和插件抽屉里的「用哪个令牌读」「版本锁定」三处原生下拉也一并换掉;令牌的尾号从跟在
    名字后面挪到了第二行,同一个账号下的两个令牌现在分得清了。

  • 「服务端核心」和「下载核心」合成一页。 侧栏里这两行变回一行:核心库在上,下载在下,一屏之内
    从「我有什么」走到「再拿一个」,不用先点一次二级导航。Java 环境和数据库环境早就是这个形状 ——
    当初拆成两页是因为下载区有一整屏高,而核心这边可下的只有 Paper 和 Velocity 两个,选择器就一行,
    版本列表本来也封着高度,拆开的结果是核心库独占一屏、下面空着三分之二。

    下载进行中的提示从侧栏的「下载核心」挪到了侧栏页头那行字(显示「正在下载…」),和 Java 安装中的
    提示一致。/library/cores/download 这样的旧链接照常打开核心页,不会 404。

  • 实例设置页重排。 每张卡片现在是左边一句「这一段是干什么的」、右边一列字段,字段按内容定宽 ——
    内存那种只填四位数的框不再和文件路径一样宽,所有输入框的左边缘对齐在同一条线上。原先的排版把列数
    交给窗口宽度决定(1440 下正好三列),于是同一行里会出现三种宽度的输入框,六行的说明被塞进三百像素
    的窄格。

    长解释折进「为什么?」,点开才展开,正文一字未改。「开服前检查」没问题时收成页头下的一行,不再占
    一张卡;「从核心库安装」折进「启动方式」,就在它写的那个「服务端 jar」字段旁边。

    「保存设置」改成只在有改动时浮出的贴底条,旁边多了「放弃」;「从面板移除」和「删除实例及所有文件」
    挪进页尾独立的「危险操作」区 —— 它们原先和保存按钮在同一行的两端。

    代理配置页和新建实例向导的表单跟着同一套排版走。

  • 文件页没开文件时不再留一栏空编辑器。 那一栏原先一直占着三分之一的宽度,里面只写着「点一个文件
    会在这里打开」,而旁边的列表为了让出这点宽度,在任何窗口下都把「修改时间」那一列丢掉了。现在它收
    成零宽、随着打开文件滑开(和侧栏折叠同一种动效),列表在没开文件时拿回整栏宽度和「修改时间」。

  • 「编辑模式」从工具栏挪到路径那一行,做成一张小卡片。 它原先是四个按钮里的第四个,和「新建
    文件夹」长得一模一样 —— 但那三个是对文件做事,这一个是换一整屏的用法。现在它带一句「列表让位,
    目录树带上文件」,并且在列表变窄时不会被挤到第三行去。

  • Java 环境和数据库环境各自合回一页,下载源那一页重排。 三处都是同一个问题:一屏能看见的
    东西太少。

    两个资源库不再拆成三个侧栏入口。 Java 环境原来是「已安装 / 安装新版本 / 下载设置」三页,
    数据库环境是「我的数据库 / 已装引擎 / 安装引擎」三页 —— 拆开是因为当年后两件事各占一屏,
    可现在每页只剩一张卡,1440 宽的屏幕有七成是空的。合回来的前提是后两件事都瘦了:可安装是一行
    一个版本的瓦片,发行版和下载源收成「可安装」卡头里的两个小选择器。已安装仍然在最上面 ——
    当初拆页要保的就是这一条。旧链接(/library/java/install 这类)不会 404,会落到合并后的那一页。

    安装进行中原来靠「安装新版本」那一行的徽章提示,那一行没了,改在侧栏标题下面写「正在安装…」。

    资源清单有表头了。 Java 运行时、数据库、服务端核心这三张清单,原来每一行都自带「体积」「安装于」
    这样的字段名 —— 一列不变的标题,有几行就印几遍。现在列名在清单顶上写一次,行里只剩值,八个运行时
    从八屏收成一屏。1240px 以下栏位本来就会并成一组,那时表头自己收起来、每行的字段名照常回来,所以
    窄屏和手机上什么都没少。

    「可安装」的按钮回到了行上。 原来是先点一个版本选中、再到表单下面找「安装」按钮;现在每个版本
    一行,安装按钮就在这一行的右端,一步到位。镜像类型(JRE / JDK)、发行版、下载源都收进卡头 ——
    它们是这次下载的属性,不是某个版本的,摆在列表上方会比列表本身还显眼。数据库的三个引擎同理,
    收成卡头里的一排小按钮。

    数据库页拆成了「表格 + 详情栏」。 连接串、JDBC 地址、密码原来长在每一行里,四个数据库就是四屏,
    而且真正要逐字读的那一行每次出现在页面的不同位置。现在左边是表格,右边一栏固定放着选中那个库的
    连接信息、要粘进插件配置的两行、自启开关和删除。1240px 以下详情栏落到表格下面。

    下载源那一页的镜像列表装进了一个框里。 五个单选是同一个问题的五个答案,一个带边框的列表才这么说;
    代理前缀单独占一栏,手机上落到说明下面 —— 挤在名字旁边会把说明压成一行一个词。

  • 插件市场从一列宽行改成了卡片网格,筛选条件重新摊开在左边。 结果现在是一格一个插件:项目图标放大到
    40px、名字一眼能扫、简介给足两行而不是截在半句话上;下载量、更新时间、加载器这些原来行里有的事实一条没
    少,都在卡片下半部分,每一行卡片的按钮对齐在同一条线上。找插件的第一遍不是从头读十条,是挑出那四五条值得
    读的,宽行在这一步给不了落眼的地方。

    筛选从「参照 / 来源 / 仅兼容 / 更多筛选」四个要点开才看得见的气泡,变回左边一条 208px 的栏:分类列表、
    参照实例的勾选、来源、排序、是否含客户端模组全部摊开。分类和排序是设一次就决定整页结果的东西,收在关着的
    气泡里等于没说。「搜索」按钮的约定没变 —— 改筛选不会自动发请求,点了才走。

    结果条数旁边新增一排「生效中」的筛选气泡,每个带 ×,可以一个一个摘掉(摘掉立刻重搜),末尾是「清除」。
    以前生效的条件根本看不见,一个很短的结果列表没法解释自己为什么短。

    窄屏:768px 以下筛选栏折进一个「筛选」按钮(里面有东西时带一个小圆点),结果紧跟着搜索框;再窄一档卡片
    收成一列。实例页里的「市场」标签用的是同一套,它比整页窄一个侧栏,所以栏和结果是按容器宽度自己换行的,
    不是按窗口宽度。

  • 页面开头的说明文字不会再被右边的一排事实挤断。 标题和页面自己的事实(路径、状态徽章、按钮)
    原来抢同一行,遇上一个特别深的数据目录时说明文字被压到不足一半宽、断在句子中间。现在挤到看不下去的
    时候,右边那排自己换到下一行,说明文字保住能读的宽度;事实本来就窄的页面,看起来和以前一模一样。

  • 卡片内部的密度收紧了一档:卡片纵向内边距和行距各收 2px,资源表格行高从 52px 收到 50px。横向
    不动 —— 横着一收,卡片里的表格就贴边了。

  • 「启动设置」里的顺序改成跟命令行一致:Java 环境 → 服务端 Jar → 内存 → JVM 参数 → 服务端参数,
    从上到下就是 java -Xmx… <JVM 参数> -jar server.jar <服务端参数> 从左到右。

  • 「从脚本读启动参数」从表单中间那个输入框改成了一个弹窗,入口挪到 JVM 参数旁边。原来那一行杵在
    表单正中,把一个会改五个字段的控件摆在了其中一个字段的标题底下;弹窗能在动手之前先说清楚它要动什么。

  • 在已有实例上读脚本,不再覆盖 Java 环境和服务端 Jar。 实例建好之后这两项归面板管(Java 在
    「资源库 → Java 环境」,核心在核心库),一个 2019 年的 run.sh 把 /usr/lib/jvm/java-8 塞回来
    是倒退。脚本里写了什么照样读出来给你看,只是不往表单里填 —— 「这服以前跑在 Java 8 上」恰好解释了
    它为什么在 Java 25 上起不来。内存、JVM 参数、服务端参数和参数文件还是照常导入:参数文件面板
    没有别的途径能拿到,那串带精确版本号的 unix_args.txt 路径只能从脚本里读或者一个字一个字敲。
    「导入现有目录」不受影响,那会儿面板还没接管任何东西,Java 和核心照旧从脚本里读。

  • 进了资源库的某一个货架,另外四个也还在侧栏里。 以前进了「Java 环境」就只剩它自己那三页,想去
    「服务端核心」得先「返回面板」再点一次。而这五个货架本来就是按配一台服的顺序排的 —— Java 跑核心、
    核心装插件、插件要数据库 —— 那是一条会一口气走完的路,导航却偏偏不让走。现在当前货架的页面下面
    多一组「其他资源库」,横着挪一格是一次点击。

  • 二级侧栏的出口回到了左上角,并且按钮写的是去哪儿。 它一度挪到栏底,理由是顶栏返回键已经指着
    同一个地方;实际用下来,导航栏的左上角就是找「返回」时手先过去的位置,这个反射比省下一行更值钱。
    文案保留了改好的那一版:写去哪儿——「返回面板」「返回实例列表」——而不是「上一级」。

    收起侧边栏挪到了栏底,而且每一层都有:栏子多宽是对整根栏子的设定,属于栏底那个安静的位置。[
    照旧在任何一层都能折叠。

  • 面板不再执行任何人的启动脚本。 脚本从「启动方式」变成「参数来源」:读完原样留在目录里不动,启动
    一律由面板自己拼命令行。

    这么改是因为面板读不懂的启动设置就是面板管不了的启动设置 —— 脚本一旦接管命令行,内存框、Java 选择、
    内存图表的 -Xmx 参考线就全成了摆设,而摆设比没有更坏:它让人以为自己设过了。顺带消失的是一整类坑:
    脚本里的 nohup / screen / tmux / 行尾 & 会把 JVM 交出去、让面板秒判「已停止」而服务器还开着,
    现在它们只是解析时剥掉的一层外壳,不再需要警告。

    升级时存量的脚本实例会被自动转换:面板读一次它们的脚本,把参数写进配置。转不了的不会静默失败 ——
    实例会被拦住不让开服,「开服前检查」里说明原因并原样列出它原来的启动命令,照着填好启动设置就能开。

    「启动设置」页跟着变了:「面板拼命令/用我的脚本」换成「核心 jar/参数文件」,JAVA_TOOL_OPTIONS
    开关去掉了(它本来就只在脚本模式下有意义)。

  • Java 的「下载源」页改名「下载设置」,发行版和下载源在同一页选。下载源列表现在跟着发行版走:
    清华、南大、华为、GitHub 加速都是 Adoptium 发布树的镜像,对 Zulu 不适用,所以选中 Zulu 时不再列出。

  • 快照版本号换成 snapshot-<提交数> 了。 以前叫 0.5-snapshot.213,读起来像「0.5 的预览版」,
    可 0.5 里会有什么、什么时候发、甚至发不发,在打这个快照的时候都还没定 —— 那个版本号是替一个没人
    决定过的版本占位。快照不是冲着某个版本去的,它就是 main 在那个提交的样子,而那个提交唯一确定的
    数字是提交数。tag 也不带 v 前缀了,后面跟的不是语义化版本,加个 v 只会让人以为是。

    行为上有一处变化:正式版发布不再把快照面板拉回正式版轨道。 规则改成「快照排在所有正式版之上」——
    这更符合事实,正式版是从 main 上切出去的,快照里本来就有那些代码,被「更新」到正式版其实是往回走。
    快照通道从此只跟 main,想回正式版轨道就在更新页把通道切回「正式版」。另外发布提交现在也发一版
    快照
    ,这样快照通道拿得到跟正式版一模一样的代码,不会停在发布前一版。

    已经装了旧式快照的面板不用管:0.5-snapshot.213 照样能解析,新式排在它之上,下一版快照会正常推
    过去 —— 这正是上一条(更新检查先学会读新格式)先做的原因。

  • 每个页面都用同一个页头开场了。 之前只有资源库、主机和面板设置下的页面顶上有「标题 + 一句说明 +
    右侧操作」这一套;实例里的八个分页各开各的:控制台顶着服务器名,监控顶着一排时间筛选,文件直接是
    一张卡,插件和配置历史是一行 16px 的小标题加一串按钮,服务器配置顶着一排文件标签,实例设置又是
    一张卡——而且比别的页面整体低一行。一页一页点过去像八个人各写了一块。现在这八页和概览页都用
    Page 同一个页头(PageHead),标题就是侧栏上那个词,说明一句,操作靠右,第一行和所有别的页面
    对齐;控制台的服务器名也放大到跟页标题一样。概览页多了标题和一句说明,「新建实例」从「实例」小节
    上移到页头,跟别的页面放主要操作的位置一致。

  • 几处零散的排版顺手理了。 控制台顶部三个数字块在平板宽度下不再只占半行(能撑满时撑满,屏幕
    不够宽才横向滚);「外观」页像素字体那段说明不再从卡片右边溢出去(两条重复的规则各加了一次
    24px 缩进);「下载队列」的「进行中」「历史」两节装进卡片,跟插件库其他页面一个样;「节点配置」的
    SSH 终端一节收成一张带标题的卡片,事实栏和上面「本机」那张对齐,起始目录整行显示且能换行。

  • 面板的图标换成 README 上那个立方体了。 侧栏、登录页和浏览器标签页此前挂的是 ⛏ 字形,
    而 README 顶上是 docs/images/logo.svg 的等距立方体 —— 同一个项目在两个地方长着两张脸。
    现在三处都用立方体,标记本身收在 web/src/components/Logo.tsx 里,只有一份。
    侧栏和登录页的方块底仍然跟着主题走(深色下底色和墨色对调),标签页图标没有主题可跟,
    固定用浅色那套渐变。

  • 更新检查现在认识 snapshot-<提交数> 这种快照版本号。 工作流暂时还在发 0.5-snapshot.86,
    这一步只是让面板提前能读懂以后的命名——做版本比较的是已经装在机器上的那个二进制,它要是解析
    不了新格式,就会把那种 tag 整个跳过并一直显示「已是最新」。所以解析必须先发出去、等它装进大家的
    面板,改名才能安全进行。两种格式现在都能比:snapshot-N 之间按提交数排,整体排在所有正式版之上
    (正式版是从 main 上切出去的,快照里本来就有那些代码),切回「正式版」通道照样提示装回最新正式版。

  • releases 页上的快照从留 5 份改成留 3 份。 面板更新永远只提供最新的那一份,更早的快照
    点不到——它们只是给人手动下载用的,留五份除了占页面没别的用处。

  • 「代理连线」从面板最外层挪进了实例,而且两头都有。 它以前是侧栏「实例」组下的一整页,
    理由是一条连线是两个实例之间的事实、谁都不独占 —— 这句话对的是事实,错的是导航:面板
    最外层因此摆了一个关于代理端的页面,而大多数人一个代理端都不跑,它也是那一层里唯一一个
    不是「地方」而是「关系」的入口。

    现在它是每个实例都有的一节,各看各的那一半:代理端看「后面挂着哪些服务端」,
    服务端看「前面站着哪个代理端」。连线还是同一张画布、同一套动作 —— 拖一条线过去,
    面板照样把两边六处配置一起改好 —— 只是这一半被过滤成了跟你有关的那一半。这才是当初那句
    「谁都不独占」真正要的结果:两头都看得见,两头都能动手。

    从服务端这一侧也看得见代理端后面的其他子服,只是置灰、不带按钮 —— 名字仍然可以点,
    点了就到那台服务端自己的页面上去改。一开始这些行是被过滤掉的,那等于画了一张少了几行的
    [servers] 表:你看不出自己是四个大厅里的哪一个,也看不出 lobby2 这个名字已经被占了,
    而这恰恰是有人打开这张卡要问的事。同理,从代理端那一侧现在也能看出某个服务端已经挂在
    另一个代理端后面
    了。规矩很简单:这张卡上有按钮的行是你的,没按钮的行不是。
    (「面板外」那种指向别的机器的行也跟着一起收进底色里 —— 它本来就没有按钮,却是整张卡上
    最扎眼的一行。)

    /network 这个地址留着,书签和 ⌘K 里的「代理连线」都还能用,会落到最该打开的那一头
    (有代理端就是代理端)。

  • 侧栏实例行的缩进改成了看得出来的 12px。 原来是 20px 内边距配一个 10px 的圆点列,
    名字正好落在其他标签右边 3 像素的位置 —— 看得见,但不像是故意的,而这是一个缩进最糟的
    距离。圆点现在站在上面那些图标用的同一个 18px 字形列里,两种行共用一套节奏,差别只剩缩进。

  • 侧栏分组标题按中文来排。 11px、0.08em 字距加 text-transform: uppercase 是拉丁文
    全大写小标题的排法,而这里每个标题都是两三个汉字:大写完全没起作用,字距反而把右边的
    「0/3」推离了各行对齐的那条边。顺便把左内边距对齐到了它所覆盖的那些标签。

  • 实例侧栏多了「配置历史」一项,排在「服务器配置」下面 —— 问题就是从那里来的:改了一个文件,
    服务器起不来了,接着想看的就是这个文件昨天长什么样。

  • 配置历史的时间线默认显示「全部」,不再默认「重要」。默认藏起来的行,需要先有人告诉你它被藏
    起来了,你才敢信这条时间线是完整的。「重要」还在,仍然是一键的事。

  • 实例首页的 CPU / 内存读数、以及磁盘用量的百分比,现在会走到新数值上,不再直接跳过去。 面板
    每五秒采一次样,所以一个实时数字大部分时间是静止的,然后突然换一个 —— 而一次跳变不带方向:47%
    接替 12% 和 47% 接替 52% 长得一模一样,可瞄一眼 CPU 想知道的恰恰就是它在往哪走。数值沿着进度条
    已经在用的那条曲线(--dur-data / --ease-out)走过去,于是条和数字是一起动的。

    第一个读数直接落位,不从 0 数上来 —— 那是秒表,不是仪表;服务器没在跑的时候仍然显示「—」而不是
    0。开了「减少动态效果」的读者拿到的还是直接跳变。

  • 开关机按钮换字的时候不再是硬切。 启动 → 启动中… → 停止 是服务器在改变状态,而两帧之间换掉
    文字恰好是眼睛最容易漏掉的那种变化,偏偏发生在最需要知道服务器在干什么的那一行上。现在字是淡入
    的,按钮本身一动不动 —— 按钮元素保持不变,键盘焦点才不会在操作中途掉到页面上;也没有任何位移,
    因为这排按钮是用来停掉有人在线的服务器的,指针够过去的时候目标不该还在动。

移除

  • 不再支持非 Java 的服务端。 基岩版的 bedrock_server 这类原生二进制过去是靠「自定义启动命令」跑的,
    随该功能一并移除 —— 它没有 JVM,也没有任何启动参数可供面板读取和管理。请继续用 systemd 之类托管它们。

修复

  • 修好文件编辑器里光标和选区错位。 滚到一个长文件的末尾时,光标画在文字上方十几像素处,选中一段
    会在两行之间浮出一份错位的副本,行号也跟着对不上。三层(行号、语法高亮、真正在输入的文本框)原先
    靠互相抄 scrollTop 对齐,但 wrap="off" 会在文本框里放一条横向滚动条,它比另外两层矮了一条滚动条
    的高度,也就能多滚这么多 —— 多出来的部分另外两层够不着,被悄悄截断。改成用 transform 摆位,不存在
    截断,三层在任何位置都对得上。

  • 插件库、插件源设置里的一批小号按钮一直是全尺寸。 它们要的那个样式类在样式表里根本不存在,
    所以那 16 个按钮比设计的大一圈,把所在的操作行撑高。同一批修好的还有:警告徽章的描边着色失效
    (同一个类被写了两遍,后一遍把描边丢了);插件源对话框里那份发布附件列表被挤成居中一团、还压着
    一层棋盘格背景(它和文件预览重名,两个组件互相抢样式);配置历史的差异行少了基础排版;Java 环境、
    服务端核心、新建实例向导里那句「装到哪里」的说明是正文大小的主文字色,读起来和旁边的按钮一样响。

    这几处的共同原因是样式类名写错了既不报错也不报警,元素只是安静地渲染成没样式的样子。现在构建时
    会检查,这类问题不会再悄悄留下来。

  • 侧栏「概览」上那个待处理数字不再一律画成错误红。 它现在按里面最严重的那一条上色,和概览页
    那几行告警本身是同一套:出事了是红的,提醒是琥珀色的,「有个插件能更新」这种就是一个普通计数 ——
    跟两行之下「插件库」的那个数字长得一样,因为它们本来就是一回事。以前无论哪一级都是红的,于是
    一个插件有新版本看上去和一台服崩了没有区别,而红色在这个面板里只该是后一种意思。

  • 「从脚本读启动参数」旁边那个按钮不再歪着。 它跟输入框底下那三行说明文字的底边对齐,而不是跟
    输入框对齐 —— 随着那一整行改成弹窗,造成歪斜的那个容器在这一页不存在了。

  • 装 Azul Zulu 的 Java 25 会卡在「download exceeds the declared 61117500 bytes」。 Azul 的
    元数据接口把这个包的体积报少了 9 个字节(声明 61117500,CDN 上实际是 61117509),而那 61117509
    个字节的 SHA-256 恰好就是 Azul 自己公布的那一个 —— 包是好的,数字是错的。以前面板拿这个数字当
    硬性关卡,于是一个完全正确的下载被判成失败,偏偏 Zulu 又只有官方 CDN 一个源,提示里的「换个源
    再试」根本无处可换。现在有校验和时就以校验和为准,声明的体积只用来画进度条;没有校验和的来源
    仍然按体积严格核对,那时它是唯一的检查。

    Java 运行时、服务端核心、插件三处下载都照这个改了,上游哪天把体积报错,不会再变成一个装不上
    的包。三处的下载错误也都改成了中文(以前是半英文的 download exceeds the declared …),并且
    下载中途断掉会直说「下载中断,只收到 X 字节」,而不是报一个看不出所以然的校验和不符。

  • 插件下载现在会核对来源公布的校验和。 Hangar 每个文件都公布 SHA-256,面板一直把它读进来、
    存起来,却从来没拿它比对过下载到的字节 —— 镜像给了个过期或者不对的 jar 也照收不误。现在对不上
    就拒收,文件不会进插件库。

    Modrinth 公布的是 SHA-512(它不发 SHA-256),面板以前干脆没读这个字段,现在一并读进来并核对,
    于是两大插件源的下载都是验过的了。SHA-1 故意不收 —— 三个里最弱的那个,收了就等于给攻击者
    留了挑算法的余地。GitHub 发布页和 SpigotMC 确实什么校验和都不公布,那两类来源的信任仍然只到
    HTTPS 为止,跟以前一样。

    插件库记录的那个 SHA-256 不受影响:它一直是面板自己按收到的字节算的,是全局对账用的身份,
    不是凭证 —— 一个用 SHA-512 验过的 jar 照样按 SHA-256 入账。

  • 开着像素字体时,各个货架列表里的日期被截成「2026/08/09 1…」。 「安装于」「加入于」「建于」共用
    一条固定宽度的栏位,那个宽度是按默认字体量的:同一个日期在默认字体下要 102px,在像素字体下要 139px,
    而栏位是 132px —— 于是省略号吃掉了几点几分,留下了世纪。旁边两条弹性栏位有的是富余。

  • 建筑卡片的「尺寸」被截成「121 ×…」。 尺寸、方块、种类是均分的三等份,于是「58」和
    「121 × 41 × 121」拿一样宽。三个加起来其实装得下,只是按个数分而不是按需要分。现在按内容比例分,
    并且真到最窄的那一列时换行而不是截断 —— 尺寸没有有用的前缀,截在哪儿都得点开才知道这张卡片是什么。

  • 数据库「已装引擎」里的「安装于」比别处截得更狠。 那一行只有两个字段却要占三条栏位,占位格放在了
    末尾,把日期挤进了 96px 的窄栏。占位格现在放在最前面,日期落回该落的宽栏。

  • 配置历史里点「与出厂对比」、或者展开一个空文件的改动,会让整个面板变成白屏。 后端的 diff 在
    两边内容相同、或者文件本身是空的时候不返回任何差异块,前端把它当成数组去读长度,一个渲染期的
    异常就把整棵 React 树卸载了。现在这两种情况会照实说「磁盘上的内容与这个版本一致」和「这是一个
    空文件」。

  • 「与出厂对比」以前要点两次才有反应。 第一次点只是选中了最早那条快照,它要打开的文件在选中
    变化时又被清掉了。现在一次点到位,并且顺带切到「全部」筛选,免得选中的那条自动快照根本不在
    左边的列表里。

  • 一个页面渲染出错不再让整个面板变白。 实例的每个分区、以及面板的主内容区各有一层错误边界:
    出错的那一页显示错误信息,侧栏、顶栏和其他分区照常可用 —— 控制台尤其不会被别的页面带下去。

安装

下载对应平台的压缩包,解压后直接运行:

tar -xzf hypercraft-0.5.0-linux-amd64.tar.gz
cd hypercraft-0.5.0-linux-amd64
./hypercraft -data ./data

前端已经嵌在二进制里,不需要另外部署。开机自启参考包内的
hypercraft.service。

校验

sha256sum -c SHA256SUMS.txt --ignore-missing