Removed the need for subchunks to know their Y coordinates

This commit is contained in:
Dylan K. Taylor 2017-01-01 12:57:09 +00:00
parent e85d6d134e
commit 69061ba4ad
8 changed files with 29 additions and 80 deletions

View File

@ -914,9 +914,8 @@ class Level implements ChunkManager, Metadatable{
}
foreach($chunk->getSubChunks() as $subChunk){
foreach($chunk->getSubChunks() as $Y => $subChunk){
if(!$subChunk->isEmpty()){
$Y = $subChunk->getY();
$k = mt_rand(0, 0x7fffffff);
for($i = 0; $i < 3; ++$i, $k >>= 10){
$x = $k & 0x0f;

View File

@ -76,7 +76,7 @@ interface Chunk{
* @param int $x 0-15
* @param int $y 0-255
* @param int $z 0-15
* @param int $blockId , if null, do not change
* @param int $blockId 0-255, if null, do not change
* @param int $meta 0-15, if null, do not change
*
* @return bool
@ -301,16 +301,8 @@ interface Chunk{
*/
public function getHeightMapArray() : array;
public function getBlockIdArray() : string;
public function getBlockDataArray() : string;
public function getBlockExtraDataArray() : array;
public function getBlockSkyLightArray() : string;
public function getBlockLightArray() : string;
/**
* @return bool
*/

View File

@ -26,10 +26,9 @@ namespace pocketmine\level\format\generic;
use pocketmine\utils\ChunkException;
class EmptySubChunk extends SubChunk{
protected $y;
public function __construct(int $y){
$this->y = $y;
public function __construct(){
}
public function isEmpty() : bool{
@ -109,7 +108,7 @@ class EmptySubChunk extends SubChunk{
}
public function networkSerialize() : string{
return "\x00" . str_repeat("\x00", 10240);
return str_repeat("\x00", 10240);
}
public function fastSerialize() : string{

View File

@ -97,13 +97,12 @@ class GenericChunk implements Chunk{
$this->height = $provider !== null ? ($provider->getWorldHeight() >> 4) : 16;
foreach($subChunks as $subChunk){
$y = $subChunk->getY();
foreach($subChunks as $y => $subChunk){
if($y < 0 or $y >= $this->height){
throw new ChunkException("Invalid subchunk index $y!");
}
if($subChunk->isEmpty()){
$this->subChunks[$y] = new EmptySubChunk($y);
$this->subChunks[$y] = new EmptySubChunk(); //TODO: point to a single object instead of creating many for each chunk
}else{
$this->subChunks[$y] = $subChunk;
}
@ -111,7 +110,7 @@ class GenericChunk implements Chunk{
for($i = 0; $i < $this->height; ++$i){
if(!isset($this->subChunks[$i])){
$this->subChunks[$i] = new EmptySubChunk($i);
$this->subChunks[$i] = new EmptySubChunk(); //TODO: todo above
}
}
@ -511,42 +510,10 @@ class GenericChunk implements Chunk{
return $this->heightMap;
}
public function getBlockIdArray() : string{
$result = "";
foreach($this->subChunks as $subChunk){
$result .= $subChunk->getBlockIdArray();
}
return $result;
}
public function getBlockDataArray() : string{
$result = "";
foreach($this->subChunks as $subChunk){
$result .= $subChunk->getBlockDataArray();
}
return $result;
}
public function getBlockExtraDataArray() : array{
return $this->extraData;
}
public function getBlockSkyLightArray() : string{
$result = "";
foreach($this->subChunks as $subChunk){
$result .= $subChunk->getSkyLightArray();
}
return $result;
}
public function getBlockLightArray() : string{
$result = "";
foreach($this->subChunks as $subChunk){
$result .= $subChunk->getBlockLightArray();
}
return $result;
}
public function hasChanged() : bool{
return $this->hasChanged;
}
@ -555,13 +522,13 @@ class GenericChunk implements Chunk{
$this->hasChanged = $value;
}
public function getSubChunk(int $fY, bool $generateNew = false) : SubChunk{
if($fY < 0 or $fY >= $this->height){
return new EmptySubChunk($fY);
}elseif($generateNew and $this->subChunks[$fY] instanceof EmptySubChunk){
$this->subChunks[$fY] = new SubChunk($fY);
public function getSubChunk(int $y, bool $generateNew = false) : SubChunk{
if($y < 0 or $y >= $this->height){
return new EmptySubChunk();
}elseif($generateNew and $this->subChunks[$y] instanceof EmptySubChunk){
$this->subChunks[$y] = new SubChunk();
}
return $this->subChunks[$fY];
return $this->subChunks[$y];
}
public function setSubChunk(int $fY, SubChunk $subChunk = null, bool $allowEmpty = false) : bool{
@ -654,12 +621,12 @@ class GenericChunk implements Chunk{
$stream->putInt($chunk->z);
$count = 0;
$subChunks = "";
foreach($chunk->subChunks as $subChunk){
foreach($chunk->subChunks as $y => $subChunk){
if($subChunk->isEmpty()){
continue;
}
++$count;
$subChunks .= $subChunk->fastSerialize();
$subChunks .= chr($y) . $subChunk->fastSerialize();
}
$stream->putByte($count);
$stream->put($subChunks);
@ -679,8 +646,7 @@ class GenericChunk implements Chunk{
$subChunks = [];
$count = $stream->getByte();
for($y = 0; $y < $count; ++$y){
$subChunks[] = new SubChunk(
$stream->getByte(), //y
$subChunks[$stream->getByte()] = new SubChunk(
$stream->get(4096), //blockIds
$stream->get(2048), //blockData
$stream->get(2048), //skyLight

View File

@ -24,7 +24,6 @@ declare(strict_types = 1);
namespace pocketmine\level\format\generic;
class SubChunk{
protected $y;
protected $ids;
protected $data;
@ -40,18 +39,13 @@ class SubChunk{
}
}
public function __construct(int $y, string $ids = "", string $data = "", string $blockLight = "", string $skyLight = ""){
$this->y = $y;
public function __construct(string $ids = "", string $data = "", string $blockLight = "", string $skyLight = ""){
self::assignData($this->ids, $ids, 4096);
self::assignData($this->data, $data, 2048);
self::assignData($this->blockLight, $blockLight, 2048);
self::assignData($this->skyLight, $skyLight, 2048);
}
public function getY() : int{
return $this->y;
}
public function isEmpty() : bool{
assert(strlen($this->ids) === 4096, "Wrong length of ID array, expecting 4096 bytes, got " . strlen($this->ids));
return substr_count($this->ids, "\x00") === 4096;
@ -213,7 +207,7 @@ class SubChunk{
}
public function fastSerialize() : string{
// y, ids, data, skylight, blocklight
return chr($this->y) . $this->ids . $this->data . $this->skyLight . $this->blockLight;
// ids, data, skylight, blocklight
return $this->ids . $this->data . $this->skyLight . $this->blockLight;
}
}

View File

@ -53,12 +53,12 @@ class Anvil extends McRegion{
$nbt->Sections = new ListTag("Sections", []);
$nbt->Sections->setTagType(NBT::TAG_Compound);
$subChunks = -1;
foreach($chunk->getSubChunks() as $subChunk){
foreach($chunk->getSubChunks() as $y => $subChunk){
if($subChunk->isEmpty()){
continue;
}
$nbt->Sections[++$subChunks] = new CompoundTag(null, [
"Y" => new ByteTag("Y", $subChunk->getY()),
"Y" => new ByteTag("Y", $y),
"Blocks" => new ByteArrayTag("Blocks", GenericChunk::reorderByteArray($subChunk->getBlockIdArray())), //Generic in-memory chunks are currrently always XZY
"Data" => new ByteArrayTag("Data", GenericChunk::reorderNibbleArray($subChunk->getBlockDataArray())),
"BlockLight" => new ByteArrayTag("BlockLight", GenericChunk::reorderNibbleArray($subChunk->getBlockLightArray())),
@ -116,8 +116,7 @@ class Anvil extends McRegion{
if($chunk->Sections instanceof ListTag){
foreach($chunk->Sections as $subChunk){
if($subChunk instanceof CompoundTag){
$subChunks[] = new SubChunk(
$subChunk->Y->getValue(),
$subChunks[$subChunk->Y->getValue()] = new SubChunk(
GenericChunk::reorderByteArray($subChunk->Blocks->getValue()),
GenericChunk::reorderNibbleArray($subChunk->Data->getValue()),
GenericChunk::reorderNibbleArray($subChunk->BlockLight->getValue()),

View File

@ -66,10 +66,11 @@ class McRegion extends BaseLevelProvider{
$data = "";
$blockLight = "";
$skyLight = "";
$subChunks = $chunk->getSubChunks();
for($x = 0; $x < 16; ++$x){
for($z = 0; $z < 16; ++$z){
for($y = 0; $y < 8; ++$y){
$subChunk = $chunk->getSubChunk($y);
$subChunk = $subChunks[$y];
$ids .= $subChunk->getBlockIdColumn($x, $z);
$data .= $subChunk->getBlockDataColumn($x, $z);
$blockLight .= $subChunk->getBlockLightColumn($x, $z);
@ -165,7 +166,7 @@ class McRegion extends BaseLevelProvider{
$skyLight .= substr($fullSkyLight, $offset, 8);
$offset += 64;
}
$subChunks[] = new SubChunk($y, $ids, $data, $blockLight, $skyLight);
$subChunks[$y] = new SubChunk($ids, $data, $blockLight, $skyLight);
}
if(isset($chunk->BiomeColors)){

View File

@ -57,12 +57,12 @@ class PMAnvil extends Anvil{
$nbt->Sections = new ListTag("Sections", []);
$nbt->Sections->setTagType(NBT::TAG_Compound);
$subChunks = -1;
foreach($chunk->getSubChunks() as $subChunk){
foreach($chunk->getSubChunks() as $y => $subChunk){
if($subChunk->isEmpty()){
continue;
}
$nbt->Sections[++$subChunks] = new CompoundTag(null, [
"Y" => new ByteTag("Y", $subChunk->getY()),
"Y" => new ByteTag("Y", $y),
"Blocks" => new ByteArrayTag("Blocks", $subChunk->getBlockIdArray()),
"Data" => new ByteArrayTag("Data", $subChunk->getBlockDataArray()),
"BlockLight" => new ByteArrayTag("BlockLight", $subChunk->getBlockLightArray()),
@ -120,8 +120,7 @@ class PMAnvil extends Anvil{
if($chunk->Sections instanceof ListTag){
foreach($chunk->Sections as $subChunk){
if($subChunk instanceof CompoundTag){
$subChunks[] = new SubChunk(
$subChunk->Y->getValue(),
$subChunks[$subChunk->Y->getValue()] = new SubChunk(
$subChunk->Blocks->getValue(),
$subChunk->Data->getValue(),
$subChunk->BlockLight->getValue(),