From cbaeec54ff6a8406ba01eb8c45b6e31eacc7d63c Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Fri, 13 Jun 2014 20:04:07 +0200 Subject: [PATCH] Added biomeIds and biomeColors to Anvil format --- src/pocketmine/level/Level.php | 56 +++++++++++++++---- src/pocketmine/level/format/Chunk.php | 42 ++++++++++++++ src/pocketmine/level/format/SimpleChunk.php | 4 +- src/pocketmine/level/format/anvil/Chunk.php | 14 ++++- .../level/format/anvil/RegionLoader.php | 3 + .../level/format/generic/BaseChunk.php | 48 +++++++++++++++- 6 files changed, 153 insertions(+), 14 deletions(-) diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 23b7e0c0d..9b8d22499 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -1055,6 +1055,46 @@ class Level implements ChunkManager, Metadatable{ $this->getChunkAt($x >> 4, $z >> 4)->setBlockLight($x & 0x0f, $y & 0x7f, $z & 0x0f, $level & 0x0f); } + /** + * @param int $x + * @param int $z + * + * @return int + */ + public function getBiomeId($x, $z){ + return $this->getChunkAt($x >> 4, $z >> 4)->getBiomeId($x & 0x0f, $z & 0x0f); + } + + /** + * @param int $x + * @param int $z + * + * @return int[] + */ + public function getBiomeColor($x, $z){ + return $this->getChunkAt($x >> 4, $z >> 4)->getBiomeColor($x & 0x0f, $z & 0x0f); + } + + /** + * @param int $x + * @param int $z + * @param int $biomeId + */ + public function setBiomeId($x, $z, $biomeId){ + $this->getChunkAt($x >> 4, $z >> 4)->setBiomeId($x & 0x0f, $z & 0x0f, $biomeId); + } + + /** + * @param int $x + * @param int $z + * @param int $R + * @param int $G + * @param int $B + */ + public function setBiomeColor($x, $z, $R, $G, $B){ + $this->getChunkAt($x >> 4, $z >> 4)->setBiomeColor($x & 0x0f, $z & 0x0f, $R, $G, $B); + } + /** * Gets the Chunk object * @@ -1189,9 +1229,13 @@ class Level implements ChunkManager, Metadatable{ $orderedLight = ""; $flag = chr($Yndex); + $chunk = $this->getChunkAt($X, $Z, true); + $biomeIds = $chunk->getBiomeIdArray(); + $biomeColors = implode(array_map("pocketmine\\utils\\Binary::writeInt", $chunk->getBiomeColorArray())); + /** @var \pocketmine\level\format\ChunkSection[] $sections */ $sections = []; - foreach($this->getChunkAt($X, $Z, true)->getSections() as $section){ + foreach($chunk->getSections() as $section){ $sections[$section->getY()] = $section; } @@ -1206,15 +1250,7 @@ class Level implements ChunkManager, Metadatable{ } } - - $biomeIDs = str_repeat("\x04", 256); - if($X % 5 === 0 and $Z % 5 === 0){ - $ppm = base64_decode("mpqahISEbW1tZmZmZmZmXl5eXl5eXl5eXl5eXl5eXl5eZmZmZmZmbW1thISEmpqafX19bW1tbW1tS5ubS5qdfbXTSpSbS5ubTJ6cSpWZfbXTSpWZTJ6cbW1tbW1tfX19bW1tbW1tfbXSfbbVSI+dfdL/fbrafbfVSZKefbjYfbjYfbXSSpWZfbTRbW1tbW1tZmZmTKGdSpSbfbrbfbzdfdL/SI+dfbnZfdL/fdL/SZKeSpKYSYyWfbbVS5iaZmZmXl5eS6CiSZmmfdL/fbzeSZCcSpSbfbfVSJKifdL/SpegfbXTfbfWfbXTS5ubXl5eXl5efdL/fdL/fdL/fbrbfbbVSpKYfbTRSpecSpieSZCcfbjYSZCcSpegS52iXl5eXl5eSpegfbnZSZSfSZGafbbVxsYAxsYAxsYAxsYAfbjYfdL/SZikfdL/fdL/Xl5eXl5eSpSbfbjYSpegS5qdfbTRxsYA1tYA1tYAxsYASpegfdL/SZahfbfXSpegXl5eXl5efbfWfdL/AAAAAAAAAAAAxsYA1tYAAAAAxsYAS56gSp2lAAAAfbfVS5iaXl5eXl5efbXSSZWjAAAAfbnZfbjYAAAAxsYAAAAAAAAASZOgAAAAAAAAfbfWSpWZXl5eXl5eTJ6cS56gAAAAAAAAAAAASpegS5ubAAAAfdL/AAAAfdL/AAAASZOgfbfVXl5eXl5eTKKfSp2lAAAAfdL/fdL/Sp2lS56gAAAAfdL/SZamSpyjAAAAfdL/fdL/Xl5eZmZmS6CifdL/AAAASZamSZmmfdL/SZqoAAAAfdL/SJOlfdL/AAAAfbnZSpegZmZmbW1tbW1tfdL/AAAAfbXSSpegfdL/fdL/AAAAfbfXfbrbfdL/AAAAfbbVbW1tbW1tfX19bW1tbW1tAAAAfbTRS5qdSp2lfdL/AAAAS5ubSpSbfbfVAAAAbW1tbW1tfX19mpqahISEbW1tZmZmZmZmXl5eXl5eXl5eXl5eXl5eXl5eZmZmZmZmbW1thISEmpqa"); - $grassColor = "\x01" . implode("\x01", str_split($ppm, 3)); - }else{ - $grassColor = str_repeat("\x01\x85\xb2\x4a", 256); - } - $ordered = zlib_encode(Binary::writeLInt($X) . Binary::writeLInt($Z) . $orderedIds . $orderedData . $orderedSkyLight . $orderedLight . $biomeIDs . $grassColor, ZLIB_ENCODING_DEFLATE, 8); + $ordered = zlib_encode(Binary::writeLInt($X) . Binary::writeLInt($Z) . $orderedIds . $orderedData . $orderedSkyLight . $orderedLight . $biomeIds . $biomeColors, ZLIB_ENCODING_DEFLATE, 8); if(ADVANCED_CACHE == true and $Yndex === 0xff){ Cache::add($identifier, $ordered, 60); diff --git a/src/pocketmine/level/format/Chunk.php b/src/pocketmine/level/format/Chunk.php index ce37e06ee..64c8d893b 100644 --- a/src/pocketmine/level/format/Chunk.php +++ b/src/pocketmine/level/format/Chunk.php @@ -140,6 +140,38 @@ interface Chunk{ */ public function getHighestBlockAt($x, $z); + /** + * @param int $x 0-15 + * @param int $z 0-15 + * + * @return int 0-255 + */ + public function getBiomeId($x, $z); + + /** + * @param int $x 0-15 + * @param int $z 0-15 + * @param int $biomeId 0-255 + */ + public function setBiomeId($x, $z, $biomeId); + + /** + * @param int $x + * @param int $z + * + * @return int[] RGB bytes + */ + public function getBiomeColor($x, $z); + + /** + * @param int $x 0-15 + * @param int $z 0-15 + * @param int $R 0-255 + * @param int $G 0-255 + * @param int $B 0-255 + */ + public function setBiomeColor($x, $z, $R, $G, $B); + /** * Thread-safe read-only chunk * @@ -232,4 +264,14 @@ interface Chunk{ */ public function getSections(); + /** + * @return string[] + */ + public function getBiomeIdArray(); + + /** + * @return int[] + */ + public function getBiomeColorArray(); + } \ No newline at end of file diff --git a/src/pocketmine/level/format/SimpleChunk.php b/src/pocketmine/level/format/SimpleChunk.php index e197f0ac2..88e58a470 100644 --- a/src/pocketmine/level/format/SimpleChunk.php +++ b/src/pocketmine/level/format/SimpleChunk.php @@ -52,8 +52,8 @@ class SimpleChunk{ $this->z = $chunkZ; $this->flags = $flags; for($y = 0; $y < self::$HEIGHT; ++$y){ - $this->ids[$y] = isset($ids[$y]) ? $ids[$y] : str_repeat("\x00", 4096); - $this->meta[$y] = isset($meta[$y]) ? $meta[$y] : str_repeat("\x00", 2048); + $this->ids[$y] = (isset($ids[$y]) and strlen($ids[$y]) === 4096) ? $ids[$y] : str_repeat("\x00", 4096); + $this->meta[$y] = (isset($meta[$y]) and strlen($meta[$y]) === 2048) ? $meta[$y] : str_repeat("\x00", 2048); } } diff --git a/src/pocketmine/level/format/anvil/Chunk.php b/src/pocketmine/level/format/anvil/Chunk.php index 290f99903..8c72d37b6 100644 --- a/src/pocketmine/level/format/anvil/Chunk.php +++ b/src/pocketmine/level/format/anvil/Chunk.php @@ -26,8 +26,12 @@ use pocketmine\level\format\generic\EmptyChunkSection; use pocketmine\level\format\LevelProvider; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\Byte; +use pocketmine\nbt\tag\ByteArray; use pocketmine\nbt\tag\Compound; use pocketmine\nbt\tag\Enum; +use pocketmine\nbt\tag\Int; +use pocketmine\nbt\tag\IntArray; +use pocketmine\utils\Binary; class Chunk extends BaseChunk{ @@ -65,6 +69,14 @@ class Chunk extends BaseChunk{ $this->nbt->Sections->setTagType(NBT::TAG_Compound); } + if(!isset($this->nbt->Biomes) or !($this->nbt->Biomes instanceof ByteArray)){ + $this->nbt->Biomes = new ByteArray("Biomes", str_repeat("\x01", 256)); + } + + if(!isset($this->nbt->BiomeColors) or !($this->nbt->BiomeColors instanceof IntArray)){ + $this->nbt->BiomeColors = new IntArray("BiomeColors", array_fill(0, 156, Binary::readInt("\x01\x85\xb2\x4a"))); + } + $sections = []; foreach($this->nbt->Sections as $section){ if($section instanceof Compound){ @@ -80,7 +92,7 @@ class Chunk extends BaseChunk{ } } - parent::__construct($level, $this->nbt["xPos"], $this->nbt["zPos"], $sections, $this->nbt->Entities->getValue(), $this->nbt->TileEntities->getValue()); + parent::__construct($level, $this->nbt["xPos"], $this->nbt["zPos"], $sections, $this->nbt->Biomes->getValue(), $this->nbt->BiomeColors->getValue(), $this->nbt->Entities->getValue(), $this->nbt->TileEntities->getValue()); } /** diff --git a/src/pocketmine/level/format/anvil/RegionLoader.php b/src/pocketmine/level/format/anvil/RegionLoader.php index 3998552bc..3ec703896 100644 --- a/src/pocketmine/level/format/anvil/RegionLoader.php +++ b/src/pocketmine/level/format/anvil/RegionLoader.php @@ -194,6 +194,9 @@ class RegionLoader{ ]); } + $nbt->Biomes = new ByteArray("Biomes", $chunk->getBiomeIdArray()); + $nbt->BiomeColors = new IntArray("BiomeColors", $chunk->getBiomeColorArray()); + $entities = []; foreach($chunk->getEntities() as $entity){ diff --git a/src/pocketmine/level/format/generic/BaseChunk.php b/src/pocketmine/level/format/generic/BaseChunk.php index 507d0f33a..01cdb0210 100644 --- a/src/pocketmine/level/format/generic/BaseChunk.php +++ b/src/pocketmine/level/format/generic/BaseChunk.php @@ -32,6 +32,7 @@ use pocketmine\tile\Chest; use pocketmine\tile\Furnace; use pocketmine\tile\Sign; use pocketmine\tile\Tile; +use pocketmine\utils\Binary; abstract class BaseChunk implements Chunk{ @@ -44,6 +45,12 @@ abstract class BaseChunk implements Chunk{ /** @var Tile[] */ protected $tiles = []; + /** @var string */ + protected $biomeIds; + + /** @var int[256] */ + protected $biomeColors; + /** @var \WeakRef */ protected $level; @@ -55,12 +62,14 @@ abstract class BaseChunk implements Chunk{ * @param int $x * @param int $z * @param ChunkSection[] $sections + * @param string $biomeIds + * @param int[] $biomeColors * @param Compound[] $entities * @param Compound[] $tiles * * @throws \Exception */ - protected function __construct(LevelProvider $level, $x, $z, array $sections, array $entities = [], array $tiles = []){ + protected function __construct(LevelProvider $level, $x, $z, array $sections, $biomeIds = null, array $biomeColors = [], array $entities = [], array $tiles = []){ $this->level = new \WeakRef($level); $this->x = (int) $x; $this->z = (int) $z; @@ -77,6 +86,18 @@ abstract class BaseChunk implements Chunk{ } } + if(strlen($biomeIds) === 256){ + $this->biomeIds = $biomeIds; + }else{ + $this->biomeIds = str_repeat("\x01", 256); + } + + if(count($biomeColors) === 256){ + $this->biomeColors = $biomeColors; + }else{ + $this->biomeColors = array_fill(0, 256, Binary::readInt("\x01\x85\xb2\x4a")); + } + foreach($entities as $nbt){ if($nbt instanceof Compound){ if(!isset($nbt->id)){ @@ -171,6 +192,23 @@ abstract class BaseChunk implements Chunk{ $this->sections[$y >> 4]->getBlockSkyLight($x, $y & 0x0f, $z, $data); } + public function getBiomeId($x, $z){ + return ord($this->biomeIds{($z << 4) + $x}); + } + + public function setBiomeId($x, $z, $biomeId){ + $this->biomeIds{($z << 4) + $x} = chr($biomeId); + } + + public function getBiomeColor($x, $z){ + $color = $this->biomeColors[($z << 4) + $x] & 0xFFFFFF; + return [$color >> 16, ($color >> 8) & 0xFF, $color & 0xFF]; + } + + public function setBiomeColor($x, $z, $R, $G, $B){ + $this->biomeColors = 0xFF000000 | (($R & 0xFF) << 16) | (($G & 0xFF) << 8) | ($B & 0xFF); + } + public function getHighestBlockAt($x, $z){ for($Y = self::SECTION_COUNT; $Y >= 0; --$Y){ if(!$this->isSectionEmpty($Y)){ @@ -255,4 +293,12 @@ abstract class BaseChunk implements Chunk{ return $this->sections; } + public function getBiomeIdArray(){ + return $this->biomeIds; + } + + public function getBiomeColorArray(){ + return $this->biomeColors; + } + } \ No newline at end of file