🔣 方块状态
简介
在 Minecraft 的方块系统中,每个方块都带有一个或多个方块状态。例如,木头有朝向,树叶有不同的距离。这些方块状态决定了方块在游戏中的行为和外观。
单状态方块
大多数方块仅需一个方块状态即可正常运行。以下示例展示了如何配置单状态方块。
blocks:
default:chinese_lantern:
state:
id: 15
state: note_block:15
model:
path: "minecraft:block/custom/chinese_lantern"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/chinese_lantern_top"
"side": "minecraft:block/custom/chinese_lantern"
内部标识符
blocks:
default:chinese_lantern:
state:
id: 15
id
代表方块的唯一标识符。例如,本例中的 15
将对应于 craftengine:note_block_15
。
id: 15
中的 15 与 state: note_block:15
中的 15 完全不相关。我稍后会解释。
方块标识符的最大数量取决于两个因素的总和:
- 可用的外观方块状态:这些在
mappings.yml
文件中定义。对于单一的方块类型,你“释放”的空闲方块状态越多,可用的外观方块状态数量就越多。 - 额外注册的真实方块状态:这些通过
additional-real-blocks.yml
文件添加。此配置允许你为特定方块手动注册额外的服务器端侧真实方块状态,进一步增加内部标识符的总量。
视觉方块状态
blocks:
default:chinese_lantern:
state: note_block:15
state
指的是客户端看到的视觉外观。这些方块状态是我们通过 mappings.yml 文件释放的原版方块状态。可用方块状态的最大数量由 Minecraft 版本决定,并且受到严格限制。note_block:15
指的是第 16 个(从零开始计数)被释放的音符盒方块状态。
如果您想精确控制使用中的外观方块状态,可以像这样配置方块状态。
state: minecraft:note_block[instrument=hat,note=0,powered=false]
模型
blocks:
default:chinese_lantern:
state:
model:
path: "minecraft:block/custom/chinese_lantern"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/chinese_lantern_top"
"side": "minecraft:block/custom/chinese_lantern"
model
决定了哪个 3D 模型将替换被释放的原版方块状态。除了标准的方块模型外,CraftEngine 还允许进一步配置随机模型和模型旋转。
如果你不确定如何配置 path
和 generation
等属性,你应该首先完成教程。
加权模型
要实现随机模型,只需以列表格式提供模型路径即可:
state:
models: # model(s)
- path: "minecraft:block/custom/fairy_flower_1"
weight: 8
- path: "minecraft:block/custom/fairy_flower_2"
weight: 5
- path: "minecraft:block/custom/fairy_flower_3"
weight: 2
weight:设置模型在游戏中被选用的权重。默认为1(即100%)。如果候选模型指定了一个模型选择列表,游戏会根据方块所在的位置计算应该选择什么模型,如果方块位置一致选择的模型也就一致。模型列表内一个模型被选中的概率由weight决定:假设第一个模型的weight为w1,第二个模型的weight为w2,以此类推直到第n个模型,那么总权重为W=w1+w2+w3+...+wn,选中第n个模型的概率就是wn/W。举例来说,如果第一个模型权重为1,第二个模型权重为2,第三个模型权重为1,则选中第一个模型的概率为25%,选中第二个模型的概率为50%,选中第三个模型的概率为25%。
旋转
如果你需要创建一块具有三种不同方向的木头,你只需指定 x 和 y 属性即可。
model:
path: "minecraft:block/custom/chinese_lantern"
x: 90
y: 180
uvlock: false
x: 模型相对于X轴的旋转,单位为度,必须为90的倍数。
y: 模型相对于Y轴的旋转,单位为度,必须为90的倍数。
uvlock: 是否锁定方块纹理的旋转方向,默认为false。如果设置为 true,则锁定方块材质的旋转。这样,使用上面的 x 和 y 属性时,材质不会随方块旋转。
多状态方块
接下来的内容可能会比较难懂。我会尽可能详细地解释,请务必逐字逐句仔细阅读。
创建多状态方块的第一步是为该方块定义状态属性的类型。在此示例中,我设置了一个 axis
属性。
blocks:
default:palm_log:
states: # state(s)
properties:
axis: # 属性名称
type: axis # 数据类型
default: y # 默认值
属性
属性名称几乎可以随意选择,但我建议使用小写字母。不过,插件会为特殊的放置行为硬编码某些名称。例如,当属性名为 axis
时,插件在放置时会自动对齐其方向。这一过程是完全自动化的。
在下面的示例中,由于属性名为 custom_axis
,插件在放置时不会应用旋转。无论你如何放置,方块在放置时将始终使用 custom_axis=y
状态。
custom_axis:
type: axis
default: y
您可以在ℹ️ 属性中找到有关属性类型和插件硬编码属性名称的详细信息。
外观
在第二步中,我们需要配置自定义方块的可能视觉外观。例如,一个木头方块需要三种方向,因此我们需要指定三种原版方块状态作为其视觉表现。
blocks:
default:palm_log:
states:
appearances:
axisY:
state: "note_block:0"
model:
path: "minecraft:block/custom/stripped_palm_log"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
axisX:
state: "note_block:1"
model:
x: 90
y: 90
path: "minecraft:block/custom/stripped_palm_log_horizontal"
generation:
parent: "minecraft:block/cube_column_horizontal"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
axisZ:
state: "note_block:2"
model:
x: 90
path: "minecraft:block/custom/stripped_palm_log_horizontal"
generation:
parent: "minecraft:block/cube_column_horizontal"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
在上述配置中,axisX
、axisZ
和 axisY
可以任意名称。您可以使用任何能清晰表示视觉状态的描述性术语,只要它们是唯一的即可。
state
和 model(s)
的配置遵循与单状态方块相同的规则。如果您对任何细节不确定,请参阅相关文档。
变体
在最后一步中,我们需要组合所有自定义属性,列出所有可能的组合,并为每个组合分配内部方块标识符。如果您不熟悉 内部标识符,请参阅相关文档。
对于属性及其值,使用 =
连接它们(例如,axis=y
)。当多个属性一起出现时,用逗号分隔(例如,axis=y,age=7
)。
blocks:
default:palm_log:
states:
variants:
axis=x:
appearance: axisX # 指的是我们在“appearances”中刚刚定义的外观名称。
id: 0
axis=y:
appearance: axisY
id: 1
axis=z:
appearance: axisZ
id: 2
完整配置
blocks:
default:palm_log:
states:
properties:
axis:
type: axis
default: y
appearances:
axisY:
state: "note_block:0"
model:
path: "minecraft:block/custom/stripped_palm_log"
generation:
parent: "minecraft:block/cube_column"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
axisX:
state: "note_block:1"
model:
x: 90
y: 90
path: "minecraft:block/custom/stripped_palm_log_horizontal"
generation:
parent: "minecraft:block/cube_column_horizontal"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
axisZ:
state: "note_block:2"
model:
x: 90
path: "minecraft:block/custom/stripped_palm_log_horizontal"
generation:
parent: "minecraft:block/cube_column_horizontal"
textures:
"end": "minecraft:block/custom/palm_log_top"
"side": "minecraft:block/custom/palm_log"
variants:
axis=x:
appearance: axisX
id: 0
axis=y:
appearance: axisY
id: 1
axis=z:
appearance: axisZ
id: 2
要为特定状态自定义方块设置,请添加如下配置:
variants:
"distance=7,persistent=false,waterlogged=false":
appearance: "default"
id: 6
settings:
is-randomly-ticking: true
懵逼了?
您可能会对 id
和 state
之间的关系感到困惑——为什么需要配置这两个参数?除了使配置更复杂之外,这么做的实际目的是什么?
要理解原因,您需要了解 CraftEngine 在底层是如何实现自定义方块的。让我们从讨论插件背后的原理开始。
未使用的方块状态
首先,让我问你一个简单的问题:原版树叶有多少种不同的外观?我相信你会很快得出答案:两种方块状态——含水和不含水。
但你知道服务器端需要为单一类型的树叶维护多少种方块状态吗?
答案
正确答案是 28。你答对了吗?
但这个数字是怎么计算出来的呢?让我们按下F3打开调试屏幕,然后将视角对准树叶并且确保处在你的方块交互距离内。你会注意到在方块命名空间ID下列出了几个键值对——这些代表了方块的属性。或者,你可以使用调试棒来检查这些属性。
- waterlogged:2 种状态(true/false)。
- persistent:2 种状态(true/false)。
- distance:7 种状态(值从 1 到 7)。
因此,树叶可能的状态总数是 2 × 2 × 7 = 28
。
然后你会意识到——哇!树叶方块有这么多状态,但只有两种视觉变体,我们能否将那些多余的状态重新用于自定义方块外观?正是如此!这就是 mappings.yml
文件发挥作用的地方。通过 mappings.yml
,我们可以将看似相同的方块状态映射为共享相同的视觉表现的方块状态。这种巧妙的方法释放了那些冗余状态,供我们的自定义方块实现使用。
mappings.yml
以下是默认 mappings.yml 配置的摘录。它将所有 distance=1-7 的橡树树叶映射到 distance=7 且 persistent=true。这意味着世界中的每个原版橡树树叶在技术上都被插件转换为 distance=7、persistent=true 的橡树树叶——但你无法从视觉上分辨差异,因为它们看起来完全相同。
"minecraft:oak_leaves[distance=1,persistent=false,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=2,persistent=false,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=3,persistent=false,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=4,persistent=false,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=5,persistent=false,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=6,persistent=false,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=7,persistent=false,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=1,persistent=true,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=2,persistent=true,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=3,persistent=true,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=4,persistent=true,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=5,persistent=true,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
"minecraft:oak_leaves[distance=6,persistent=true,waterlogged=false]": minecraft:oak_leaves[distance=7,persistent=true,waterlogged=false]
标识符与方块状态
现在,让我们回到刚刚讨论的 id 和 state。方块状态指的是我们在 mappings.yml 中释放的“未使用”方块状态,而 id 代表服务器端实际存在的方块状态。我们需要通过 数据包魔法 在这两个参数之间建立一座桥梁,以便服务器上实际存在的新方块能够映射到那些释放的原版方块状态,从而表现为自定义方块。
真实方块状态不足
默认情况下,插件会生成并释放与可用视觉方块状态数量相等的真实方块状态。然而,在某些情况下,我们可能需要特殊机制,这些机制需要更多的真实方块状态但只需要较少的视觉方块状态。在这种场景下,多个真实方块状态将被映射到相同的视觉方块状态,从而导致标题中提到的“真实方块不足”问题。
为了解决这个问题,您需要使用 additional-real-blocks.yml
文件来注册额外的真实方块。