FreeMinecraftModels 模型创作注意事项
本页说明 FreeMinecraftModels 在导入和运行时读取的模型文件、配套文件及名称规则。
源格式
FreeMinecraftModels 目前接受:
.bbmodel文件,用于可编辑的源导入.fmmodel文件,用于精简的运行时就绪模型数据
对于没有配套文件的单个 .bbmodel:
- 将它直接放在
plugins/FreeMinecraftModels/imports中,扩展名使用小写.bbmodel - 运行
/fmm reload - 检查转换后的
.fmmodel是否出现在活动模型文件夹中,以及重载是否成功
单文件导入器会把原文件留在 imports,因此后续导入会再次转换。它不收集散放的 .json 或 .yml 配套文件,也不接受散放的 .fmmodel。对于自制模型集,请将模型和配套文件一起放在活动 models 文件夹中,或使用结构正确的内容包。imports 中没有 pack.meta 的任意子文件夹会被跳过。被拒绝的重载可能保留旧目录,请检查控制台。
单文件转换只保留纹理的 source、id 和 name,会丢弃动画尺寸与时间元数据,并且要求存在 textures 数组。如果需要这些元数据,请使用活动模型文件夹或保留原文件的内容包;运行时模型读取器本身允许缺少纹理数组。
文件夹用途
plugins/FreeMinecraftModels/imports
plugins/FreeMinecraftModels/models
plugins/FreeMinecraftModels/models_disabled
imports是手动模型导入和官方包下载在处理前的接收文件夹models包含已激活安装的模型内容models_disabled包含当前已禁用的已下载或已安装的包内容
旧安装可能有首字母大写的 Models 文件夹。FreeMinecraftModels 运行时优先使用现有的小写 models,否则使用 Models。在不区分大小写的文件系统中,两者指向同一目录;在区分大小写的文件系统中,它们可以并存。此时共享内容包导入器优先使用现有的 Models 目标,而运行时读取小写 models。请在服务器停止时备份并统一到小写 models,避免导入文件落在活动模型树之外。
模型 ID
- 运行时模型 ID 来自文件名,不包含
.bbmodel或.fmmodel扩展名 - 使用稳定、唯一的文件名,因为 ID 是命令和 API 调用解析的目标
- Blockbench 动画引用基于名称,因此模型内重复或不清晰的命名比干净、明确的命名方案更容易造成问题
- 活动模型文件夹中的扩展名匹配不区分大小写,因此接受
.BBModel和.FMModel。从imports导入散放文件时,只识别小写.bbmodel
ID 规范化与冲突
文件名在成为运行时模型 ID 和资源包文件名之前会先被规范化:
- 转为小写
- 每一个不属于
a-z、0-9、.、_、-的字符都会被替换为_
因此 My Table.bbmodel、my table.bbmodel 和 my_table.bbmodel 全都规范化成同一个 ID:my_table。
在任何转换开始之前,FreeMinecraftModels 会扫描整个 models 目录树,检查是否有文件规范化后得到相同的 ID。如果拥有该 ID 的所有文件逐字节完全相同(两个内容包附带同一个模型时就会出现这种情况),FMM 会加载绝对路径排序最靠前的那个,并直接跳过其余副本,不产生警告。当这些文件内容不同时:
- 每一个发生冲突的文件都会被拒绝 —— 它们都不会被加载,因此不存在悄悄的"最后一个胜出"
- 该模型 ID 在本次加载过程的剩余阶段被封锁
- 被拒绝的模型也会被排除在基岩版自定义实体资源包的导出之外
- 控制台会输出:
[FMM Models] Rejected normalized model ID collision '<id>'. These files normalize to the same ID: <paths>. Rename the files so every normalized model ID is unique; no colliding model was loaded.
修复办法始终是重命名文件,使规范化后的 ID 各不相同。最稳妥的习惯是从一开始就用小写加下划线来命名模型文件(stone_table.bbmodel),这样文件名与运行时 ID 就完全一致,也彻底消除了意外冲突的可能。
Blockbench 兼容性
- FreeMinecraftModels 会从
.bbmodel中读取meta.format_version,并根据其主版本号分支 - 缺少
meta块、缺少format_version,或者值无法解析,都会回退到版本4,并输出一条指明该模型的信息/警告 - 缺少
textures数组是被接受的,会被当作空纹理列表处理,而不会让导入器崩溃。此后基岩版自定义实体导出器会跳过该模型,因为基岩版导出至少需要一张纹理 - 提取出的纹理文件名会被统一规范为单一的
.png扩展名。诸如body.jpg、body.PNG或body这样的源名称,都会以body.png的形式写出并被引用 format_version4.x及更早:骨骼直接从outliner树中读取,该树内联携带骨骼名称format_version5.x及更新:outliner 的结构发生了变化。outliner现在是由纯 UUID 字符串和{uuid, isOpen, children}字典构成的嵌套树,其中没有 name 键,而真正的骨骼数据(包括name)保存在一个独立的扁平groups数组中。FMM 通过 UUID 把两者连接起来 —— 每个 outliner 节点会被替换为它在groups中匹配的条目,然后递归合并子节点 —— 因此骨骼名称、原点和旋转都能正常解析- 手工编辑或程序生成
.bbmodel文件时值得了解的影响:- 缺少
groups数组的 v5 文件会不经合并直接传递。已经合并的 outliner 仍可能正常工作;未经处理的无名 v5 组节点则可能在骨架读取器需要名称时导致模型加载失败 outliner和groups之间的 UUID 必须完全一致;没有匹配 group 的 outliner 节点会被原样保留,而不是被丢弃- 不要把 v5 的
format_version与 v4 形态的 outliner 混在一起,反之亦然 —— 分支是根据声明的版本选择的,而不是根据实际结构
- 缺少
- 如果导入日志显示模型格式与 FreeMinecraftModels 不兼容,请首先将其视为模型格式问题,而不是 wiki 或命令问题
影响运行时的骨骼约定
当前转换器和骨架管线识别以下命名约定:
hitbox- 保留用于碰撞箱生成
- 应该清晰地定义模型碰撞箱,而不是用作视觉骨骼
- 必须是 outliner 中的顶级骨骼才能定义运行时碰撞。嵌套的
hitbox会经过普通骨骼解析,但保持隐藏,且不会定义模型的碰撞箱 - 应恰好包含一个立方体,定义宽(x)、深(z)和高(y)。额外立方体会记录
has more than one value defining a hitbox! Only the first cube will be used。空组会记录has a hitbox bone but no hitbox cube!,并留下零尺寸,与没有 hitbox 不同。立方体的偏移和旋转不会成为碰撞箱偏移:解析器使用各边长度的绝对值和零模型偏移 - 永远不会被动画化(指向
hitbox的动画轨道会被跳过)、永远不会被渲染,并被排除在基岩版几何体导出之外。在基岩版上,没有hitbox骨骼的模型会回退到1.0x2.0
tag_...- 作者可选添加的名牌锚点,参见下方名牌位置
h_...- 被视为头部骨骼
b_...- Java 运行时的非显示骨骼。结构用途请使用不含立方体的骨骼:基岩版几何导出不会过滤
b_前缀,因此这些骨骼上的立方体仍可能显示
- Java 运行时的非显示骨骼。结构用途请使用不含立方体的骨骼:基岩版几何导出不会过滤
m_...- 骑乘点骨骼。每个带此前缀的骨骼创建一个玩家座位,由
MountPointManager管理。多个m_骨骼创建多个座位。管理器选择第一个空座位,并在占用期间使用临时 Interaction 实体;其公开骑乘方法接受玩家,不接受任意实体。
- 骑乘点骨骼。每个带此前缀的骨骼创建一个玩家座位,由
前缀区分大小写,hitbox 名称的比较则不区分。这些名称影响转换和运行时行为。
名牌位置
tag_ 骨骼现在是可选的。FMM 按名称字母顺序选择第一个 tag_ 骨骼作为名牌锚点。没有这类骨骼时,会将名牌放在缩放后的碰撞箱上方,因此无标签骨骼的模型也能显示名称。
如果备用位置不合适,可添加不含立方体的 tag_name 骨骼。多个标签骨骼不再产生同一名牌的多个副本。
API 支持多行名称、缩放、行距和可见性。各行从上到下排列,最后一行位于锚点处。参见API 指南。
立方体着色与发光
- 来自 Blockbench 的立方体
light_emission值为0到15之间的整数时会被保留。其他任何值都会被丢弃,并输出一条以with invalid light_emission. Expected an integer from 0 to 15; ignoring this value.结尾的控制台警告。 - 关闭了着色(
shade: false)的立方体还会在生成的几何体中获得shade_direction_override: "up",这样 Minecraft 26.3 客户端也会像旧版客户端一样以无着色方式渲染它。FMM 对同名显示模型.json中的立方体也应用相同规则。你自己设置的值会被保留
未分组的立方体
在 outliner 顶部声明、不属于任何组的立方体,会以纯 UUID 字符串而不是骨骼条目的形式到达。FreeMinecraftModels 会把它们挂到自动生成的根骨骼(freeminecraftmodels_autogenerated_root)上,因此它们仍会被渲染。它们无法被动画寻址,所以任何你打算做动画的东西都要放进一个真正的组里。
IK、空对象和定位器
当前代码确认支持:
- Blockbench 空对象作为 IK 控制器
- IK 链蓝图和运行时 IK 求解(FABRIK)
- 定位器解析。定位器也可以作为 Blockbench 粒子效果的锚点;参见粒子
只有当空对象的 .bbmodel 条目同时包含 ik_source(源骨骼)和 ik_target(目标骨骼或定位器)时,才会成为 IK 控制器。导入器搜索层级,也包含同级和向下的搜索路径。根层级的同级节点会产生仅含源的链。lock_ik_target_rotation 会被读取并保存,但当前求解器并不应用它。
重要的实际限制:
- 源/目标之间的关联是通过 UUID 建立的,因此重命名不会破坏它 —— 但如果任一 UUID 在模型中缺失,控制台会记录
IK chain in model <model>: Could not find source bone with UUID .../Could not find target with UUID ...,并跳过该骨链 - 如果搜索找不到从源到目标的路径,会记录
Could not find path from source to target并跳过该链 - 控制器的动画查找是基于名称的,因此控制器命名需要在模型结构和动画数据之间保持稳定
- 只有位置关键帧驱动 IK,其偏移会加到目标骨骼或定位器的静止位置上,而不是保存的控制器静止位置。旋转和缩放轨道不会驱动 IK
关于 IK 是如何逐帧被驱动的,参见动画。
1.21.4+ 输出拆分
FreeMinecraftModels 声明了 api-version: 1.21.4,因此 1.21.4 是最低服务器版本,你拿到的永远是现代的物品模型定义布局:
plugins/FreeMinecraftModels/output/FreeMinecraftModels/assets/freeminecraftmodels/items
旧版(1.21.4 之前)基于皮革马铠 override 的分支在代码中依然存在,但任何能加载当前插件的服务器都不会走到那里。如果你在看旧的笔记或旧的输出文件夹,你看到的差别就是这个。
展示模型 JSON(1.21.4+)
管理员可以在 .bbmodel 或 .fmmodel 文件旁边放置一个同名的 .json 文件(例如 table.bbmodel + table.json)。此 JSON 应从 Blockbench 导出为"Java Block/Item"模型,定义物品在手持或在物品栏中显示时的外观。
FMM 读取活动模型旁的 JSON,将其复制到资源包,并重写 textures 映射中不带命名空间的值。数字纹理键对应模型已提取纹理的索引;未匹配的键会使用一个可用纹理(如果存在)。带命名空间的值保持不变。没有配套 JSON 时,物品使用基础材质的外观:装饰物放置物品通常为纸,手持物品则使用配置的材质。格式错误的配套文件会记录 Failed to process display model JSON for ...,且不会注册该显示模型。
YML 中的自定义物品配置
在模型配套 YAML 中设置 material,即可注册手持物品:
isEnabled: true
material: DIAMOND_SWORD
name: "&6Flame Blade"
lore:
- "&7A blade with a fire enchantment"
enchantments:
- "minecraft:fire_aspect,2"
附魔 ID 应为小写且带命名空间。皮革材质接受 RGB 染色后缀,例如 LEATHER_CHESTPLATE:ff8800;参见配置。使用不支持的材质、无命名空间附魔或非空 scripts: 列表的物品不可用;控制台会说明原因,原文件则会保留。scripts: 仍仅用于装饰物。
其他无效定义,例如非布尔值 isEnabled、格式错误的附魔条目、重复附魔或无效物品文件名,可能导致候选目录和重载被拒绝。物品文件名应为小写,只含 a-z、0-9、.、_ 和 -,最长 128 个字符。自定义物品扫描读取 .yml,不读取 .yaml。通过 /fmm giveitem <item> 或管理员浏览器获取已注册物品;装饰物配方和商店购买产生的是纸质放置物品。
物品效果现在由附魔定义管理。魔杖和法杖使用魔法武器配置。两者都不使用旧的装备物品 Lua 运行时。
基岩版和渲染路径注意事项
- 基岩版支持取决于
sendCustomModelsToBedrockClientsV2(默认值为true;替代了较旧的sendCustomModelsToBedrockClients键)以及周围的 Floodgate/Geyser/资源包路径 - 受支持版本上的 Java 客户端可以在启用
useDisplayEntitiesWhenPossible时使用展示实体渲染 - 不要假设在 Java 客户端上显示正确的模型对您的基岩版路径自动安全
实用创作建议
- 保持文件名稳定,因为它们会成为运行时 ID
- 保持控制器和动画命名明确,因为 Blockbench 动画查找是基于名称的
- 按用途使用保留的虚拟骨骼名称(
hitbox、tag_、h_、b_、m_)。只有碰撞箱上方的备用名牌位置不合适时,才添加tag_锚点 - 共享运行时状态使用小写
spawn、idle、walk、attack和death;攻击和死亡仍需要运行时触发,其他名称则需明确调用播放(参见动画) - 打算用于
/fmm disguise的模型至少也应当附带idle,还可以加上sneak和jump,这两者只有伪装控制器才会识别(参见玩家伪装) - 在
/fmm reload后验证导入的输出,而不仅仅是在 Blockbench 内部 - 验证为目标 Minecraft 版本生成的包内容,尤其是
1.21.4+
弓和弩状态模型
FMM 在生成资源包时自动检测弓和弩的显示状态。每个必需状态都要有已加载的模型文件,以及处理成功的配套显示 .json;仅有文件名并不足够。请用基础名称配置手持物品,并使用对应的 BOW 或 CROSSBOW 材质。
命名约定
| 后缀 | 用途 | 弓 | 弩 |
|---|---|---|---|
_idle | 手持物品,未拉弓或未装填 | 必需 | 必需 |
_draw_start | 刚开始拉弓 | 必需 | 必需 |
_draw_half | 拉到一半 | 必需 | 必需 |
_draw_full | 完全拉满 | 必需 | 必需 |
_charged | 已装填的弩(箭或火箭) | -- | 必需 |
弓需要四个模型(除 _charged 外全部)。弩需要全部五个。
示例文件布局
plugins/FreeMinecraftModels/models/my_weapons/
cool_bow_idle.bbmodel
cool_bow_idle.json
cool_bow_draw_start.bbmodel
cool_bow_draw_start.json
cool_bow_draw_half.bbmodel
cool_bow_draw_half.json
cool_bow_draw_full.bbmodel
cool_bow_draw_full.json
cool_bow.yml
对于弩,还需添加 cool_bow_charged.bbmodel 和 cool_bow_charged.json。物品配置为 cool_bow.yml,使用不带 _idle 的基础名称。
检测机制
- 检测在资源包生成时(启动时或
/fmm reload)自动进行。 - 完整的显示状态集会得到一个以基础名称命名的公开物品定义,例如
cool_bow.json。各个_idle、拉弓和装填状态的物品定义会移除,但其几何仍由基础定义引用 - 显示注册表公开基础 ID 并移除状态 ID。包含
_charged的完整集合视为弩,不含则视为弓。缺少显示状态会阻止分组 - YML 配置使用基础名称,例如
cool_bow.yml。物品目录会跳过带状态后缀的 YML 文件,装饰物配置查找也会去掉后缀
展示模型 JSON
每个必需状态都必须有自己的配套显示 .json,例如 cool_bow_idle.json 和 cool_bow_draw_full.json。FMM 通过生成的基础物品定义连接它们。条件和输出路径请参阅资源包输出。
超出范围
本页不尝试保证:
- 确切的 Blockbench UI 步骤
- 艺术工作流偏好
- 旧版本地 README 材料中描述的每个遗留
.bbmodel特性
这些细节的变化速度比上述已验证的运行时契约更快。