예제 #1
0
 public function __construct(LevelProvider $level, $regionX, $regionZ)
 {
     $this->x = $regionX;
     $this->z = $regionZ;
     $this->levelProvider = $level;
     $this->filePath = $this->levelProvider->getPath() . "region/r.{$regionX}.{$regionZ}.mcr";
     $exists = file_exists($this->filePath);
     touch($this->filePath);
     $this->filePointer = fopen($this->filePath, "r+b");
     stream_set_read_buffer($this->filePointer, 1024 * 16);
     //16KB
     stream_set_write_buffer($this->filePointer, 1024 * 16);
     //16KB
     if (!$exists) {
         $this->createBlank();
     } else {
         $this->loadLocationTable();
     }
 }
예제 #2
0
 public function doChunkGarbageCollection()
 {
     $this->timings->doChunkGC->startTiming();
     $X = null;
     $Z = null;
     foreach ($this->chunks as $index => $chunk) {
         if (!isset($this->unloadQueue[$index]) and (!isset($this->usedChunks[$index]) or count($this->usedChunks[$index]) === 0)) {
             if (PHP_INT_SIZE === 8) {
                 $X = $index >> 32 << 32 >> 32;
                 $Z = ($index & 4294967295.0) << 32 >> 32;
             } else {
                 list($X, $Z) = explode(":", $index);
                 $X = (int) $X;
                 $Z = (int) $Z;
             }
             if (!$this->isSpawnChunk($X, $Z)) {
                 $this->unloadChunkRequest($X, $Z, true);
             }
         }
     }
     foreach ($this->provider->getLoadedChunks() as $chunk) {
         if (!isset($this->chunks[PHP_INT_SIZE === 8 ? ($chunk->getX() & 4294967295.0) << 32 | $chunk->getZ() & 4294967295.0 : $chunk->getX() . ":" . $chunk->getZ()])) {
             $this->provider->unloadChunk($chunk->getX(), $chunk->getZ(), false);
         }
     }
     $this->provider->doGarbageCollection();
     $this->timings->doChunkGC->stopTiming();
 }
예제 #3
0
 public function doChunkGarbageCollection()
 {
     $this->timings->doChunkGC->startTiming();
     $X = null;
     $Z = null;
     foreach ($this->chunks as $index => $chunk) {
         if (!isset($this->unloadQueue[$index]) and (!isset($this->usedChunks[$index]) or count($this->usedChunks[$index]) === 0)) {
             Level::getXZ($index, $X, $Z);
             if (!$this->isSpawnChunk($X, $Z)) {
                 $this->unloadChunkRequest($X, $Z, true);
             }
         }
     }
     foreach ($this->provider->getLoadedChunks() as $chunk) {
         if (!isset($this->chunks[Level::chunkHash($chunk->getX(), $chunk->getZ())])) {
             $this->provider->unloadChunk($chunk->getX(), $chunk->getZ(), false);
         }
     }
     $this->provider->doGarbageCollection();
     $this->timings->doChunkGC->stopTiming();
 }
예제 #4
0
 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();
 }
예제 #5
0
 /**
  * @param string        $data
  * @param LevelProvider $provider
  *
  * @return Chunk
  */
 public static function fromBinary($data, LevelProvider $provider = null)
 {
     try {
         $chunkX = PHP_INT_SIZE === 8 ? unpack("V", substr($data, 0, 4))[1] << 32 >> 32 : unpack("V", substr($data, 0, 4))[1];
         $chunkZ = PHP_INT_SIZE === 8 ? unpack("V", substr($data, 4, 4))[1] << 32 >> 32 : unpack("V", substr($data, 4, 4))[1];
         $chunkData = substr($data, 8, -1);
         $flags = ord(substr($data, -1));
         $entities = null;
         $tiles = null;
         if ($provider instanceof LevelDB) {
             $nbt = new NBT(NBT::LITTLE_ENDIAN);
             $entityData = $provider->getDatabase()->get(substr($data, 0, 8) . "2");
             if ($entityData !== false and strlen($entityData) > 0) {
                 $nbt->read($entityData, true);
                 $entities = $nbt->getData();
                 if (!is_array($entities)) {
                     $entities = [$entities];
                 }
             }
             $tileData = $provider->getDatabase()->get(substr($data, 0, 8) . "1");
             if ($tileData !== false and strlen($tileData) > 0) {
                 $nbt->read($tileData, true);
                 $tiles = $nbt->getData();
                 if (!is_array($tiles)) {
                     $tiles = [$tiles];
                 }
             }
         }
         $chunk = new Chunk($provider instanceof LevelProvider ? $provider : LevelDB::class, $chunkX, $chunkZ, $chunkData, $entities, $tiles);
         if ($flags & 0x1) {
             $chunk->setGenerated();
         }
         if ($flags & 0x2) {
             $chunk->setPopulated();
         }
         return $chunk;
     } catch (\Exception $e) {
         return null;
     }
 }
예제 #6
0
 public function doChunkGarbageCollection()
 {
     $this->timings->doChunkGC->startTiming();
     $X = \null;
     $Z = \null;
     foreach ($this->chunks as $index => $chunk) {
         if (!isset($this->unloadQueue[$index]) and (!isset($this->usedChunks[$index]) or \count($this->usedChunks[$index]) === 0)) {
             $X = $index >> 32 << 32 >> 32;
             $Z = ($index & 0xffffffff) << 32 >> 32;
             if (!$this->isSpawnChunk($X, $Z)) {
                 $this->unloadChunkRequest($X, $Z, \true);
             }
         }
     }
     foreach ($this->provider->getLoadedChunks() as $chunk) {
         if (!isset($this->chunks[($chunk->getX() & 0xffffffff) << 32 | $chunk->getZ() & 0xffffffff])) {
             $this->provider->unloadChunk($chunk->getX(), $chunk->getZ(), \false);
         }
     }
     $this->provider->doGarbageCollection();
     $this->timings->doChunkGC->stopTiming();
 }
예제 #7
0
 /**
  * @param string        $data
  * @param LevelProvider $provider
  *
  * @return Chunk
  */
 public static function fromBinary($data, LevelProvider $provider = \null)
 {
     try {
         $chunkX = \unpack("V", \substr($data, 0, 4))[1];
         $chunkZ = \unpack("V", \substr($data, 4, 4))[1];
         $chunkData = \substr($data, 8, -1);
         $flags = \ord(\substr($data, -1));
         $entities = \null;
         $tiles = \null;
         $extraData = [];
         if ($provider instanceof LevelDB) {
             $nbt = new NBT(NBT::LITTLE_ENDIAN);
             $entityData = $provider->getDatabase()->get(\substr($data, 0, 8) . LevelDB::ENTRY_ENTITIES);
             if ($entityData !== \false and \strlen($entityData) > 0) {
                 $nbt->read($entityData, \true);
                 $entities = $nbt->getData();
                 if (!\is_array($entities)) {
                     $entities = [$entities];
                 }
             }
             $tileData = $provider->getDatabase()->get(\substr($data, 0, 8) . LevelDB::ENTRY_TILES);
             if ($tileData !== \false and \strlen($tileData) > 0) {
                 $nbt->read($tileData, \true);
                 $tiles = $nbt->getData();
                 if (!\is_array($tiles)) {
                     $tiles = [$tiles];
                 }
             }
             $tileData = $provider->getDatabase()->get(\substr($data, 0, 8) . LevelDB::ENTRY_EXTRA_DATA);
             if ($tileData !== \false and \strlen($tileData) > 0) {
                 $stream = new BinaryStream($tileData);
                 $count = $stream->getInt();
                 for ($i = 0; $i < $count; ++$i) {
                     $key = $stream->getInt();
                     $value = $stream->getShort(\false);
                     $extraData[$key] = $value;
                 }
             }
         }
         $chunk = new Chunk($provider instanceof LevelProvider ? $provider : LevelDB::class, $chunkX, $chunkZ, $chunkData, $entities, $tiles);
         if ($flags & 0x1) {
             $chunk->setGenerated();
         }
         if ($flags & 0x2) {
             $chunk->setPopulated();
         }
         if ($flags & 0x4) {
             $chunk->setLightPopulated();
         }
         return $chunk;
     } catch (\Exception $e) {
         return \null;
     }
 }
예제 #8
0
 public function doChunkGarbageCollection()
 {
     $this->timings->doChunkGC->startTiming();
     $X = \null;
     $Z = \null;
     foreach ($this->chunks as $index => $chunk) {
         if (!isset($this->unloadQueue[$index]) and (!isset($this->usedChunks[$index]) or \count($this->usedChunks[$index]) === 0)) {
             list($X, $Z) = \explode(":", $index);
             $X = (int) $X;
             $Z = (int) $Z;
             if (!$this->isSpawnChunk($X, $Z)) {
                 $this->unloadChunkRequest($X, $Z, \true);
             }
         }
     }
     foreach ($this->provider->getLoadedChunks() as $chunk) {
         if (!isset($this->chunks[$chunk->getX() . ":" . $chunk->getZ()])) {
             $this->provider->unloadChunk($chunk->getX(), $chunk->getZ(), \false);
         }
     }
     $this->provider->doGarbageCollection();
     $this->timings->doChunkGC->stopTiming();
 }