JSON 模型格式


概况

自定义玩家模型(CPM)允许您使用JSON来自定义骨骼,方块,平面,飘带和粒子,结合强大的表达式功能来自定义模型外观。

主JSON文件

每个模型包必须包含一个名为“ model.json”的json文件。 一个典型的json结构如下所示:

{
    "modelId": ...,
    "modelName": ...,
    "version": ...,           // 可选
    "author": ...,            // 可选
    "fpLeft": [ ... ],        // 可选
    "fpRight": [ ... ],       // 可选
    "skeleton": { ... },      // 可选,可使用表达式
    "eyeHeight": { ... },     // 可选
    "boundingBox": { ... },   // 可选
    "variables": { ... },     // 可选,可使用表达式
    "hide": [ ... ],          // 可选
    "bones": [ ... ]
}

基本信息

  • modelId:每个模型应具有唯一ID,否则将被视为不同版本的同一模型,因此在提供ID时请避免冲突。模型ID只能包含小写字母,数字和下划线(_)。
  • modelName:模型名称是玩家使用命令/custommodel list时在游戏中看到的模型名称。模型名称可以有冲突,并且可以包含任何字符。
  • version:当加载具有相同模型ID的不同模型时,系统会选择版本最大的模型(按字典顺序比较字符串)。
  • author:写上您的名字,加入名人堂。

原有骨骼

玩家模型是用骨骼构成的,方块均附加在骨骼上,骨骼定义了模型如何运动。 原有骨骼是构建原版玩家模型的骨骼,包含以下骨骼:

  • head
  • body
  • left_arm
  • right_arm
  • left_leg
  • right_leg

以及它们的第二层:

  • head_overlay
  • body_overlay
  • left_arm_overlay
  • right_arm_overlay
  • left_leg_overlay
  • right_leg_overlay

这些骨骼的运动由游戏代码控制,此mod不会干涉以保持兼容性。您可以做的是调整其位置以更改模型的身高,或隐藏它们并制作全新的替代骨骼。

第一人称渲染

此mod允许您选择要在第一人称视角中渲染的骨骼。 您可以将这些骨骼添加到“fpLeft”或“fpRight”列表中,这取决于您的主手。请仅添加原有手臂骨骼的子骨骼(“left_arm”或“right_arm”及其第二层),并不要在其上添加“physics”,除非您清楚地知道自己要做什么。

骨架

骨架定义了原有骨骼的位置,可以用来改变模型的身材,例如使自己像末影人一样高,而无需进行复杂的修改。您可以参考末影人模型作为示例。

碰撞箱和眼睛高度

更改模型身材后,大多数情况下,您也希望对碰撞箱做相应更改以适合您的新身材。现在,您可以为不同的玩家姿势定义它们:

  • standing
  • fall_flying
  • sleeping
  • swimming
  • spin_attack
  • sneaking
  • dying

在大多数情况下,定义三个姿势(standing,sneaking和dying)的碰撞箱和眼睛高度就足够了。 因此,以下是json的大致情况:

{
    "eyeHeight": {
        "standing": 1.215,
        "dying": 1.215,
        "sneaking": 0.9525
    },
    "boundingBox": {
        "standing": [0.45, 1.35],
        "dying": [0.45, 1.35],
        "sneaking": [0.45, 1.125]
    }
}

隐藏部分模型

您可以隐藏不希望看到的原有骨骼或特征,例如当您想要更改其位置/外观等时。游戏不会显示添加到此列表的骨骼或特征,但仍将计算其变换矩阵,因此它们仍然可以成为父骨骼。 数组的每个元素必须是原有玩家骨骼之一或原有特征之一:

  • helmet_head
  • helmet_head_overlay
  • chestplate_body
  • chestplate_left_arm
  • chestplate_right_arm
  • leggings_body
  • leggings_left_leg
  • leggings_right_leg
  • boots_left_leg
  • boots_right_leg
  • held_item_left
  • held_item_right
  • cape
  • head_wearing (头颅,南瓜等)
  • elytra
  • shoulder_parrot_left
  • shoulder_parrot_right

还可以是它们的组合:

  • head_all: head, head_overlay

  • body_all: body, body_overlay

  • left_arm_all: left_arm, left_arm_overlay

  • right_arm_all: right_arm, right_arm_overlay

  • arms_all: left_arm_all, right_arm_all

  • left_leg_all: left_leg, left_leg_overlay

  • right_leg_all: right_leg, right_leg_overlay

  • legs_all: left_leg_all, right_leg_all

  • model_all: head_all, body_all, arms_all, legs_all

  • helmet_all: helmet_head, helmet_head_overlay

  • chestplate_all: chestplate_body, chestplate_left_arm, chestplate_right_arm

  • leggings_all: leggings_body, leggings_left_leg, leggings_right_leg

  • boots_all: boots_left_leg, boots_right_leg

  • armor_body_all: chestplate_body, leggings_body

  • armor_arms_all: chestplate_left_arm, chestplate_right_arm

  • armor_left_leg_all: leggings_left_leg, boots_left_leg

  • armor_right_leg_all: leggings_right_leg, boots_right_leg

  • armor_legs_all: armor_left_leg_all, armor_right_leg_all

  • armor_all: helmet_all, armor_body_all, armor_arms_all, armor_legs_all

  • held_item_all: held_item_left, held_item_right

  • shoulder_parrot_all: shoulder_parrot_left, shoulder_parrot_right

  • feature_all: armor_all, held_item_all, shoulder_parrot_all, cape, head_wearing, elytra

隐藏它们之后,您可以将这些特征(不能是骨骼)附加到自定义骨骼上以更改其原始位置。 骨骼的缩放/可见性也将应用于附加的特征。

坐标系

与原始模型坐标系不同,CPM使用的坐标系与Minecraft的世界坐标系相同,玩家模型面朝北方,即-Z方向。

Direction XYZ
East +X
West -X
North -Z
South +Z
Up +Y
Down -Y

骨骼

骨骼是构成模型的基础,它们构成了玩家模型的整体框架,并定义了每个部分的运动规律。 一个典型的骨骼json如下所示:

{
    "id": ...,
    "parent": ...,                  // 可选
    "texture": ...,                 // 可选,可使用表达式
    "textureSize": [ ..., ... ],    // 可选
    "position": [ ..., ..., ... ],  // 可选,可使用表达式
    "rotation": [ ..., ..., ... ],  // 可选,可使用表达式
    "scale": [ ..., ..., ... ],     // 可选,可使用表达式
    "visible": ...,                 // 可选,可使用表达式
    "emissive": ...,                // 可选,可使用表达式
    "color": [ ..., ..., ... ],     // 可选,可使用表达式
    "alpha": ...,                   // 可选,可使用表达式
    "physics": [ ... ],             // 可选
    "attached": [ ... ],            // 可选
    "boxes": [ ... ],               // 可选
    "quads": [ ... ],               // 可选
    "particles": [ ... ],           // 可选
    "items": [ ... ]                // 可选
}
  • id: 每个骨骼必须具有唯一的ID,并且不能与原有的骨骼或特征(body, head, etc)相同。
  • parent: 父骨骼必须是原有的骨骼之一,或者是之前定义的自定义骨骼。 父骨骼和子骨骼必须按顺序出现。 子骨骼将遵循父骨骼的变换(纹理,位置,旋转,缩放和可见性),就好像它是父骨骼的一部分一样。 如果为空,则将默认选择身体骨骼作为父骨骼。
  • texture: 带有前缀“tex.”的贴图文件名,不包含路径或后缀(例如“tex.hair”对应的贴图文件名为“ hair.png”)。 贴图文件与“model.json”存储在同一文件夹中。 如果为空,则使用与其父骨骼相同的纹理。若父骨骼为原有的骨骼之一,则使用玩家的皮肤贴图。有三个默认存在的贴图:“tex.skin”代表玩家皮肤,“tex.cape”代表玩家披风(如果有的话),“tex.elytra”代表鞘翅贴图(如果有的话)。 对于没有披风的玩家,可以使用“tex.cape>0”来测试当前玩家是否拥有披风。
  • textureSize: 当指定贴图时必须指定贴图大小。 在大多数情况下,它与贴图的分辨率相同。 贴图大小不能使用动画,因此在为贴图设置动画时,请确保所有使用的纹理具有相同的分辨率。
  • position: 定义子骨骼的相对位置。 请注意,这不会更改当前骨骼的位置,而仅仅影响子骨骼和附加的方块、特征、粒子等等的位置。默认值[0,0,0]。
  • rotation: 定义当前骨骼的欧拉旋转角度。 默认值[0,0,0]。
  • scale: 定义当前骨骼的缩放比例。 默认值[1,1,1]。
  • visible: 指定是否渲染可见元素(附加的方块,特征等)。 如果未指定,它将具有与其父骨骼相同的可见性。
  • emissive: 是否自发光,例如蜘蛛或末影人的眼睛。
  • color & alpha: 改变模型的默认颜色(255,255,255,255)。
  • physics, boxes, quads, particles & items: 请见下面的章节。
  • attached: 当需要更改原有特征(盔甲,持有的物品等)的位置,就可以隐藏它们并将其附加到新骨骼上。 将相同的特征附加到多个骨骼将使特征渲染多次。

方块和平面

Minecraft中的大多数实体模型都是由方块构成的。 一个典型的方块json如下所示:

{
    "textureOffset": [ ..., ... ],  // 可选
    "coordinates": [ ... ],         // 可选
    "sizeAdd": ...,                 // 可选
    "mirror": ...                   // 可选
}
  • textureOffset: 方块UV坐标的左上角。 每个方块包含六个面,其UV按照与玩家皮肤相同的方式排列。 默认值[0,0]。
  • coordinates: 定义方块的偏移位置和大小。 前三个参数是偏移量,后三个参数是大小。 默认值[0,0,0,0,0,0]。 方块坐标与实际世界坐标之间的比例为16:1。
  • sizeAdd: 像玩家模型的二层皮肤一样拓展方块。 默认值0。
  • mirror: 有一些模型使用了相同的贴图但是方向相反,例如左右手的贴图。此选项可以让贴图左右翻转。

平面json与方块几乎相同,除了它们是二维的,因此“coordinates”仅包含5个参数。

粒子

粒子系统已经广泛应用于现代的3D游戏中。 CPM为粒子发射器提供了各种参数,供您自定义特殊效果。

{
    "posRange": [ ..., ..., ... ],  // 可选,可使用表达式
    "dirRange": ...,                // 可选,可使用表达式
    "angle": [ ..., ... ],          // 可选,可使用表达式
    "speed": [ ..., ... ],          // 可选,可使用表达式
    "rotSpeed": [ ..., ... ],       // 可选,可使用表达式
    "lifeSpan": [ ..., ... ],       // 可选,可使用表达式
    "density": ...,                 // 可选,可使用表达式
    "animation": [ ..., ... ],      // 可选
    "colorR": [ ..., ... ],         // 可选,可使用表达式
    "colorG": [ ..., ... ],         // 可选,可使用表达式
    "colorB": [ ..., ... ],         // 可选,可使用表达式
    "colorA": [ ..., ... ],         // 可选,可使用表达式
    "size": [ ..., ... ],           // 可选,可使用表达式
    "gravity": ...,                 // 可选,可使用表达式
    "collide": ...                  // 可选,可使用表达式
}
  • posRange: 发射粒子相对于当前骨骼位置的最大初始偏移量。 默认值[0,0,0]。
  • dirRange: 粒子生成时的最大方向偏移角(以度为单位)。 如果为0,则新粒子将沿当前骨骼的Z轴移动,如果不为0,则将在圆锥中随机选取一个方向。默认值为0。
  • angle: 初始粒子旋转角度的最小值和最大值(以度为单位)。 默认值[0,0]。
  • speed: 粒子移动速度的最小和最大值,以米/秒为单位。 默认值[0,0]。
  • rotSpeed: 粒子旋转速度的最小值和最大值,以度/秒为单位。 默认值[0,0]。
  • lifeSpan: 每个粒子存在多少个游戏刻,最小值和最大值。 默认值[1,1]。
  • density: 每个游戏刻中产生多少新粒子。 默认值1。
  • animation: 可以将粒子的贴图拆分为子图像以制作动画。 此参数指定每列/每行有多少个子图像。 默认值[1,1]。
  • color(R|G|B|A): 粒子颜色的最小值和最大值。 默认值[1,1]。
  • size: 粒子尺寸的最小值和最大值。 默认值[1,1]。
  • gravity: 如果不为0,将对所有粒子施加方向为-Y的重力。 可以为负。默认值0。
  • collide: 粒子是否会与方块/实体碰撞。 默认为false。

物品模型

您可以将物品模型作为玩家模型的一部分。

{
    "itemId": "item. ... ",    // 可使用表达式
    "enchanted": ...           // 可选,可使用表达式
}
  • itemId:您要附加的物品ID。使用物品常量,例如item.apple,item.diamond_sword等。
  • 附魔:物品模型是否附魔。

物理系统

骨骼json中的“physics”条目指定当前骨骼运动符合的物理规律。 物理骨骼不会像刚体那样严格保持与其父骨骼的相对变换,而是会像弹簧一样遵循物理规则,可用于模拟头发,围巾等的移动。此条目包含5个参数:

  • elasticity: [0, +inf), 弹性:父骨骼移动时所施加的力的强度,指向运动方向。
  • stiffness: [0, +inf), 刚度:不断施加于骨骼,以保持与父骨骼的相对变换的力的强度。
  • damping1: [0, 1), 阻尼1:在每个游戏周期内乘以当前骨骼的速度,以模拟空气阻力。
  • damping2: [0, +inf), 阻尼2:在玩家实体移动速度的相反方向上施加的力的强度。
  • gravity: [0, +inf), 重力的强度。

动画

CPM使玩家能够使用表达式创建自己的动画。 例如,以下骨骼:

{
    "id": "bounce".
    "position": [ 0, "sin(age)", 0 ],
    "boxes": [ ... ]
}

它将在Y方向上反复横跳。

有两种表达式类型:浮点型和布尔型。 它们可以与各种变量和功能结合使用,以实现复杂的运动。 动画表达式可以被应用于以上章节中标记有“可使用表达式”的所有参数。

您还可以在json根节点中添加自定义变量:

{
    "variables": {
        "bounce": "sin(age)",
        "should_bounce": "is_sneaking"
    }
}

然后,您可以在之后的表达式中使用“var.bounce”和“var.should_bounce”来访问它们。请注意,这些变量不能引用其自身。

还有另外一种变量——刻更新变量,它们在每个游戏刻进行更新,重要的是它们能够引用其自身!这就意味着这些变量实际是图灵完备的——使用它们能够完成任何可实现的算法。一个典型的刻更新变量如下所示:

{
    "tickVars": {
        "selfAdd": ["float", 0, "if(tvl.selfAdd<10,tvl.selfAdd+1,0)]
    }
}

变量名为selfAdd,float为变量类型,目前只有浮点型和布尔型两种,0为变量的初始值。这个变量的值将在0到10之间循环。有三种方法可以引用这个变量的值:

  • tvl.xxx: 获取变量在上一游戏刻的值。
  • tvc.xxx: 获取变量在当前游戏刻的值。
  • tvp.xxx: 获取一个在上面两者之间的值,使用游戏的partial变量进行插值。

这里有一个使用刻更新变量实现的俄罗斯方块游戏可供参考。

以下是可用于形成表达式的所有变量和函数:

name type arguments description
limb_swing 浮点变量 胳膊摆动的角度
limb_speed 浮点变量 胳膊摆动的距离
age 浮点变量 玩家实体存在的时间
head_yaw 浮点变量 头部和身体旋转欧拉角之差
head_pitch 浮点变量 头部旋转的欧拉角
scale 浮点变量 模型的比例 (一般是0.0625)
health 浮点变量 玩家当前生命值
food_level 浮点变量 玩家当前饱食度
hurt_time 浮点变量 被攻击的剩余时间(渲染为红色)
pos_x 浮点变量 X坐标
pos_y 浮点变量 Y坐标
pos_z 浮点变量 Z坐标
speed_x 浮点变量 X速度
speed_y 浮点变量 Y速度
speed_z 浮点变量 Z速度
yaw 浮点变量 头部旋转的欧拉角
body_yaw 浮点变量 身体旋转的欧拉角
pitch 浮点变量 头部旋转的欧拉角
swing_progress 浮点变量 胳膊摆动的进度 [0, 1] (攻击或放置方块时)
is_alive 布尔变量 是否存活
is_burning 布尔变量 是否在燃烧
is_glowing 布尔变量 是否在发光
is_hurt 布尔变量 是否被攻击(渲染为红色)
is_in_lava 布尔变量 是否在岩浆中
is_in_water 布尔变量 是否在水中
is_invisible 布尔变量 是否不可见
is_on_ground 布尔变量 是否在陆地上
is_riding 布尔变量 是否在骑乘中
is_sneaking 布尔变量 是否在潜行
is_sprinting 布尔变量 是否在奔跑
is_wet 布尔变量 是否变湿(下雨或者在水中)
is_first_person 布尔变量 是否在渲染第一视角
pi 浮点常量 3.1415926 ...
time 浮点变量 当前的昼夜循环时间 [0, 24000)
+, -, *, /, % 浮点函数 float x 2 基本运算
sin, asin, cos, acos, tan, atan 浮点函数 float 三角函数
atan2 浮点函数 float x 2 三角函数
torad, todeg 浮点函数 float 角度/弧度转换
min, max 浮点函数 float x n 最小值/最大值
clamp 浮点函数 float x 3 max(f2, min(f1, f3))
abs, floor, ceil, exp, frac, log, pow, round, signum, sqrt 浮点函数 float 初等函数
fmod 浮点函数 float x 2 浮点数取余
random 浮点函数 - 返回 [0, 1) 的随机数
!, &&, || 布尔函数 boolean x 2 布尔运算
>, >=, <, <=, ==, != 布尔函数 float x 2 浮点数比较
equals 布尔函数 float x 3 带误差的浮点数比较 abs(f1 - f2) < f3
between 布尔函数 float x 3 f1是否在f2和f3之间
in 布尔函数 float x n f1是否为{f2, f3, ..., fn}中的一个
if 浮点函数 boolean, float, (boolean, float) x n, float if (b1) f1 {else if (b2) f2} x n else fn
(bone name).(t|r|s)(x|y|z) 浮点变量 获取骨骼的相对位移、旋转、缩放变换。例如 head.rx, body.tz, 等
tex.(texture name) 浮点常量 获取指定名称的贴图
inv.(mainhand|offhand| helmet|chestplate|leggings| boots|main(0 - 35)) 浮点变量 获取玩家背包中的物品。例如 inv.main4 表示背包的第五格
item.(item id) 浮点常量 获取指定物品的id。例如 inv.mainhand==item.apple 可判断玩家是否持有苹果.
pose.(pose id) 浮点常量 获取指定姿势的id。
current_pose 浮点变量 获取玩家当前的姿势。
effect.(effect id) 浮点变量 获取玩家身上的药水效果等级。(没有的话为-1)