1安装与启用
LinuxTAB 不需要前置插件,一个 jar 就能跑。队伍、头衔、假人都是可选的联动项:装了谁就接谁,没装也只是少一块信息,不会报错、不会影响其它功能。
- 把
LinuxTAB-26.11.8.jar放进服务器的plugins/目录。服务端用 Paper 或 Spigot 1.12.2,Java 8 及以上。 - 重启服务器。第一次启动会生成
plugins/LinuxTAB/config.yml,默认就是「2 列 × 20 行、补空位、延迟列开」。 - 看一眼控制台的启动摘要,确认列数、补位、延迟列、PlaceholderAPI 都是你要的状态。
- 之后改配置只需要
/linuxtab reload,不用重启服务器;玩家列表会在下一次刷新(默认 20 tick)内变过来。
正常启动时控制台是这样两行:
如果第二行里某一段写的是「未检测到」,说明对应的插件没装或没启用,那一项功能会自动关掉,其余照常工作。想让队伍、头衔、假人都显示出来,把 LinuxTeam、LinuxTitle、FakePlayerPlugin 一起装上即可,LinuxTAB 启动时会自己认。
配置放在哪
插件的所有配置都在一个文件里,没有子目录、没有数据库:
改完存盘,执行 /linuxtab reload。如果配置写错(缩进错了、键名拼错),插件不会崩,会在控制台打一行黄色警告并保留旧配置继续跑,修好再 reload 一次就行。
2布局:怎么让人少也是多列
1.12.2 的客户端把玩家列表画成一张固定网格:每列固定 20 行,最多 4 列。行数是客户端写死的,服务端改不了;服务端唯一能决定的是「谁被塞进第几列第几行」。
所以在线只有 12 个人的时候,如果只发 12 个条目,客户端就只画一列 12 行,右边三列是空的——看起来根本没有多列。LinuxTAB 的做法是按列补位:把空条目补齐到整列(20 的倍数),多列布局在人少时也成立,题目里的「人少也是多列」就是这么来的。
配置项
| 键 | 默认值 | 说明 |
|---|---|---|
layout.columns | 2 | 列数,取 1 ~ 4。1.12.2 客户端只认 4 列,写大于 4 会被压回 4。 |
layout.rows | 20 | 每列行数。1.12.2 客户端就是 20,改小只会让补位少填几行,一般不要动。 |
layout.pad-empty | true | 人数不足时用空条目补满整列。关掉它,人少时就只剩一列。 |
layout.include-fakes | false | 假人要不要出现在 TAB 里。默认 false:每轮刷新都会把 FakePlayerPlugin 加进来的假人条目移除,列表里只有真人。改成 true 后假人排在真人上面。 |
layout.fakes-first | true | 假人排最前面(true)还是按 layout.sort 和真人混排(false)。只有开了 include-fakes 才有意义。 |
layout.fill | column | column = 先填满第一列再换列,真人紧跟在假人下面;balance = 按列均分,几列的高度尽量一样。 |
layout.empty-name | &7 | 补位条目显示的名字。留一个颜色码就是一条看不见的空白,不要写成文字,否则列表里会多出 20 个「空」。 |
layout.empty-skin.value | "" | 补位条目的皮肤纹理值(base64)。不填就是客户端默认的白色 Steve 头。 |
layout.empty-skin.signature | "" | 上面那个纹理值对应的签名,两个要成对填。 |
两种填充方式怎么选
column 是默认值:假人排第一列开头,真人接着往下排,第一列满了才换第二列,视觉上最像「一列名单接着一列名单」。balance 会把总数平均摊到每一列,比如 30 个人分 2 列就是 15 + 15,看起来更对称,代价是玩家进出的瞬间偶尔会看到整列重排。
一个完整的布局配置
3顺序规则(重要)
LinuxTAB 发出去的最终顺序是:真人(各自队伍)→ 补位空行。真人按队伍聚在一起,空行全部沉底。假人默认不进列表,需要的话在配置里打开 layout.include-fakes,打开后假人排在真人上面。
客户端会自己重排,你要顺着它来
1.12.2 客户端拿到玩家列表后并不会照抄服务端给的顺序,它会按三个键重新排序:是否旁观 → 计分板队伍名 → 玩家名。也就是说,服务端发过去的顺序会被打乱一遍,插件必须让「排序结果」也符合预期,否则你看到的永远是乱序。
补位空条目就是这里最容易翻车的:它们没有队伍、名字又只有一个颜色码,客户端一排就会把它们排到中间去,于是「真人被空行挤到中间」或者「真人掉到最后一行」。LinuxTAB 的处理是——把补位空条目全部塞进一个队名以 U+FFFF 开头的计分板队伍里,这个字符比任何正常字符都大,客户端按队伍名排序时必然把它们排到最后,空行就永远沉底了。
/scoreboard teams list 里看到它,插件停用时会一起清掉,下次启动再建回来。
假人默认不显示
假人是 FakePlayerPlugin 创建的服务器端玩家,它为了让假人有皮肤、也让别的插件(经济、在线统计)认得出它,会自己把假人加进玩家列表——客户端随即会把假人画进 TAB。LinuxTAB 默认的处理是把假人条目摘掉:每轮刷新都发一次移除,进服瞬间也会补一刀,所以列表里只有真人。
想看到假人,把 layout.include-fakes 改成 true 再 /linuxtab reload。打开后假人排在真人上面(用的是假人自己的 UUID,不会和真人重条目),顺序是假人(无队伍)→ 真人(各自队伍)→ 补位空行。
layout.include-fakes。
5动画与打字机
头尾面板里的文字可以动起来:按帧轮播,或者用打字机一个字一个字打出来。动画定义在 animations 下面,用 %animation:<名字>% 引用。
配置项
| 键 | 默认值 | 说明 |
|---|---|---|
animations.<名字>.style | frames | typewriter = 打字机逐字显示;frames = 按 frames 列表轮播。 |
animations.<名字>.interval | 4 | 每帧间隔,单位是 tick。4 = 每 0.2 秒一帧。 |
animations.<名字>.frames | [] | frames 模式下的文字列表,从头循环。 |
animations.<名字>.text | "" | typewriter 模式要打出来的那一整句。 |
animations.<名字>.color | &f | 打字机文字的颜色,写一个颜色码即可。 |
animations.<名字>.hold | 30 | 打完(或收完)之后停留多少帧再继续,单位同样按 interval 算。 |
打字机的完整过程
以 text: "欢迎回来" 为例,一整个循环是这样的:
欢 → 欢迎 → 欢迎回 → 欢迎回来(停 hold 帧)→ 欢迎回 → 欢迎 → 欢 → 空(停一下)→ 从头再来。
也就是打完不会硬切回空,而是原路收回去,看起来像有人在敲键盘又删掉。想让收字更快,把 hold 调小即可;不想收字就直接用 frames 轮播。
refresh-ticks 压到 4,不用你手动改。你手写了 refresh-ticks: 20 也一样会被压下来。
interval 别低于 2,帧数别堆到几十条,否则每个在线玩家每秒都会收到几十次字符串更新。
6玩家名格式
列表里每个名字显示成什么样,由 player-list.name-format 决定。它是一段模板,支持颜色码和几个占位符,插件会把它们换成队伍、头衔和玩家名。
| 键 | 默认值 | 说明 |
|---|---|---|
player-list.name-format | &7[%team%&7] %title%&f%name% | 整行的格式。%team% 队伍名、%title% 头衔、%name% 玩家名。 |
player-list.no-team | &8无队伍 | 玩家没有队伍时 %team% 的值。想直接不显示,把它设成空字符串。 |
player-list.no-title | "" | 玩家没有头衔时 %title% 的值,默认空。 |
layout.max-name-length | 16 | 名字最长显示多少字符,超出的部分截断。列宽有限,太长会把后面的延迟列顶出去。 |
默认格式渲染出来是这样,队伍和头衔各带一层方括号:
prefix 一般已经自带方括号(比如 [元老])。如果你的头衔显示成 [[元老]],把格式里的 %title% 前后的括号去掉,或者把 LinuxTitle 的 prefix 改成不带括号的写法。
&7[%team%&7] %title%&f%name% 这样的长度基本刚好,再往前面加「玩家」「会员」之类的固定文字,长 ID 就会被截断或换行。
7延迟列
延迟列用玩家列表右侧的计分板区域显示每个人的 ping,数值直接取自服务端记录的连接延迟,不额外发包,也不影响性能。
| 键 | 默认值 | 说明 |
|---|---|---|
player-list.ping.enabled | true | 延迟列开关。关掉后右侧计分板不显示 ping。 |
player-list.ping.title | Ping | 计分板标题,也就是这一列最上面那行字。最多 32 个字符,超出的部分会被自动截断。 |
player-list.ping.refresh-ticks | 20 | 更新间隔,20 = 每秒刷新一次数值。 |
单元格的显示格式是 &7%ping% ms 这种风格:前面一个颜色码,中间是数字,后面跟单位。分档着色也会自动做——延迟低的偏绿、偏高偏黄、再高偏红,方便一眼看出谁在卡。
The received string length is longer than maximum allowed)。插件已经会按 32 字符自动截断,这里只提醒别指望长标题能显示全。
8命令
命令不多,日常只用得到 reload。所有子命令都需要 linuxtab.admin 权限,默认只有 OP 有。
| 命令 | 别名 | 说明 | 权限 |
|---|---|---|---|
/linuxtab info | /ltab info | 打印当前状态:列数、每列行数、补位开关、填充方式、在线/假人数量,以及 LinuxTeam、LinuxTitle、FakePlayerPlugin、PlaceholderAPI 四个联动的连接结果。 | linuxtab.admin |
/linuxtab reload | /ltabreload | 重新读取 config.yml 并重建玩家列表、头尾面板和延迟列。配置有错时保留旧配置并在控制台给警告。 | linuxtab.admin |
/linuxtab debug | /ltab debug | 开关调试日志。打开后控制台会额外打印 [布局] 和 [头尾] 两类行,排查顺序和面板问题时用。 | linuxtab.admin |
debug 打开后能看到什么
顺序不对的时候,先看第一行的「合计」是不是 20 的整数倍。不是整数倍说明补位没生效,检查 layout.pad-empty 和 layout.rows;是整数倍但人还是掉到最后,把第二行发出来看空行到底排在第几位。
/linuxtab debug 关掉就好。重启服务器也会自动关掉。
9常见问题
① 看
plugins/ 里有没有 TAB.v6.1.0.jar,有就删掉;② 看根目录有没有
TAB/ 文件夹,那是 TAB 插件的数据目录,一起移走,留着也可能被别的插件读;③ 看有没有
sTablist 这类插件,同样停用;④ 执行
/linuxtab reload,再让玩家退出重进一次。这几步做完还是原版样式,用
/linuxtab info 看插件是否真的启用了,以及控制台有没有报错。
U+FFFF 开头的计分板队伍里,客户端按队伍名排序时它们必然沉底,不会再插到真人中间。如果升级之后还出现,先确认你确实用的是 26.11.8,然后
/linuxtab debug 打开调试,看 [布局] 那行打印的位次——空行应该全部排在所有 player: 之后。顺序对但显示不对,通常是客户端缓存,让玩家退出列表界面再打开一次。
prefix 一般已经自带方括号([元老]),而默认格式 &7[%team%&7] %title%&f%name% 里 %title% 是没有再加括号的,所以正常不会重复。出现双括号说明你在格式里手动加了
[%title%],或者 LinuxTitle 的 prefix 本身就带了一层括号又被你加了一层。删掉格式里多出来的那对括号即可;title() 已经处理过占位,不需要你再包一层。
layout.empty-skin 就行:value 填 base64 纹理值,signature 填对应的签名,两个要成对。想完全看不见,可以把 layout.empty-name 设成只有一个颜色码(默认就是 &7),再配一个接近背景色的透明皮肤。注意换皮肤后客户端要重新拉纹理,让玩家重进一次才会变。
想要稳定可控,建议直接用
&0 ~ &f 和 &l 这些原版色码写配置。等服务器升到 1.16+ 再换 hex 才有效果。
10配置全表
下面这张表是 config.yml 里 LinuxTAB 用到的全部键,默认值和说明都在里面。左边一列可以直接对照你的配置文件。
| 键 | 默认值 | 说明 |
|---|---|---|
layout.columns | 2 | 列数 1 ~ 4,客户端最多 4 列。 |
layout.rows | 20 | 每列行数,1.12.2 客户端固定 20,一般不改。 |
layout.pad-empty | true | 人少时补空条目,保证多列成立。 |
layout.fill | column | column 先填满一列再换列;balance 按列均分。 |
layout.empty-name | &7 | 空条目的显示名,只留颜色码最干净。 |
layout.empty-skin.value | "" | 空条目的皮肤纹理 base64。 |
layout.empty-skin.signature | "" | 与上面成对的签名。 |
layout.max-name-length | 16 | 名字最长显示字符数,超出截断。 |
header-footer.enabled | true | 头尾面板总开关。 |
header-footer.refresh-ticks | 20 | 面板刷新间隔,用打字机时自动压到 4。 |
header-footer.active | default | 默认使用哪套设计。 |
header-footer.designs.<名字>.display-condition | "" | 生效条件,空 = 不限制;多条用 ; 连接。 |
header-footer.designs.<名字>.header | "" | 面板上部文字,\n 换行。 |
header-footer.designs.<名字>.footer | "" | 面板下部文字,\n 换行。 |
animations.<名字>.style | frames | typewriter 打字机 / frames 轮播。 |
animations.<名字>.interval | 4 | 每帧 tick 数,4 = 0.2 秒一帧。 |
animations.<名字>.frames | [] | 轮播用的文字列表。 |
animations.<名字>.text | "" | 打字机要打的整句。 |
animations.<名字>.color | &f | 打字机文字颜色。 |
animations.<名字>.hold | 30 | 打完 / 收完后停留的帧数。 |
player-list.name-format | &7[%team%&7] %title%&f%name% | 列表里每行的格式。 |
player-list.no-team | &8无队伍 | 没队伍时 %team% 的值。 |
player-list.no-title | "" | 没头衔时 %title% 的值。 |
player-list.ping.enabled | true | 延迟列开关。 |
player-list.ping.title | Ping | 延迟列的计分板标题(最多 32 个字符,超出自动截断)。 |
player-list.ping.refresh-ticks | 20 | 延迟数值刷新间隔。 |
designs 和 animations 下面的名字是你自己起的,引用时写 %animation:名字% 要完全一致(区分大小写)。改完记得 /linuxtab reload。