BLZYの自定义进度

BLZYの自定义进度

将原版进度界面替换为基于画布的高度自定义成就系统,支持7种条件类型,包括NBT物品匹配、前置链、维度锁定、批量编辑、原版浏览以及实时服务器同步。

Advancement Overhaul 是一款面向 Minecraft 1.21.1(NeoForge)的进度系统全面重构模组。它完全替换原版进度界面与底层逻辑,提供可自由缩放、拖拽、编辑的无限画布 UI、10 种条件类型、前置依赖链、维度锁定、原版进度管理、完整的 /adv 命令树以及 KubeJS 和 FTB Quests 深度兼容。模组同时面向生存玩家和整合包/地图作者,支持在游戏中实时创建、编辑、导入导出自定义进度。


一、主要功能

1.1 原版成就的禁用与管理

本模组允许对原版(及其他模组)的成就进行精细控制:

  • 默认禁用:配置项 vanilla.defaultEnabled 默认为 false,所有原版成就在首次安装时默认禁用,需要手动启用。
  • 按命名空间白名单:通过 mods.enabledMods 配置自动启用的模组命名空间列表(如 ["minecraft", "create"]),该模组下所有成就自动创建分类并启用。
  • 单个启用/禁用:/adv vanilla enable <id> / /adv vanilla disable <id> 对单个原版成就进行开关。
  • 批量操作:/adv vanilla enableall / /adv vanilla disableall 一键启用或禁用所有原版成就。
  • 运行时过滤:通过 AdvancementManagerMixin 在进度加载阶段将禁用的原版进度从运行时 Map 中移除,禁用进度完全不可见、不可触发。
  • 玩家登录检查:玩家登录时自动撤销所有已被禁用的原版进度,防止残留完成状态。
  • 服务端拦截:即使某些途径(如命令)触发了被禁用的原版进度,ServerEventHandler 也会立即撤销。

工作流程:

服务器启动 / reload
  └── AdvancementManager.apply()
      ├── [Mixin HEAD] 缓存原版 JSON → 注入自定义进度
      └── [Mixin RETURN] 过滤禁用的原版进度 → 仅保留启用的
          └── filterDisabledVanillaFromMap()
              ├── defaultEnabled = false → 移除所有不在启用列表中的
              └── defaultEnabled = true  → 仅移除明确禁用的

1.2 自定义画布 UI 与父子成就树形显示

模组提供全新的无限画布 UI,完全取代原版进度界面:

  • 无限画布:支持鼠标滚轮缩放(以光标为中心)、中键/拖拽平移,带平滑惯性动画。
  • 成就卡片:每个进度以卡片形式在画布上展示,包含图标、名称、完成状态指示和条件进度条。
  • 树形依赖连线:
    • 采用直角树状图风格绘制成就之间的前置依赖关系:父级竖线 → 水平线段 → 子级竖线,拐点处有圆角连接点。
    • 自动识别三种依赖来源:自定义进度前置条件、原版 parent 关系、原版进度关联的自定义前置条件(VanillaAdvMeta)。
    • 连线颜色区分状态:普通连线、已完成连线(绿色高亮)、选中项的前置/后继连线。
    • 选中某个成就时,其直系前置和直系后继卡片分别以不同背景色高亮显示。
  • 树形布局:通过 BFS 遍历原版进度的 parent 关系计算每个进度的树深度,按层分组排列。
  • 自动布局(AutoLayout):基于 DAG 拓扑排序的三阶段布局算法——Phase 1 自顶向下重心启发式 → Phase 2 自底向上父节点居中 → Phase 3 最终重叠修正,支持同时布局自定义和原版进度。
  • 标签页系统:支持多标签页切换、拖拽排序、重命名、创建/删除,可将不同进度分类组织。
  • 空间网格索引:将卡片按世界坐标分桶到 480px 的网格单元,渲染时仅处理视口范围内的单元格,支持千级卡片流畅渲染。

1.3 猫爪成就牌匾

当玩家完成一个成就时,屏幕顶部会出现一个带有猫咪元素的精美牌匾 HUD 动画:

  • 视觉设计:
    • 深紫色背景(#24163E / #362058)搭配薰衣草色边框(#E8C0FF)
    • 金色标题文字 "✦ 成就达成 ✦"
    • 左右对称的完整小猫爪印(1 个主肉垫 + 4 个趾垫扇形排列,浅粉色 #FFB6C1)
    • 分隔线两侧各有迷你猫爪装饰
    • 底部脚印轨迹(成对的迷你爪印)
    • 四角星星闪烁点缀
  • 动画效果:
    • 滑入阶段(400ms):easeOutBack 回弹缓出曲线,从屏幕上方优雅落位
    • 停留阶段(2400ms):完全显示
    • 淡出阶段(300ms):easeInQuad 渐隐
  • 队列系统:同时完成多个成就时自动排队依次展示,不会重叠
  • FTB 任务完成:FTB Quests 任务完成时也会触发牌匾显示
  • 通过 HUD Overlay 实现,无论当前打开什么界面都能显示

二、维度管理

通过维度锁定系统,可以在玩家完成指定成就之前阻止其进入特定维度:

  • 锁定维度:/adv dimension lock <dim> 阻止玩家进入指定维度
  • 解锁维度:/adv dimension unlock <dim> 解除锁定
  • 设置解锁条件:/adv dimension setcondition <dim> <advId> 绑定一个成就作为解锁条件
  • 移除解锁条件:/adv dimension removecondition <dim> 移除条件(维度保持锁定但无需成就解锁)

工作机制:

  1. 玩家尝试传送至被锁定的维度时,ServerEventHandler.onEntityTravelToDimension() 拦截传送事件
  2. 检查目标维度的 DimensionLock:如果 disabled = true 且玩家未完成 unlockAdvancementId 指定的成就
  3. 取消传送事件,将玩家传送到当前维度的安全位置(优先重生点,其次传送门周围地面)
  4. 向玩家发送提示消息
  5. 1 秒冷却防止同一 tick 内多次弹出消息

数据存储:维度锁配置持久化在 ServerDataStore 中,以 JSON 格式存储。


三、自定义图片

在无限画布上可以自由添加 PNG 图片作为装饰或背景:

  • 图片存放目录:config/advancement_overhaul/images/(手动放入 PNG 文件)
  • 持久化文件:config/advancement_overhaul/image_elements.json(保存图片位置和属性)
  • 格式限制:仅支持 .png,最大 16MB
  • 操作方式:
    • 右键空白画布 → 上下文菜单 → "创建图片" → 从 images/ 目录选择文件
    • 图片可拖动移动位置
    • 图片可缩放(放大 1.25x / 缩小 0.8x),缩放范围 0.1x ~ 5.0x
    • 图片可锁定防止误拖动
    • 右键图片可删除
  • 渲染:使用 DynamicTexture + NativeImage 加载为 Minecraft 纹理,注册到 TextureManager

四、Config 设置

配置文件路径:config/advancementoverhaul-common.toml(NeoForge COMMON 类型,服务端+客户端共享)

配置项 类型 默认值 说明
interface.hideVanilla boolean false 是否用自定义 Canvas UI 替换原版进度界面
permission.editPermissionLevel int (0-4) 2 编辑命令所需的最低权限等级(2 = OP 级别)
toast.duration int (ms) 3000 Toast 通知显示时长(500-30000ms)
performance.playerDataSaveInterval int (ticks) 6000 玩家数据定期保存间隔(约 5 分钟)
vanilla.defaultEnabled boolean false 原版/模组进度的默认启用状态(false = 默认禁用)
mods.enabledMods List<String> [] 自动启用的模组命名空间白名单(如 ["minecraft", "create"])

五、指令系统

主命令为 /adv,支持权限分级和 Tab 补全。

玩家操作

命令 说明
/adv complete <id> [player] 强制完成成就(跳过前置条件检查)
/adv reset <player> <id|all> 重置玩家单个或全部进度
/adv give <id> [player] 授予成就
/adv revoke <id> [player] 撤销成就
/adv check <id> 查看进度状态(完成/待定/进度百分比)

CRUD 操作

命令 说明
/adv delete <id> 删除自定义成就
/adv batchdelete <ids,...> 批量删除
/adv setname <id> <name> 设置名称
/adv setdescription <id> <desc> 设置描述
/adv seticon <id> <icon> 设置图标(物品/实体/方块 ID)
/adv togglehidden <id> 切换隐藏状态
/adv setprereq <id> <ids,...> 设置前置条件(含循环依赖 BFS 检测)
/adv createjson <json> 通过 JSON 创建成就
/adv updatejson <json> 通过 JSON 更新成就

工具命令

命令 说明
/adv import 从 import/ 文件夹扫描 JSON 文件导入数据
/adv export 导出所有数据到 export/ 文件夹
/adv autolayout 对当前标签页执行自动布局
/adv reload 重载所有数据并重新同步

维度管理

命令 说明
/adv dimension lock <dim> 锁定维度
/adv dimension unlock <dim> 解锁维度
/adv dimension setcondition <dim> <advId> 设置解锁条件
/adv dimension removecondition <dim> 移除解锁条件

标签页管理

命令 说明
/adv tab add <name> 创建新标签页
/adv tab delete <name> 删除标签页
/adv tab order <name1,name2,...> 设置标签页排序

原版成就管理

命令 说明
/adv vanilla enable <id> 启用单个原版成就
/adv vanilla disable <id> 禁用单个原版成就
/adv vanilla enableall 启用所有原版成就
/adv vanilla disableall 禁用所有原版成就
/adv vanilla setpos <id> <x> <y> 设置原版成就在画布上的位置
/adv vanilla settab <id> <tab> 将原版成就分配到指定标签页
/adv vanilla cleartab <id> 清除原版成就的标签页分配
/adv vanilla save <id> 保存原版成就的当前配置

六、KubeJS 兼容

模组通过 kubejs.plugins.txt 自动注册为 KubeJS 插件,提供两类集成:

6.1 脚本 API(Bindings)

在 KubeJS 脚本中通过 AdvancementOverhaul 对象直接调用:

// 查询
AdvancementOverhaul.getAllIds()                          // 获取所有自定义成就 ID
AdvancementOverhaul.getName("my_adv")                    // 获取成就显示名称
AdvancementOverhaul.isCompleted(event.player, "my_adv")  // 是否已完成
AdvancementOverhaul.getProgress(event.player, "my_adv")  // 进度百分比 (0-100)

// 操作
AdvancementOverhaul.complete(event.player, "my_adv")     // 强制完成
AdvancementOverhaul.reset(event.player, "my_adv")        // 重置

// 创建(链式构建器)
AdvancementOverhaul.builder("my_adv")
    .name("我的成就")
    .description("描述")
    .tab("默认")
    .pos(100, 200)
    .hidden(false)
    .condition("kill_entity", "minecraft:zombie", 10)
    .conditionNbt("kill_entity", "minecraft:skeleton", 20, "{}")
    .prerequisite("other_adv_id")
    .register()

6.2 事件监听

在 KubeJS 脚本中监听模组事件:

// 成就完成事件
AdvancementOverhaul.completed(event => {
    console.log(`Player ${event.player.name} completed ${event.advancementId}`)
    console.log(`Achievement name: ${event.advancementName}`)
})

// 进度更新事件
AdvancementOverhaul.progress(event => {
    console.log(`${event.advancementId}: ${event.progress}/${event.total}`)
    if (event.completed) {
        // 完成时 progress >= total
    }
})

// 成就重置事件
AdvancementOverhaul.reset(event => {
    console.log(`${event.advancementId} was reset for ${event.player.name}`)
})

七、FTB Quests 兼容

模组与 FTB Quests 实现深度双向集成:

7.1 FTB 任务作为成就条件

  • 条件类型 FTB_QUEST_COMPLETE 允许将 FTB 任务完成作为自定义成就的前置条件
  • 通过 Architectury 事件监听(实时)和 Tick 轮询(每 20 tick 兜底)两种方式检测任务完成
  • 任务完成时自动触发条件评估和级联释放

7.2 FTB 成就奖励的条件检查

  • 当 FTB 任务将自定义成就作为奖励时,AdvancementRewardMixin 在 claim() 方法执行之前拦截检查
  • 如果成就是自定义成就且条件未满足,直接取消 claim() 调用——不会先授予后撤销
  • 条件满足才放行,让 FTB 正常授予,后续事件同步到自定义系统

7.3 KnownServerRegistries 同步

  • 自动将自定义成就 ID 注册到 FTB 的 KnownServerRegistries,确保 FTB 团队界面能正确显示成就完成状态
  • 客户端连接时自动同步,FTB 模组未加载时静默降级
  • 通过反射获取 FTB Quests 版本号并输出日志

7.4 属性变更通知

  • 当成就的名称、图标、描述、隐藏状态等属性变更时,自动调用 ServerQuestFile.markDirty() 通知 FTB 存盘

八、技术信息

项目 说明
MC 版本 1.21.1
模组加载器 NeoForge
Java 版本 21
配置类型 COMMON(服务端 + 客户端共享)
数据存储格式 JSON(分别存储在 advancements/、players/、tabs/、vanilla/ 目录下)
条件类型 10 种(KILL_ENTITY / CRAFT_ITEM / GET_ITEM / BREAK_BLOCK / PLACE_BLOCK / CHANGE_DIMENSION / DEAL_DAMAGE / TAKE_DAMAGE / FISH_ITEM / FTB_QUEST_COMPLETE)
条件逻辑 AND(所有条件均满足才算完成)
评估模式 Instant(一次性检测)/ Progress(累积进度追踪)/ Stack-aware(GET_ITEM 背包追踪)
NBT 匹配模式 IGNORE / CONTAINS / EXACT / NONE_EMPTY
级联完成 BFS 栈遍历,64 层上限,防循环依赖
网络同步 全量同步(GZIP 压缩)+ 增量同步(实时进度更新)
C2S 安全 命令白名单 + 频率限制(5条/秒)+ 服务端权限二次校验

新增自定义资源替换系统

资源文件夹

启动时自动在 config/advancementoverhaul/resources/ 创建文件夹和 README.txt 说明文件。

可替换资源

资源 文件名 格式 说明
牌匾纹理 plaque.png PNG,推荐 240×56 替换牌匾背景,文字叠在上面
完成音效 chime.wav mp3 PCM 完全替换默认紫水晶旋律