跳转至

聊天与名称显示修改(Chat & Display)

玩家看到的「表面功夫」——聊天消息长啥样、头顶名字是什么、Tab 列表里叫什么,都能用 KubeJS 改。这篇把三块整合成一个章节:

  • 聊天消息修改:加前缀(称号/权限)、替换敏感词、拦截消息;
  • 头顶名称修改displayName 覆盖玩家名字(头顶 + Tab 列表一起变);
  • Tab 面板修改:Tab 列表显示的就是 displayName,改名字 = 改 Tab。

💡 这篇是「实现称号系统(29 篇)」的显示层深化——29 篇把三者用在称号上,这篇讲透原理和通用玩法。


1. 聊天消息修改

监听 PlayerEvents.chat,改 event.message 就能改写玩家发出的消息(改的是服务端最终广播出去的内容,全服都看到改后的)。

1.1 加前缀(称号 / 权限 / 随便什么)

// server_scripts/display_chat_prefix.js
PlayerEvents.chat(event => {   // 监听"玩家发消息"
  let player = event.player
  let title = player.persistentData.title   // 读玩家当前称号 id(29 篇存进去的)

  if (title && title !== 'none') {   // 有称号就加前缀
    event.message = '§7[' + title + ']§r ' + event.message   // 效果: [killer] 大家好
  }
})

💡 更正式的称号显示(带颜色、查称号表)直接抄 29 篇:event.message = title.color + '[' + title.name + ']§r ' + event.message

1.2 替换敏感词

// server_scripts/display_chat_filter.js
const BAD_WORDS = ['敏感词1', '敏感词2', '敏感词3']   // 要替换的词表(服主可自己加)

PlayerEvents.chat(event => {
  let msg = event.message   // 先存到 let 变量里(后面要重新赋值,不能用 const)
  BAD_WORDS.forEach(word => {   // 遍历词表
    msg = msg.replaceAll(word, '***')   // 把词替换成 ***(replaceAll 替换全部)
  })
  event.message = msg   // 写回消息
})

1.3 拦截屏蔽(不让发出去)

event.message 置空,消息就发不出来了:

// server_scripts/display_chat_block.js
PlayerEvents.chat(event => {
  let msg = event.message

  if (msg.includes('脏话A') || msg.includes('脏话B')) {   // 命中屏蔽词
    event.player.tell('§c这条消息包含违禁词,已拦截!')   // 只告诉本人
    event.message = ''   // 置空 = 不广播(null 也可以,'' 更稳)
    return
  }

  if (msg.startsWith('!') ) {   // 以 ! 开头的当指令处理(这里只是示例拦截逻辑)
    // 比如配合 29/31 篇的 !称号 !签到 指令,在别的事件里已经处理过,这里就不用管
  }
})

⚠️ 拦截后玩家自己会「看到」消息已发送,但全服没人收到——想更明显可以同时 player.tell 提示原因(上面的例子就是)。

1.4 只允许特定格式

// server_scripts/display_chat_restrict.js
PlayerEvents.chat(event => {
  let msg = event.message
  if (!msg.startsWith('[交易]')) {   // 不允许直接喊话,必须先打 [交易] 标签
    event.player.tell('§c请使用格式:[交易] <你要卖的东西>')
    event.message = ''
  }
})

2. 玩家头顶名称修改

player.displayName 是玩家的「显示名」——设置后头顶名字、Tab 列表名字、聊天里的名字都会变(原版机制)。它存在客户端显示层,服务器重启后会还原,所以要在登录事件里重新设置。

// server_scripts/display_name.js —— 头顶名称完整流程
function applyName(player) {   // 封装成函数:给谁设置显示名就调谁(改称号后也调它刷新)
  let title = player.persistentData.title   // 读称号(没有就是 undefined)
  if (!title || title === 'none') {   // 没称号
    player.displayName = player.username   // 恢复成默认名(原版名字)
    return
  }
  player.displayName = '§6[' + title + ']§r ' + player.username   // 带称号的名字
}

PlayerEvents.loggedIn(event => {   // 登录时设置一次(重启后也能恢复)
  applyName(event.player)
})

// 用法:改称号后立刻刷新名字
// applyName(某玩家)   // 29 篇的切换称号指令里就是这么调的

💡 displayName 不影响存档、不影响指令选择器(@a 还是按真实 ID 匹配),只是显示层面的花活,随便折腾。


3. Tab 面板修改

Tab 列表(按 Tab 键打开的那个玩家列表)显示的名字就是玩家的 displayName——所以第二节的 applyName 一改,Tab 列表同步生效,不需要额外 API。

按身份显示不同 Tab 名字的完整示例:

// server_scripts/display_tab.js —— 按身份显示不同 Tab 名字
function applyName(player) {
  let data = player.persistentData

  if (player.isCreative()) {   // 创造模式 = 管理员(跟 29 篇管理指令同一个判断)
    player.displayName = '§c★ 管理 §r' + player.username
  } else if (data.vip) {   // 存档里打了 vip 标记(充值/活动发的)
    player.displayName = '§d✦ VIP §r' + player.username
  } else if (data.title && data.title !== 'none') {   // 有称号
    player.displayName = '§6[' + data.title + ']§r ' + player.username
  } else {
    player.displayName = player.username   // 普通玩家
  }
}

PlayerEvents.loggedIn(event => applyName(event.player))   // 登录时刷新

💡 判断身份的三个思路:player.isCreative()(创造=管理员,最简单)、persistentData 标记(data.vip = true,可后台发)、29 篇的称号表(unlocked/title)。

Tab 面板顶部/底部文字(header/footer):KubeJS 1.20.1 没有可靠的现成 API,不建议强行实现(硬写要碰网络包,容易崩)。想要这个效果,要么等 KubeJS 更新,要么用专门的模组。名字修改这一层,上面完全够用。


4. 整合案例:一键全装

一个文件实现:聊天加称号前缀 + 敏感词替换 + 违禁词拦截 + 管理员特殊颜色 + 头顶/Tab 名字带身份:

// server_scripts/display.js —— 聊天与名称显示完整案例
const BAD_WORDS = ['脏话1', '脏话2']   // 屏蔽词(直接拦截)
const FILTER_WORDS = ['敏感词A', '敏感词B']   // 替换词(替换成 ***)

// —— 聊天:前缀 + 过滤 + 管理员颜色 ——
PlayerEvents.chat(event => {
  let player = event.player
  let msg = event.message

  // 1. 拦截违禁词
  if (BAD_WORDS.some(w => msg.includes(w))) {
    player.tell('§c消息含违禁词,已拦截!')
    event.message = ''
    return
  }

  // 2. 替换敏感词
  FILTER_WORDS.forEach(w => { msg = msg.replaceAll(w, '***') })

  // 3. 加前缀:管理员红色 / 有称号用称号 / 普通玩家原样
  if (player.isCreative()) {
    msg = '§c[管理]§r ' + msg
  } else {
    let title = player.persistentData.title
    if (title && title !== 'none') msg = '§6[' + title + ']§r ' + msg
  }

  event.message = msg
})

// —— 名字:头顶 + Tab 同步 ——
function applyName(player) {
  if (player.isCreative()) {
    player.displayName = '§c★ 管理 §r' + player.username
  } else if (player.persistentData.vip) {
    player.displayName = '§d✦ VIP §r' + player.username
  } else if (player.persistentData.title && player.persistentData.title !== 'none') {
    player.displayName = '§6[' + player.persistentData.title + ']§r ' + player.username
  } else {
    player.displayName = player.username
  }
}

PlayerEvents.loggedIn(event => applyName(event.player))   // 登录刷新(重启后也能恢复)

效果:

聊天:  [管理] 服主: 大家好
头顶:  ★ 管理
        服主
Tab:   ★ 管理 服主

5. 速查表

功能 关键代码 说明
聊天加前缀 event.message = '前缀' + event.message PlayerEvents.chat 里改写
替换敏感词 msg.replaceAll(word, '***') 词表循环替换
拦截消息 event.message = '' 置空 = 不广播,可配 player.tell 提示
格式限制 msg.startsWith('[交易]') 判断 不符合就拦截
设置头顶名 player.displayName = 'xxx' 同时影响头顶 + Tab + 聊天名
恢复默认名 player.displayName = player.username 还原原版名字
登录刷新 PlayerEvents.loggedIn(event => applyName(event.player)) 重启后必须重新设置
管理员判断 player.isCreative() 创造模式当管理员(与 29 篇一致)
Tab 名字 displayName 即可 原版机制,无需额外 API
Tab header/footer ❌ 无可靠 API 1.20.1 不建议强行实现

还能玩什么? 聊天颜色渐变(拼接多段 § 颜色码)、死亡播报样式(结合 09 篇事件列表找死亡事件)、称号 + 权限 + 交易分区聊天(player.server.players 遍历定向转发)——核心就是 event.messagedisplayName 两个入口,思路都是一样的。