AdvancedScoreboard 是一个基于 Fabric 开发的 Minecraft 模组,旨在为服务器提供可配置、自动化的计分板管理能力,支持多计分板轮播展示、玩家数据自动同步、配置热更新等特性,开箱即用地提供挖掘量、放置量、在线时长、鞘翅飞行距离、受到伤害、死亡次数、击杀生物数等维度的计分板统计。
- 多维度计分板统计
- 挖掘量:统计玩家破坏方块的数量
- 放置数量:统计玩家放置方块的数量
- 在线时长:基于游戏内置统计,自动计算玩家在线小时数
- 鞘翅飞行距离:统计玩家使用鞘翅飞行的公里数
- 受到伤害:统计玩家受到的伤害值
- 死亡次数:统计玩家的死亡次数
- 击杀生物数:统计玩家击杀生物的数量(不包含击杀玩家)
- ...
- 自动轮播切换:配置化的计分板轮播
- 数据自动同步:定时将配置数据同步到游戏内计分板,并自动保存到本地配置文件
- 配置热加载:修改配置文件后无需重启,切换/保存间隔实时生效
- 默认配置初始化:首次启动自动生成默认配置,支持配置加载失败自动回退
- 命令系统
- 查询榜单:玩家可通过
/asb scoreboard指令查询任意榜单的全部数据 - 配置项修改:OP 可通过
/asb set指令动态修改轮播间隔、保存间隔、最大显示数量 - 全局显示控制:OP 可通过
/asb notDisplay指令全局隐藏/显示指定榜单
- 查询榜单:玩家可通过
/asb
├─ set # 仅 OP 可用
│ ├─ switchInterval <value> # 修改轮播间隔(秒,最小 1)
│ ├─ saveInterval <value> # 修改保存间隔(秒,最小 1)
│ ├─ maxDisplayNum <value> # 修改榜单最大显示玩家数(最小 1)
│ └─ border <value> # 修改榜单显示名边框(默认 "===")
│
├─ scoreboard <displayName> # 所有玩家可用,查询指定榜单的全部数据(不受最大显示数量限制)
│ # 支持 Tab 自动补全 displayName
│
└─ notDisplay <displayName> # OP 玩家可用,切换指定榜单的显示/隐藏状态
# 支持 Tab 自动补全 displayName
- 支持自定义计分板名称和显示名
- OP 可全局控制榜单显示/隐藏,轮播时自动跳过已隐藏的榜单
- 服务器启动时自动同步配置数据,保证数据一致性
- 配置文件兼容旧版本,新增字段自动设置默认值
采用「配置驱动 + 事件监听 + 定时任务」的核心架构:
- 初始化流程(
AdvancedScoreboard.java)- 加载/初始化全局配置
- 注册指令系统(
/asb set、/asb scoreboard、/asb notDisplay) - 注册服务器启动、玩家破坏/放置方块等核心事件
- 服务器启动事件(
ServerStartedEvent.java)- 初始化全局计分板实例
- 注册配置中的计分板,同步已持久化的玩家数据
- 启动轮播切换、数据同步定时任务
- 定时任务(
Task.java)- 计分板轮播:由
ServerTick事件驱动,根据hiddenScoreboards过滤隐藏榜单,通过setObjectiveSlot(SIDEBAR)全局切换显示 - 数据同步:定时从 Minecraft Stats 读取在线时长/飞行距离/伤害/死亡数据,按
maxDisplayNum截取前 N 名同步到游戏内计分板
- 计分板轮播:由
- 配置管理(
Config.java/ScoreboardItem.java)- 基于 Jackson 实现 JSON 配置的加载/保存
- 支持默认配置初始化、旧版配置兼容(新增字段自动填充默认值)
- 事件监听(
PlayerBreakBlockEvent.java/PlayerPlaceBlockEvent.java)- 监听方块破坏/放置事件,实时更新挖掘量/放置量计分板数据
配置文件路径:config/advanced_scoreboard.json
{
"border": "===", // 榜单显示名边框(可自定义),实际显示为 border+displayName+border
"switchInterval": 5, // 计分板轮播间隔(秒),最小1秒
"saveInterval": 5, // 数据保存间隔(秒),最小1秒
"maxDisplayNum": 15, // 榜单最大显示玩家数量,最小1
"hiddenScoreboards": [], // 全局隐藏的榜单 internalName 集合
"scoreboards": [ // 计分板列表
{
"internalName": "mine_count", // 内部标识(唯一)
"displayName": "挖掘量", // 显示名称(不含边框)
"data": {} // 玩家-分数映射(自动维护)
},
{
"internalName": "place_count",
"displayName": "放置量",
"data": {}
},
{
"internalName": "online_time",
"displayName": "在线时长(h)",
"data": {}
},
{
"internalName": "elytra_dist",
"displayName": "飞行距离(km)",
"data": {}
},
{
"internalName": "damage_taken",
"displayName": "受到伤害",
"data": {}
},
{
"internalName": "deaths",
"displayName": "死亡次数",
"data": {}
},
{
"internalName": "mob_kills",
"displayName": "击杀生物数",
"data": {}
}
]
}- 配置
displayName修改计分板显示名称 - 重启服务器,模组会自动注册新的计分板
- 可通过修改
data字段手动设置玩家分数(需等待同步周期生效)
src/
├── main/
│ ├── java/cn/hycer/advancedscoreboard/
│ │ ├── AdvancedScoreboard.java // 模组主类
│ │ ├── Command/ // 指令系统
│ │ │ ├── ASBCommand.java // /asb 指令注册与共享 SuggestionProvider
│ │ │ ├── SetCommand.java // /asb set 子指令
│ │ │ ├── ScoreboardCommand.java // /asb scoreboard 子指令
│ │ │ └── NotDisplayCommand.java // /asb notDisplay 子指令
│ │ ├── Config/ // 配置相关
│ │ │ ├── Config.java // 根配置类
│ │ │ └── ScoreboardItem.java // 单个计分板配置
│ │ ├── Event/ // 事件监听
│ │ │ ├── PlayerBreakBlockEvent.java // 玩家破坏方块事件
│ │ │ ├── PlayerKillMobEvent.java // 玩家击杀生物事件
│ │ │ ├── PlayerPlaceBlockEvent.java // 玩家放置方块事件
│ │ │ └── ServerStartedEvent.java // 服务器启动事件
│ │ ├── Global/ // 全局变量
│ │ │ └── Global.java // 全局日志、计分板、配置
│ │ └── Task/ // 定时任务
│ │ └── Task.java // 轮播、同步任务
│ └── resources/
│ ├── fabric.mod.json // Fabric 模组元数据
│ ├── advancedscoreboard.mixins.json // 通用 Mixin 配置
│ ├── log4j2.xml // 日志配置
└── client/ // 客户端代码(占位)