Level: fixed recursion bug when reading dynamic states

calculating dynamic states in some cases requires getting properties from neighbouring blocks, but getting these blocks also causes their dynamic states to be calculated, leading to a bouncing recursion.
This change allows retrieving blocks without calculating dynamic state information, if the call was generated by calculating dynamic state information.
Since these blocks are incomplete, they should not be cached and are only used to allow another adjacent block to complete its state. It is therefore not possible for a block's dynamic states to depend on another block's dynamic states.

This recursion bug was observable by running /gc and walking into a door, which would cause the server to freeze and crash.
This commit is contained in:
Dylan K. Taylor 2018-11-24 17:35:56 +00:00
parent d426d18b77
commit 0fec58730b

View File

@ -1372,7 +1372,19 @@ class Level implements ChunkManager, Metadatable{
$block->y = $y;
$block->z = $z;
$block->level = $this;
$block->readStateFromWorld();
static $dynamicStateRead = false;
if($dynamicStateRead){
//this call was generated by a parent getBlock() call calculating dynamic stateinfo
//don't calculate dynamic state and don't add to block cache (since it won't have dynamic state calculated).
//this ensures that it's impossible for dynamic state properties to recursively depend on each other.
$addToCache = false;
}else{
$dynamicStateRead = true;
$block->readStateFromWorld();
$dynamicStateRead = false;
}
if($addToCache and $blockHash !== null){
$this->blockCache[$chunkHash][$blockHash] = $block;