public function unloadChunk($x, $z, $safe = true, $trySave = true) { if ($safe === true and $this->isChunkInUse($x, $z)) { return false; } if (!$this->isChunkLoaded($x, $z)) { return true; } $this->timings->doChunkUnload->startTiming(); $index = Level::chunkHash($x, $z); $chunk = $this->getChunk($x, $z); if ($chunk !== null and $chunk->getProvider() !== null) { $this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($chunk)); if ($ev->isCancelled()) { $this->timings->doChunkUnload->stopTiming(); return false; } } try { if ($chunk !== null) { if ($trySave and $this->getAutoSave()) { $entities = 0; foreach ($chunk->getEntities() as $e) { if ($e instanceof Player) { continue; } ++$entities; } if ($chunk->hasChanged() or count($chunk->getTiles()) > 0 or $entities > 0) { $this->provider->setChunk($x, $z, $chunk); $this->provider->saveChunk($x, $z); } } foreach ($this->getChunkLoaders($x, $z) as $loader) { $loader->onChunkUnloaded($chunk); } } $this->provider->unloadChunk($x, $z, $safe); } catch (\Exception $e) { $logger = $this->server->getLogger(); $logger->error($this->server->getLanguage()->translateString("pocketmine.level.chunkUnloadError", [$e->getMessage()])); if ($logger instanceof MainLogger) { $logger->logException($e); } } unset($this->chunks[$index]); unset($this->chunkTickList[$index]); unset($this->chunkCache[$index]); $this->timings->doChunkUnload->stopTiming(); return true; }
public function unloadChunk($x, $z, $safe = true) { if ($safe === true and $this->isChunkInUse($x, $z)) { return false; } $this->timings->doChunkUnload->startTiming(); $index = PHP_INT_SIZE === 8 ? ($x & 4294967295.0) << 32 | $z & 4294967295.0 : $x . ":" . $z; $chunk = $this->getChunk($x, $z); if ($chunk !== null) { $this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($chunk)); if ($ev->isCancelled()) { return false; } } try { if ($chunk !== null and $this->getAutoSave()) { $this->provider->setChunk($x, $z, $chunk); $this->provider->saveChunk($x, $z); } $this->provider->unloadChunk($x, $z, $safe); } catch (\Exception $e) { $logger = $this->server->getLogger(); $logger->error("Error when unloading a chunk: " . $e->getMessage()); if ($logger instanceof MainLogger) { $logger->logException($e); } } unset($this->chunks[$index]); unset($this->usedChunks[$index]); unset($this->chunkTickList[$index]); Cache::remove("world:" . $this->getId() . ":{$index}"); $this->timings->doChunkUnload->stopTiming(); return true; }
public function doChunkGarbageCollection() { $this->timings->doChunkGC->startTiming(); $X = null; $Z = null; foreach ($this->chunks as $index => $chunk) { if (!isset($this->usedChunks[$index])) { Level::getXZ($index, $X, $Z); $this->unloadChunkRequest($X, $Z, true); } } if (count($this->unloadQueue) > 0) { foreach ($this->unloadQueue as $index => $time) { Level::getXZ($index, $X, $Z); if ($this->getAutoSave()) { $this->provider->saveChunk($X, $Z); } //If the chunk can't be unloaded, it stays on the queue if ($this->unloadChunk($X, $Z, true)) { unset($this->unloadQueue[$index]); } } } foreach ($this->usedChunks as $i => $c) { if (count($c) === 0) { Level::getXZ($i, $X, $Z); if (!$this->isSpawnChunk($X, $Z)) { if ($this->getAutoSave()) { $this->provider->saveChunk($X, $Z); } $this->unloadChunk($X, $Z, true); } } } $this->timings->doChunkGC->stopTiming(); }