自定义重力方块
自定义重力方块可以模拟沙子、沙砾等方块的下落行为。当方块下方为空气时,方块会转为下落方块实体并受重力影响向下运动。你可以通过 netease:fall 组件精细控制下落加速度、伤害、存活时长等参数。
前置条件
本功能不需要开启实验性玩法。请先阅读 自定义基础方块 了解方块注册流程和 JSON 组件基础。如果需要监听下落相关事件,还需了解 Python 脚本开发。
概述
自定义重力方块的核心原理:通过 base_block: "custom_heavy_block" 让引擎将方块识别为重力方块类型。当方块下方变为空气时,引擎会将方块转换为一个下落方块实体(Falling Block Entity),该实体按照物理参数向下运动,直到碰到地面或超时被销毁。
下落结束后,方块实体会尝试在落地位置重新放置为方块。如果落地位置被占据,方块实体会被破坏并掉落物品(除非 cancel_drop 设为 true)。
netease:fall 组件
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
send_python_event | bool | false | 可选,是否发送下落相关事件至 Python 脚本 |
fall_acceleration | float | 0.04 | 可选,每 tick 增加的垂直向下速度 |
adjust_percentage | float | 0.98 | 可选,每 tick 移动后速度乘以的衰减系数 |
hurt_entity | bool | false | 可选,下落结束后是否对碰撞范围内的实体造成伤害 |
fall_damage_amount | float | 2.0 | 可选,原版下落伤害计算后的伤害倍率 |
max_fall_damage | int | 40 | 可选,乘以倍率后的最大伤害上限 |
min_height_remove_tick | int | 100 | 可选,方块实体低于区块最低高度后,经过该 tick 数强制删除 |
force_break_tick | int | 600 | 可选,下落方块实体存在超过该 tick 数后强制破坏 |
cancel_drop | bool | false | 可选,方块实体被破坏时是否取消掉落方块物品 |
下落物理
每个 tick,引擎按以下伪代码更新下落方块实体的运动状态:
while Tick:
falling_block.move_vector.y -= fall_acceleration # 1. 向下加速
move(falling_block) # 2. 按当前速度移动
falling_block.move_vector *= adjust_percentage # 3. 速度衰减参数影响:
| 参数 | 增大效果 | 减小效果 |
|---|---|---|
fall_acceleration | 下落加速更快,落地更快 | 下落缓慢,类似月球重力 |
adjust_percentage | 接近 1.0 时衰减极少,下落更快 | 低于 0.9 时明显减速,类似空气阻力 |
默认值(fall_acceleration: 0.04、adjust_percentage: 0.98)模拟原版沙子的下落行为。
伤害计算
当 hurt_entity 设为 true 时,下落方块实体落地后会对碰撞范围内的实体造成伤害。
伤害公式:最终伤害 = min(原版下落伤害 × fall_damage_amount, max_fall_damage)
原版下落伤害与下落高度相关,下落越高伤害越大。
碰撞限制
原版下落方块实体没有实时碰撞检测。如果两个下落方块速度不一致,可能会出现一个方块实体穿过另一个的情况。伤害计算也不是在接触瞬间,而是在落地时检测范围内是否有实体。
相关事件
当 send_python_event 设为 true 时,以下事件会发送到 Python 脚本层:
| 事件 | 触发时机 |
|---|---|
HeavyBlockStartFallingServerEvent | 重力方块开始下落(方块转为下落实体时) |
FallingBlockCauseDamageBeforeServerEvent | 下落方块即将对实体造成伤害前,可取消伤害 |
FallingBlockBreakServerEvent | 下落方块实体被破坏时(超时、无法放置等) |
FallingBlockReturnHeavyBlockServerEvent | 下落方块实体成功落地并重新放置为方块时 |
性能提示
如果不需要在脚本中监听上述事件,建议将 send_python_event 保持为 false,以减少事件分发开销。
Python 脚本示例
import server.extraServerApi as serverApi
ServerSystem = serverApi.GetServerSystemCls()
class GravityBlockServer(ServerSystem):
def __init__(self, namespace, systemName):
super(GravityBlockServer, self).__init__(namespace, systemName)
engineNs = serverApi.GetEngineNamespace()
engineSys = serverApi.GetEngineSystemName()
self.ListenForEvent(engineNs, engineSys,
'HeavyBlockStartFallingServerEvent', self, self.OnStartFalling)
self.ListenForEvent(engineNs, engineSys,
'FallingBlockCauseDamageBeforeServerEvent', self, self.OnDamageBefore)
self.ListenForEvent(engineNs, engineSys,
'FallingBlockBreakServerEvent', self, self.OnBreak)
self.ListenForEvent(engineNs, engineSys,
'FallingBlockReturnHeavyBlockServerEvent', self, self.OnReturn)
def OnStartFalling(self, args):
"""重力方块开始下落"""
blockName = args["blockName"]
pos = (args["posX"], args["posY"], args["posZ"])
dimensionId = args["dimensionId"]
entityId = args["entityId"] # 下落方块实体 ID
def OnDamageBefore(self, args):
"""下落方块即将造成伤害,可取消"""
entityId = args["entityId"]
targetId = args["targetId"]
damage = args["damage"]
# 取消对特定实体的伤害
# args["cancel"] = True
def OnBreak(self, args):
"""下落方块被破坏"""
blockName = args["blockName"]
pos = (args["posX"], args["posY"], args["posZ"])
def OnReturn(self, args):
"""下落方块成功落地还原为方块"""
blockName = args["blockName"]
pos = (args["posX"], args["posY"], args["posZ"])完整 JSON 示例
以下示例创建一个自定义重力沙块,下落时对实体造成伤害。
行为包 — 方块定义
文件路径:行为包/netease_blocks/heavy_sand.json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "mymod:heavy_sand",
"base_block": "custom_heavy_block",
"register_to_create_menu": true,
"category": "Nature"
},
"components": {
"minecraft:destroy_time": { "value": 0.5 },
"minecraft:explosion_resistance": { "value": 2.5 },
"minecraft:map_color": "#D2B48C",
"netease:tier": {
"digger": "shovel",
"destroy_special": false
},
"netease:fall": {
"send_python_event": true,
"fall_acceleration": 0.04,
"adjust_percentage": 0.98,
"hurt_entity": true,
"fall_damage_amount": 2.0,
"max_fall_damage": 40,
"min_height_remove_tick": 100,
"force_break_tick": 600,
"cancel_drop": false
}
}
}
}资源包 — terrain_texture.json
{
"resource_pack_name": "mymod",
"texture_name": "atlas.terrain",
"texture_data": {
"mymod:heavy_sand": {
"textures": "textures/blocks/heavy_sand"
}
}
}资源包 — blocks.json
{
"mymod:heavy_sand": {
"textures": "mymod:heavy_sand",
"sound": "sand"
}
}资源包 — 本地化
tile.mymod:heavy_sand.name=重力沙块常见问题
方块下方为空气但不下落
排查步骤:
- 确认
base_block设为custom_heavy_block - 确认行为包 JSON 中配置了
netease:fall组件 - 确认方块下方确实是空气方块(不是不可见的方块或流体)
下落方块不造成伤害
排查步骤:
- 确认
hurt_entity设为true - 确认
fall_damage_amount> 0 - 伤害是在落地时计算的,方块需要有足够的下落高度才能产生伤害
- 如果监听了
FallingBlockCauseDamageBeforeServerEvent,确认没有在回调中取消伤害
下落方块长时间不消失
原因: force_break_tick 默认为 600(30 秒)。如果方块在下落过程中无法落地(如一直处于空中),会在到达 force_break_tick 后被强制破坏。
你可以调小 force_break_tick 来加快超时销毁。
事件没有触发
原因: send_python_event 默认为 false。需要将其设为 true 才能接收到 HeavyBlockStartFallingServerEvent 等事件。
提示
netease:block_properties 中的 breaks_when_fallen_on_by_heavy 属性可以让某些方块在被重力方块砸中时破碎(类似火把被沙子砸断)。可以配合重力方块使用。
下一步
- 自定义基础方块 — 回顾方块注册流程和组件配置
- 方块组件速查 — 所有方块组件一览
- Python 脚本开发 — 学习如何监听下落方块事件
- 特殊方块类型 — 刷怪箱、传送门、流体等更多特殊方块
