Skip to content

自定义重力方块 ​

自定义重力方块可以模拟沙子、沙砾等方块的下落行为。当方块下方为空气时,方块会转为下落方块实体并受重力影响向下运动。你可以通过 netease:fall 组件精细控制下落加速度、伤害、存活时长等参数。

前置条件

本功能不需要开启实验性玩法。请先阅读 自定义基础方块 了解方块注册流程和 JSON 组件基础。如果需要监听下落相关事件,还需了解 Python 脚本开发。

概述 ​

自定义重力方块的核心原理:通过 base_block: "custom_heavy_block" 让引擎将方块识别为重力方块类型。当方块下方变为空气时,引擎会将方块转换为一个下落方块实体(Falling Block Entity),该实体按照物理参数向下运动,直到碰到地面或超时被销毁。

下落结束后,方块实体会尝试在落地位置重新放置为方块。如果落地位置被占据,方块实体会被破坏并掉落物品(除非 cancel_drop 设为 true)。

netease:fall 组件 ​

键类型默认值说明
send_python_eventboolfalse可选,是否发送下落相关事件至 Python 脚本
fall_accelerationfloat0.04可选,每 tick 增加的垂直向下速度
adjust_percentagefloat0.98可选,每 tick 移动后速度乘以的衰减系数
hurt_entityboolfalse可选,下落结束后是否对碰撞范围内的实体造成伤害
fall_damage_amountfloat2.0可选,原版下落伤害计算后的伤害倍率
max_fall_damageint40可选,乘以倍率后的最大伤害上限
min_height_remove_tickint100可选,方块实体低于区块最低高度后,经过该 tick 数强制删除
force_break_tickint600可选,下落方块实体存在超过该 tick 数后强制破坏
cancel_dropboolfalse可选,方块实体被破坏时是否取消掉落方块物品

下落物理 ​

每个 tick,引擎按以下伪代码更新下落方块实体的运动状态:

python
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 脚本示例 ​

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

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 ​

json
{
    "resource_pack_name": "mymod",
    "texture_name": "atlas.terrain",
    "texture_data": {
        "mymod:heavy_sand": {
            "textures": "textures/blocks/heavy_sand"
        }
    }
}

资源包 — blocks.json ​

json
{
    "mymod:heavy_sand": {
        "textures": "mymod:heavy_sand",
        "sound": "sand"
    }
}

资源包 — 本地化 ​

tile.mymod:heavy_sand.name=重力沙块

常见问题 ​

方块下方为空气但不下落 ​

排查步骤:

  1. 确认 base_block 设为 custom_heavy_block
  2. 确认行为包 JSON 中配置了 netease:fall 组件
  3. 确认方块下方确实是空气方块(不是不可见的方块或流体)

下落方块不造成伤害 ​

排查步骤:

  1. 确认 hurt_entity 设为 true
  2. 确认 fall_damage_amount > 0
  3. 伤害是在落地时计算的,方块需要有足够的下落高度才能产生伤害
  4. 如果监听了 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 属性可以让某些方块在被重力方块砸中时破碎(类似火把被沙子砸断)。可以配合重力方块使用。

下一步 ​