客户端 MOD
LyArmourers 是面向 Minecraft 1.7.10 的 Forge 客户端 MOD,与 Bukkit 服务端插件配套使用。
客户端 MOD 负责时装管理界面、时装预览、玩家与实体时装渲染、手持物品渲染、更多动作骨骼兼容、模型动画、第三人称幻影、刀光、脚印和 LyCustom 粒子。服务端插件负责时装库、物品 NBT、实体时装保存、权限、配置和插件消息同步。
本项目不是完整的时装制作工具。客户端保留的是时装读取、预览、渲染、动作和通信功能,不应将代码中遗留的原时装工坊方块、物品、服务端 GUI 或命令类视为 LyArmourers 的实际运行功能。
运行环境
| 项目 | 内容 |
|---|---|
| Minecraft | 1.7.10 |
| MOD 加载器 | Minecraft Forge |
| Forge 版本 | 1.7.10-10.13.4.1614-1.7.10 |
| Java | Java 8 |
| MOD ID | lyarmourers |
| 显示名称 | LyArmourers |
| 客户端文件 | MOD-LyArmourers-版本.jar |
| 安装位置 | 玩家客户端的 mods 目录 |
| 服务端插件 | PLUGIN-LyArmourers-版本.jar |
模块关系
LyArmourers 分为客户端 MOD 与服务端 Plugin,两部分用途不同。
| 模块 | 安装位置 | 用途 |
|---|---|---|
| 客户端 MOD | 玩家客户端的 mods 目录 | 打开界面、加载资源、解析模型、播放动画并完成全部客户端渲染 |
| Plugin 插件本体 | Bukkit 服务端的 plugins 目录 | 提供配置、时装库、实体时装、物品生成、消息协议、命令、权限、监听器和 API |
模块之间的固定边界如下:
- 客户端 MOD 不直接引用 Bukkit Plugin 的 Java 类。
- 服务端与客户端只通过插件消息通信。
- 客户端 MOD 需要与服务端 Plugin 使用配套版本。
客户端是否必须安装
需要使用以下功能的玩家必须安装客户端 MOD:
- 打开玩家时装管理界面和实体时装管理界面。
- 查看玩家、实体、NPC、物品和手持物品的时装模型。
- 查看
.armour、.lyarmourers和.bbmodel预览。 - 让时装跟随更多动作的玩家骨骼。
- 播放服务端下发的模型动画。
- 显示第三人称奔跑幻影。
- 显示自定义刀光和脚印。
- 接收并显示 LyCustom 粒子。
未安装客户端 MOD时,服务端即使保存了时装数据或发送粒子、动画、刀光、脚印消息,客户端也无法完成对应界面和渲染效果。
客户端主要功能
时装管理界面
客户端包含 manager 玩家时装管理界面,界面由服务端命令通过插件消息打开。
主要能力:
- 显示服务端时装库中的目录和文件。
- 进入子目录或返回上级目录。
- 按名称和时装类型筛选文件。
- 请求并显示时装预览。
- 把时装拖拽到背包物品上,由服务端写入时装 NBT。
- 把多个
.armour文件加入合成列表。 - 输入保存名称并请求服务端合成
.armour。 - 请求服务端创建带时装 NBT 的物品。
界面支持的类型筛选包括:
text
*、头部、身体、腿部、脚部、翅膀、剑、盾牌、弓、镐、斧、铲、锄、套装、方块、物品合成功能只接受真实 .armour 文件,.bbmodel 和 .lyarmourers 不能作为 .armour 合成源。
实体时装界面
客户端包含 entity 实体时装管理界面。
主要能力:
- 列出玩家附近
16格内已经加载的玩家、生物和 CustomNPCs NPC。 - 按距离从近到远排列实体。
- 距离相同时按运行时实体 ID 排列,保持列表顺序稳定。
- 浏览服务端时装库并请求预览。
- 把多个时装加入目标实体的待设置列表。
- 临时设置实体时装。
- 永久保存实体时装。
- 切换目标实体时请求其当前时装列表。
客户端设置和查询实体时装时会同时发送运行时实体 ID 与 UUID。服务端优先使用运行时实体 ID 定位真实 Bukkit 实体,用于处理部分非玩家实体或 CustomNPCs NPC 的客户端 UUID 与服务端 UUID 不一致问题。
玩家和实体渲染
客户端可以渲染以下来源的时装:
- 客户端正在编辑的实体临时时装。
- 服务端同步的实体时装。
- 按实体名称同步的时装。
- 玩家原版装备槽中带 LyArmourers NBT 的物品。
如果显式时装来源中已经存在 outfit,客户端不会继续追加玩家装备槽中的套装兜底,避免重复覆盖。
玩家原版头盔、胸甲、护腿和鞋子槽位中的时装 NBT 是否参与兜底渲染,由服务端配置 render-player-equipment-skins 控制。该开关不影响 API 或实体界面直接设置的时装,也不影响手持物品时装。
物品图标和鼠标预览
带 LyArmourers.skin NBT 的物品可以显示对应的时装模型图标,并在鼠标悬停时显示模型预览。
.armour和.lyarmourers使用时装工坊兼容预览链。.bbmodel使用 LyCustom 模型预览链。- 预览优先显示在原物品 Tooltip 左侧,空间不足时移动到右侧。
- 预览资源尚未返回时显示“正在加载预览”。
- 资源加载完成后,后续绘制帧会自动切换为模型预览。
- 单个模型渲染失败时会回退并记录日志,避免物品栏渲染错误直接中断客户端主循环。
服务端配置 render-item-skin-preview 可以关闭背包和快捷栏中的时装模型图标及 Tooltip 预览。关闭后不会影响第一人称、第三人称手持时装和管理界面预览。
第一人称渲染
第一人称渲染保留 Minecraft 1.7.10 原版 ItemRenderer 的装备切换、挥动、格挡、进食和拉弓矩阵,只替换最终显示的右臂或物品模型。
- 身体型
.armour或.bbmodel可以替换第一人称右臂。 head、legs、feet等不覆盖手臂的时装不会参与右臂替换。sword、bow、tool、item、block等手持型时装只替换手持物品模型。- 资源不存在、未加载完成或模型缺少右臂结构时,继续显示原版手臂或原物品。
- 地图物品继续使用原版双手地图渲染。
- 第一人称不会额外绘制本地玩家完整身体。
物品自身 NBT 指向的时装和实体时装列表中匹配当前物品类型的手持时装都可以参与第一人称渲染。
第三人称手持时装
手持型时装包括:
text
sword、bow、pickaxe、axe、shovel、hoe、shield、item、block客户端会先识别实体当前实际手持物品的类型,再寻找匹配的时装:
- 优先读取当前物品自身的
LyArmourers.skin。 - 物品没有时装 NBT 时,从实体已经设置的手持型时装中寻找匹配项。
- 找到匹配时装后,在更多动作的右手和前臂挂点上绘制模型。
- 没有匹配时装时,继续绘制原版物品。
手持型时装不会被当作身体模型绘制在实体中心。玩家没有手持匹配类型的物品时,对应手持型时装不会强制显示。
更多动作兼容
客户端内置玩家与部分怪物的动作骨骼逻辑,并把时装渲染接入动作后的骨骼矩阵。
玩家动作包括:
- 站立。
- 行走。
- 疾跑。
- 潜行。
- 跳跃。
- 游泳。
- 骑乘。
- 挖掘。
- 弓箭动作。
- 斧类动作。
- 普通攻击和连续攻击。
.armour 会继续使用时装工坊模型渲染链,并把长袖、裤腿和套装腿部分段接入上臂、前臂、大腿和小腿动作。
.bbmodel 会把标准命名的头部、身体、上臂、前臂、大腿和小腿骨骼映射到当前帧的更多动作玩家模型。
服务端强制动画
服务端可以向客户端下发实体模型动画播放和停止消息。
- 播放消息会按实体 UUID 覆盖客户端自动选择的
idle、walk、attack等动作。 - 循环动作可以由服务端保存,并在新玩家连接后重新同步。
- 非循环动作播放完成后会恢复客户端自动动作。
- 停止消息会清理强制动作状态并恢复自动动作选择。
attack、walk、idle、sprint、bow、mining、axe等已识别名称可以直接驱动更多动作骨骼。- 其它动作名需要存在于目标
.bbmodel的动画数据中。
客户端 MOD 本身没有从当前项目运行入口确认出的独立玩家命令。动画、界面、幻影、刀光和脚印等操作由服务端 /lyarmourers 命令和权限控制。
支持的时装格式
| 格式 | 用途 |
|---|---|
.armour | Armourer's Workshop 时装文件,使用内置兼容读取、烘焙和渲染流程 |
.lyarmourers | LyArmourers 兼容后缀,按 .armour 流程读取和渲染 |
.bbmodel | Blockbench 工程、Bedrock geometry 或 LyCustom ModelData 包装 |
客户端预览、玩家渲染、实体渲染和物品渲染均可使用上述格式。服务端 .armour 合成仍只支持真实 .armour 源文件。
.armour 处理能力
.armour 和 .lyarmourers 使用内置 Armourer's Workshop 兼容代码处理:
- 从服务端返回的字节流读取时装。
- 缓存并异步烘焙模型。
- 读取文件中的真实 SkinType。
- 渲染头部、身体、腿部、脚部、翅膀、套装和手持时装。
- 根据时装类型隐藏对应原版模型部位。
- 让玩家时装跟随更多动作的分段手臂和腿部骨骼。
- 捕获不兼容文件版本异常,避免错误文件直接导致客户端崩溃。
.bbmodel 处理能力
.bbmodel 由 LyCustom 模型系统解析,支持以下输入:
- 裸 Bedrock geometry JSON。
- 包含
elements、outliner和textures的 Blockbench 工程。 - 包含
setting、model、animation和textures的 LyCustom ModelData 包装。
支持的 geometry 版本:
text
1.12.0、1.10.0、1.8.0模型可以包含普通贴图和发光贴图。名称包含 _e 或 glow 的贴图会作为发光贴图,带 selected 或 particle 标记的贴图会优先作为主贴图。
常用 setting 字段:
| 字段 | 说明 |
|---|---|
type | 时装类型,默认值为 outfit |
scale | 模型整体缩放,默认值为 1.0 |
offset | 模型纵向偏移,默认值为 0 |
hideHead | 隐藏原版头部 |
hideHeadOverlay | 隐藏原版帽子层 |
hideChest | 隐藏原版身体 |
hideArmLeft | 隐藏原版左臂 |
hideArmRight | 隐藏原版右臂 |
hideLegLeft | 隐藏原版左腿 |
hideLegRight | 隐藏原版右腿 |
部分隐藏字段同时兼容 overrideModel...、hideModel... 和部位名称写法。
.bbmodel 不会仅因为类型是 outfit 就自动隐藏全部原版模型。需要隐藏的原版部位必须由模型 setting 明确声明。手持型 .bbmodel 不参与身体部位隐藏。
类型识别
客户端按以下优先级识别时装类型:
.bbmodel读取setting.type。.armour和.lyarmourers读取文件中的真实 SkinType。- 无法读取时,根据文件名关键词推断。
类型会进行以下归一化:
| 原始类型 | 归一类型 |
|---|---|
chest | body |
armourers:chest | body |
aoe | axe |
arrow | bow |
.bbmodel 没有明确声明 setting.type 时,文件名中的剑、刀、弓、工具等关键词仍可用于识别手持类型,避免模型被默认的 outfit 错误归入身体渲染。
原版模型隐藏规则
.armour 按真实时装类型隐藏原版部位:
| 时装类型 | 隐藏部位 |
|---|---|
| 头部 | 头、帽子层 |
| 身体 | 身体、左臂、右臂 |
| 腿部、脚部、裙子 | 左腿、右腿 |
| 套装 | 头、帽子层、身体、双臂、双腿 |
.bbmodel 只读取模型中明确存在的隐藏开关。多个身体型时装同时存在时,隐藏结果会合并。完成时装渲染后,客户端会恢复原版模型部位状态,避免影响后续实体或后续渲染帧。
CustomNPCs 兼容
客户端对 noppes.npcs.entity.EntityCustomNpc 提供可选兼容,没有安装 CustomNPCs 时不会影响 LyArmourers 启动。
兼容内容:
- 实体管理界面可以列出附近的 CustomNPCs NPC。
.armour和.bbmodel可以作为 NPC 时装渲染。- 时装会读取 CustomNPCs 当前帧已经计算完成的
ModelMPM部位矩阵。 - NPC 的头、身体、双臂和双腿时装跟随 CustomNPCs 自身动作。
- 缺少独立前臂和小腿时,客户端使用固定关节连接时装结构。
- NPC 三轴缩放和模型尺寸会应用到
.bbmodel时装。 - 时装隐藏原版手臂时,客户端会在渲染后按 CustomNPCs 官方手臂挂点补绘主手和副手物品。
- 原模型部位只会按时装自己的隐藏配置关闭,不会无条件隐藏整个 NPC。
LyArmourers 不会修改 CustomNPCs AI、动作触发条件或 setRotationAngles。NPC 实际站立、移动、攻击和手持姿态仍由 CustomNPCs 自身计算,LyCustom 动画层对 NPC 模型固定提交 idle。
当前专用分支只处理 EntityCustomNpc,其它模组生物继续使用通用非玩家实体渲染路径。
动画系统
.bbmodel 动画由 LyCustomAnimationManager 管理。
自动动作选择
| 玩家状态 | 动作候选顺序 |
|---|---|
| 挥手攻击 | attack_连击段、attack、swing |
| 潜行 | sneak、crouch、idle |
| 疾跑 | sprint、run、walk、idle |
| 行走 | walk、run、idle |
| 默认 | idle |
动画运行时可以采样骨骼的 rotation、position 和 scale,并支持 tick、preRender、render、postRender 脚本入口、骨骼显示控制和粒子事件。
为避免模型文件产生外部副作用,动画命令事件默认不执行。
实体模型控制器
项目提供实体模型控制器结构,默认定义以下变量和触发器:
| 项目 | 默认内容 |
|---|---|
| 静止动画 | idle |
| 移动动画 | walk |
| 攻击动画 | attack |
| 死亡动画 | death |
| 初始化触发器 | init |
| 静止触发器 | stand |
| 移动触发器 | walk |
| 攻击触发器 | attack |
| 死亡触发器 | death |
| 动画结束触发器 | animationEnd |
默认死亡逻辑会在存在死亡动画时播放 death,移除死亡计数,并在死亡动画结束后移除实体。
第三人称奔跑幻影
服务端可以按玩家 UUID 开启或关闭第三人称骨骼幻影。
客户端只会在目标玩家处于疾跑状态且确实产生移动动作时创建新幻影。停止奔跑后不再创建快照,已经存在的幻影会继续淡出直至生命周期结束。
客户端接收的参数包括:
| 参数 | 说明 |
|---|---|
lifetime-ticks | 单份幻影的存在时间 |
draw-interval-ticks | 把最近骨骼姿态加入可见队列的间隔 |
snapshot-interval-ticks | 从真实玩家模型读取骨骼姿态的间隔 |
maximum-count | 单个玩家同时保留的最大幻影数量 |
alpha | 最新幻影的不透明度,范围 0~255 |
每份幻影根据剩余生存时间连续计算透明度。服务端关闭目标玩家的幻影后,客户端会立即移除该玩家的全部现有幻影。
自定义刀光
客户端可以根据服务端同步的刀光 YAML,为不同玩家分别显示刀光。
刀光配置支持:
| 配置项 | 说明 |
|---|---|
id | 配置唯一 ID |
texture | 客户端刀光目录下的贴图相对路径 |
red、green、blue | 刀光颜色,范围 0~255 |
alpha | 刀光透明度,范围 0~255 |
additive | 是否使用发光叠加混合 |
lifetime | 刀光保留 tick |
width-scale | 刀光宽度倍率 |
刀光使用更多动作快照或时装武器的真实几何端点生成。.armour 和 .bbmodel 武器会从最终手持渲染矩阵中采集柄端与尖端,形成连续平滑轨迹。
刀光贴图需要放在:
text
<游戏目录>/resourcepacks/LyArmourers/SwordTrails/支持静态图片和 GIF。GIF 首次使用时会预解码合成帧,保留文件内每帧延时并循环播放。
刀光设置为 none 时,玩家使用 MOD 内置默认刀光参数。
自定义脚印
客户端根据玩家左右腿的动作骨骼计算脚底世界坐标。单只脚持续下降后到达最低点并开始回升时,判定为一次落地,并把脚印投射到脚下的真实碰撞面。
脚印配置支持:
| 配置项 | 说明 |
|---|---|
id | 配置唯一 ID |
texture | 客户端脚印目录下的贴图相对路径 |
width | 脚印宽度,单位为格 |
length | 脚印长度,单位为格 |
spacing | 同一只脚连续脚印的最小水平距离 |
lifetime | 未配置有效动画时的兼容生命周期 |
red、green、blue | 脚印颜色,范围 0~255 |
alpha | 脚印透明度,范围 0~255 |
additive | 是否使用发光叠加混合 |
mirror-left | 左脚是否水平镜像贴图 |
animation | 按顺序播放的脚印动画动作列表 |
脚印贴图需要放在:
text
<游戏目录>/resourcepacks/LyArmourers/FootPrints/脚印动画支持:
| 动作 | 参数 | 说明 |
|---|---|---|
delay | 毫秒 | 保持当前状态并等待 |
scale | 目标倍率 毫秒 [缓动] | 同时改变宽度和长度倍率 |
scale-width | 目标倍率 毫秒 [缓动] | 只改变宽度倍率 |
scale-length | 目标倍率 毫秒 [缓动] | 只改变长度倍率 |
alpha | 目标透明度 毫秒 [缓动] | 渐变到目标透明度 |
rotate | 相对角度 毫秒 [缓动] | 在当前角度基础上旋转 |
move | 向右格数 向前格数 向上格数 毫秒 [缓动] | 按生成时的玩家朝向移动 |
color | 红 绿 蓝 毫秒 [缓动] | 渐变到目标颜色 |
可用缓动写法:
| 缓动 | 效果 |
|---|---|
线性 | 全程匀速 |
缓入 | 开始慢,随后加速 |
缓出 | 开始快,随后减速 |
缓入缓出 | 开始慢,中间快,结束慢 |
省略缓动参数时默认使用 缓入缓出。动作名称同时兼容 延迟、缩放、宽度、长度、透明度、旋转、移动、颜色。
存在有效 animation 列表时,动作会按声明顺序播放,后一动作继承前一动作的最终状态;全部动作完成后立即删除脚印。没有有效动画动作时,客户端使用内置兼容动画和 lifetime。
LyCustom 粒子
客户端会监听以下插件消息通道并交给 LyCustom 粒子运行时解析:
| 通道 | 用途 |
|---|---|
lycustom:main | 主粒子通道 |
lycustom | 兼容粒子通道 |
当前项目确认的固定粒子名为:
text
暴雪粒子粒子数据由服务端发送,客户端负责解析和渲染。未安装客户端 MOD 时不会显示粒子效果。
客户端资源目录
MOD 初始化时会检查并创建以下目录:
text
<游戏目录>/resourcepacks/LyArmourers/SwordTrails/
<游戏目录>/resourcepacks/LyArmourers/FootPrints/| 目录 | 内容 |
|---|---|
SwordTrails | 自定义刀光静态图片或 GIF |
FootPrints | 自定义脚印静态图片或 GIF |
服务端只发送刀光和脚印 YAML,不传输贴图文件。每位玩家的客户端都必须拥有配置中 texture 指向的本地资源,否则对应特效不会绘制。
客户端尚未收到服务端 YAML、尚未收到玩家 UUID 与配置 ID 的绑定关系、配置无效或本地贴图不存在时,也不会绘制对应特效。
物品时装 NBT
客户端只把以下自定义 NBT 作为 LyArmourers 物品时装入口:
text
LyArmourers
└─ skin: String| 字段 | 类型 | 说明 |
|---|---|---|
LyArmourers.skin | String | 去掉空白字符后的末级时装文件名 ID |
客户端收到服务端的全库索引后,会把 NBT 中的时装 ID 解析为时装库中的真实相对路径。
客户端不再把旧 armourersWorkshop 标签、根级 skin、version 或其它兼容字段作为本项目时装入口。旧物品需要由服务端重新写入 LyArmourers.skin 后才能被当前客户端识别。
物品自身的时装 NBT 表示该物品的外观,不表示把对应时装穿到玩家身体上。
网络通信
客户端与服务端的主要业务通道为:
text
armourers客户端使用判别字节 64。协议负责:
- 请求时装库目录。
- 请求时装文件和预览数据。
- 写入物品时装 NBT。
- 请求
.armour合成。 - 创建时装物品。
- 查询和设置实体时装。
- 打开客户端管理界面。
- 同步实体动画。
- 同步装备渲染和物品预览开关。
- 同步时装 ID 到真实路径索引。
- 同步幻影、刀光和脚印状态。
预览文件传输规则:
| 项目 | 内容 |
|---|---|
| 小文件 | 使用完整数据包返回 |
| 大文件 | 使用分片数据包返回 |
| 单片大小 | 16000 字节 |
| 服务端消息上限 | 30000 字节 |
| 客户端请求超时 | 超过 3000ms 未完成后允许重试 |
客户端只接受与最近一次请求路径匹配的目录列表,避免延迟到达的旧消息覆盖当前界面。
时装资源请求不依赖管理界面的短时间访问授权,但服务端仍会通过时装库索引校验路径。无法解析到库内真实文件时只返回空数据,客户端不能通过相对路径访问时装库外部文件。
客户端状态清理
切换服务器或断开连接时,客户端会清理当前服务器相关状态,包括:
- 实体时装缓存。
- 可见实体请求节流记录。
- 服务端同步的渲染开关。
- 实体强制动画状态。
- 当前服务器的临时实体数据。
render-player-equipment-skins 和 render-item-skin-preview 在断开服务器后恢复为默认开启,等待下一台服务器重新同步。
兼容边界
- 不需要额外安装独立的 Armourer's Workshop 或 Mo' Bends 才能使用项目文件中内置的读取、渲染和动作兼容代码;当前构建没有声明这些 MOD 的外部 Gradle 依赖。
- 不应重新启用代码中遗留的原时装工坊方块、物品、配方、原服务端 GUI 或管理命令,它们不属于当前 LyArmourers 运行目标。
- 客户端 MOD 不负责保存永久实体时装,永久数据由服务端插件写入实体 ForgeData NBT 和服务端索引。
- 手持型
.bbmodel只进入手持渲染链,不能作为身体模型绘制。 .bbmodel是否隐藏原版部位只由模型setting的明确开关决定。- CustomNPCs 使用独立适配链,不能与普通非玩家实体渲染矩阵混用。
- 服务端插件与客户端 MOD 必须通过插件消息通信,不能互相直接引用实现类。