游戏中所有的方块都围绕着 BlockLegacy 这个类设计。
这个类定义了方块的通用基本属性,比如方块 id,碰撞箱,是否为重力方块等。
所有的方块类都继承或间接继承自这个类,比如门(DoorBlock),泥土(DirtBlock)。
每个方块类都只有一个实例,同种方块将指向同一个实例。
一种方块可能有多种状态,将方块的实例和一个方块状态包装在一起,构成通常意义上的方块(Block)。
同种方块的不同方块状态,它们对应的 BlockLegacy 是相同的。
进入游戏时,游戏会为每种方块创建一个 BlockLegacy 实例,然后遍历它们的所有方块状态,为每个方块状态创建一个 Block,分别保存在对应的实例内。
每个 BlockLegacy 实例内拥有不同方块状态的 Block 列表,称为 BlockPermutations。
无论是 Block 还是 BlockLegacy,它们创建后都是不应改变的。方块的使用就如同查询大字典,比如门从关到开状态改变,只是从关闭状态的 Block 获取对应的 DoorBlock,再从其 BlockPermutations 内找到开启状态的 Block,最后替换放置。
由前文可知,BlockLegacy 的单实例模式(准确说是享元模式)使得同种方块共用了大部分数据,且这些数据确定后就不应改变。方块的不变性是其与实体的本质区别。如果你试图修改一个草方块的碰撞箱,那么所有草方块的碰撞箱都会被修改。
这带来了许多限制,比如容器就难以实现,两个箱子只能共用一个空间。
所以方块实体的概念诞生了,它赋予方块类似实体互相独立的特点。
所有方块实体类都继承自 BlockActor 这个类,比如箱子方块实体(ChestBlockActor)。
一个方块实体内部包含了其对应的 Block,和要保存的特殊数据。相比方块,方块实体不需要提前创建,且可以多次实例化,这意味着你可以创建两个箱子方块实体对象,保存不同的容器内容。
方块实体创建后保存在区块(LevelChunk)内,可以通过区块坐标查找到方块实体。
方块实体跟随方块创建,当放置一个方块时,如果这个方块有方块实体,就会新实例化一个对应的方块实体,并保存在区块中。放置方块时也可以选择使用已有的方块实体,这样就不会新创建方块实体。
当方块被替换,被破坏(实际上就是替换为空气方块(AirBlock)),对应的方块实体也会从区块中移除。
BlockLegacy、Block、BlockActor 都使用智能指针管理。