diff --git a/src/MemoryManager.php b/src/MemoryManager.php index dbcd80092..f45647969 100644 --- a/src/MemoryManager.php +++ b/src/MemoryManager.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine; use pocketmine\event\server\LowMemoryEvent; +use pocketmine\network\mcpe\cache\ChunkCache; use pocketmine\scheduler\DumpWorkerMemoryTask; use pocketmine\scheduler\GarbageCollectionTask; use pocketmine\timings\Timings; @@ -187,6 +188,7 @@ class MemoryManager{ foreach($this->server->getWorldManager()->getWorlds() as $world){ $world->clearCache(true); } + ChunkCache::pruneCaches(); } if($this->lowMemChunkGC){ diff --git a/src/network/mcpe/cache/ChunkCache.php b/src/network/mcpe/cache/ChunkCache.php index 269451f49..bf0ee4419 100644 --- a/src/network/mcpe/cache/ChunkCache.php +++ b/src/network/mcpe/cache/ChunkCache.php @@ -36,9 +36,6 @@ use function strlen; /** * This class is used by the current MCPE protocol system to store cached chunk packets for fast resending. - * - * TODO: make MemoryManager aware of this so the cache can be destroyed when memory is low - * TODO: this needs a hook for world unloading */ class ChunkCache implements ChunkListener{ /** @var self[][] */ @@ -69,6 +66,19 @@ class ChunkCache implements ChunkListener{ return self::$instances[$worldId][$compressorId]; } + public static function pruneCaches() : void{ + foreach(self::$instances as $compressorMap){ + foreach($compressorMap as $chunkCache){ + foreach($chunkCache->caches as $chunkHash => $promise){ + if($promise->hasResult()){ + //Do not clear promises that are not yet fulfilled; they will have requesters waiting on them + unset($chunkCache->caches[$chunkHash]); + } + } + } + } + } + /** @var World */ private $world; /** @var Compressor */