[MCBE]方块被放置后发生了什么?方块更新如何影响红石系统?
何以贯之
编辑于 2025年02月26日 13:32
收录于文集
共7篇

当玩家或命令方块等放置方块时,游戏会通过 BlockSource::setBlock() 函数完成放置流程。

代码块
text/x-c++src
自动换行
复制代码
bool BlockSource::setBlock(
    const BlockPos &pos,
    const Block &block,
    int updateFlags,
    std::shared_ptr blockEntity,
    const ActorBlockSyncMessage *syncMsg,
    Actor *blockChangeSource
);
复制成功
  • pos: 方块坐标

  • block: 方块对象本身

  • updateFlags: 一个标记,一般为 3(二进制 11)

  • blockEntity: 方块的方块实体(可空)

  • syncMsg: 未知

  • blockChangeSource: 未知

BlockSource::setBlock()

首先检查 y 坐标,也就是高度限制。然后找到方块所在区块,调用区块的函数 LevelChunk::setBlock(),由该区块完成方块的放置。

代码块
text/x-c++src
自动换行
复制代码
const Block &LevelChunk::setBlock(
    const ChunkBlockPos &pos,
    const Block &block,
    BlockSource *issuingSource,
    std::shared_ptr blockEntity
);
复制成功
  • pos: 方块在区块内的坐标

  • block: 方块对象

  • issuingSource: BlockSource

  • blockEntity: 方块的方块实体(可空)

之后调用 BlockSource::_blockChanged(),完成方块更新。

代码块
text/x-c++src
自动换行
复制代码
void BlockSource::_blockChanged(
    const BlockPos &pos,
    uint32_t layer,
    const Block &block,
    const Block &previousBlock,
    int updateFlags,
    const ActorBlockSyncMessage *syncMsg,
    Actor* blockChangeSource
);
复制成功

  • pos: 方块坐标

  • layer: 层号(共 2 层,第 2 层用于实现含水方块)

  • block: 放置的方块

  • previousBlock: 原来的方块

  • updateFlags: 更新标记

  • syncMsg: 未知

  • blockChangeSource: 未知

LevelChunk::setBlock()

该函数会先真正放置下方块,同时会完成含水方块的处理。

然后会更新光照,配置方块实体并插入到本区块的方块实体列表中。

接下来调用方块的 onPlace() 函数,由其完成自身的一些更新,比如铁轨的连接;如果自己属于红石元件,也会在这里创建红石元件,添加到红石系统的待添加列表中,并初始化红石设置,比如中继器挡位。

代码块
text/x-c++src
自动换行
复制代码
virtual void xxxBlock::onPlace(
    BlockSource ®ion,
    const BlockPos &pos
) const;
复制成功

最后调用红石系统的 CircuitSystem::invalidatePos() 函数,处理该方块对周围电路的影响。

代码块
text/x-c++src
自动换行
复制代码
void CircuitSystem::invalidatePos(const BlockPos &pos);
复制成功

BlockSource::_blockChanged()

该函数内会依次调用六个面的方块的`neighborChanged()`函数,也就是广为人知的 NC 更新。观察者通过此函数检测方块更新。

六个面的更新顺序为:西 东 南 北 上 下

CircuitSystem::invalidatePos()

如果自己是红石元件,将自身所有信号源添加到待更新列表中。

如果不是,检查周围六个面是否是红石元件,如果是将其添加到待更新列表中。

然后将该元件的所有信号源添加到待更新列表中。

六个面的遍历顺序与前面不同,为:下 上 北 南 西 东

注意!!:只有生产者和电容器能被添加到待更新列表中,其它类型元件会被直接跳过。