From 0fec58730b82aeeb1c5bf7d30e611fa564cc17a7 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 24 Nov 2018 17:35:56 +0000 Subject: [PATCH] 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. --- src/pocketmine/level/Level.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 89b666f8d..67617f40c 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -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;