path = $path; if(!file_exists($this->path)){ mkdir($this->path, 0777, true); } $nbt = new BigEndianNBTStream(); $levelData = $nbt->readCompressed(file_get_contents($this->getPath() . "level.dat")); if(!($levelData instanceof CompoundTag) or !$levelData->hasTag("Data", CompoundTag::class)){ throw new LevelException("Invalid level.dat"); } $this->levelData = $levelData->getCompoundTag("Data"); if(!$this->levelData->hasTag("generatorName", StringTag::class)){ $this->levelData->setString("generatorName", (string) Generator::getGenerator("DEFAULT"), true); } if(!$this->levelData->hasTag("generatorOptions", StringTag::class)){ $this->levelData->setString("generatorOptions", ""); } } public function getPath() : string{ return $this->path; } public function getName() : string{ return $this->levelData->getString("LevelName"); } public function getTime() : int{ return $this->levelData->getLong("Time", 0, true); } public function setTime(int $value){ $this->levelData->setLong("Time", $value, true); //some older PM worlds had this in the wrong format } public function getSeed() : int{ return $this->levelData->getLong("RandomSeed"); } public function setSeed(int $value){ $this->levelData->setLong("RandomSeed", $value); } public function getSpawn() : Vector3{ return new Vector3($this->levelData->getInt("SpawnX"), $this->levelData->getInt("SpawnY"), $this->levelData->getInt("SpawnZ")); } public function setSpawn(Vector3 $pos){ $this->levelData->setInt("SpawnX", $pos->getFloorX()); $this->levelData->setInt("SpawnY", $pos->getFloorY()); $this->levelData->setInt("SpawnZ", $pos->getFloorZ()); } public function doGarbageCollection(){ } /** * @return CompoundTag */ public function getLevelData() : CompoundTag{ return $this->levelData; } public function saveLevelData(){ $nbt = new BigEndianNBTStream(); $buffer = $nbt->writeCompressed(new CompoundTag("", [ $this->levelData ])); file_put_contents($this->getPath() . "level.dat", $buffer); } public function loadChunk(int $chunkX, int $chunkZ, bool $create = false) : ?Chunk{ $chunk = $this->readChunk($chunkX, $chunkZ); if($chunk === null and $create){ $chunk = new Chunk($chunkX, $chunkZ); } return $chunk; } public function saveChunk(Chunk $chunk) : void{ if(!$chunk->isGenerated()){ throw new \InvalidStateException("Cannot save un-generated chunk"); } $this->writeChunk($chunk); } abstract protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk; abstract protected function writeChunk(Chunk $chunk) : void; }