Remove ability to set blockID and blockdata independently

This was the cause of many inconsistency and broken world bugs. In the future (once we switch to paletted chunks) this won't be possible anyway. For now, some temporary API is provided to allow modifying chunkdata directly, but it is required that **both** must be provided.
This commit is contained in:
Dylan K. Taylor 2018-11-22 16:53:22 +00:00
parent 507d47a6f5
commit 98efd27543
16 changed files with 43 additions and 200 deletions

View File

@ -37,16 +37,6 @@ interface ChunkManager{
*/
public function getBlockIdAt(int $x, int $y, int $z) : int;
/**
* Sets the raw block id.
*
* @param int $x
* @param int $y
* @param int $z
* @param int $id 0-255
*/
public function setBlockIdAt(int $x, int $y, int $z, int $id);
/**
* Gets the raw block metadata
*
@ -58,15 +48,7 @@ interface ChunkManager{
*/
public function getBlockDataAt(int $x, int $y, int $z) : int;
/**
* Sets the raw block metadata.
*
* @param int $x
* @param int $y
* @param int $z
* @param int $data 0-15
*/
public function setBlockDataAt(int $x, int $y, int $z, int $data);
public function setBlockIdAndDataAt(int $x, int $y, int $z, int $id, int $data) : void;
/**
* Returns the raw block light level

View File

@ -212,8 +212,7 @@ class Explosion{
}
}
$this->level->setBlockIdAt($block->x, $block->y, $block->z, 0);
$this->level->setBlockDataAt($block->x, $block->y, $block->z, 0);
$this->level->setBlockIdAndDataAt($block->x, $block->y, $block->z, 0, 0);
$t = $this->level->getTileAt($block->x, $block->y, $block->z);
if($t instanceof Tile){

View File

@ -2098,27 +2098,6 @@ class Level implements ChunkManager, Metadatable{
return $this->getChunk($x >> 4, $z >> 4, true)->getBlockId($x & 0x0f, $y, $z & 0x0f);
}
/**
* Sets the raw block id.
*
* @param int $x
* @param int $y
* @param int $z
* @param int $id 0-255
*/
public function setBlockIdAt(int $x, int $y, int $z, int $id){
unset($this->blockCache[$chunkHash = Level::chunkHash($x >> 4, $z >> 4)][$blockHash = Level::blockHash($x, $y, $z)]);
$this->getChunk($x >> 4, $z >> 4, true)->setBlockId($x & 0x0f, $y, $z & 0x0f, $id & 0xff);
if(!isset($this->changedBlocks[$chunkHash])){
$this->changedBlocks[$chunkHash] = [];
}
$this->changedBlocks[$chunkHash][$blockHash] = $v = new Vector3($x, $y, $z);
foreach($this->getChunkLoaders($x >> 4, $z >> 4) as $loader){
$loader->onBlockChanged($v);
}
}
/**
* Gets the raw block metadata
*
@ -2132,18 +2111,10 @@ class Level implements ChunkManager, Metadatable{
return $this->getChunk($x >> 4, $z >> 4, true)->getBlockData($x & 0x0f, $y, $z & 0x0f);
}
/**
* Sets the raw block metadata.
*
* @param int $x
* @param int $y
* @param int $z
* @param int $data 0-15
*/
public function setBlockDataAt(int $x, int $y, int $z, int $data){
public function setBlockIdAndDataAt(int $x, int $y, int $z, int $id, int $data) : void{
unset($this->blockCache[$chunkHash = Level::chunkHash($x >> 4, $z >> 4)][$blockHash = Level::blockHash($x, $y, $z)]);
$this->getChunk($x >> 4, $z >> 4, true)->setBlockData($x & 0x0f, $y, $z & 0x0f, $data & 0x0f);
$this->getChunk($x >> 4, $z >> 4, true)->setBlock($x & 0x0f, $y, $z & 0x0f, $id, $data);
if(!isset($this->changedBlocks[$chunkHash])){
$this->changedBlocks[$chunkHash] = [];

View File

@ -57,20 +57,6 @@ class SimpleChunkManager implements ChunkManager{
return 0;
}
/**
* Sets the raw block id.
*
* @param int $x
* @param int $y
* @param int $z
* @param int $id 0-255
*/
public function setBlockIdAt(int $x, int $y, int $z, int $id){
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
$chunk->setBlockId($x & 0xf, $y, $z & 0xf, $id);
}
}
/**
* Gets the raw block metadata
*
@ -87,17 +73,9 @@ class SimpleChunkManager implements ChunkManager{
return 0;
}
/**
* Sets the raw block metadata.
*
* @param int $x
* @param int $y
* @param int $z
* @param int $data 0-15
*/
public function setBlockDataAt(int $x, int $y, int $z, int $data){
if($chunk = $this->getChunk($x >> 4, $z >> 4)){
$chunk->setBlockData($x & 0xf, $y, $z & 0xf, $data);
public function setBlockIdAndDataAt(int $x, int $y, int $z, int $id, int $data) : void{
if(($chunk = $this->getChunk($x >> 4, $z >> 4)) !== null){
$chunk->setBlock($x & 0xf, $y & 0xf, $z & 0xf, $id, $data);
}
}

View File

@ -184,8 +184,8 @@ class Chunk{
*
* @return bool
*/
public function setBlock(int $x, int $y, int $z, ?int $blockId = null, ?int $meta = null) : bool{
if($this->getSubChunk($y >> 4, true)->setBlock($x, $y & 0x0f, $z, $blockId !== null ? ($blockId & 0xff) : null, $meta !== null ? ($meta & 0x0f) : null)){
public function setBlock(int $x, int $y, int $z, int $blockId, int $meta) : bool{
if($this->getSubChunk($y >> 4, true)->setBlock($x, $y & 0x0f, $z, $blockId & 0xff, $meta & 0x0f)){
$this->hasChanged = true;
return true;
}
@ -205,20 +205,6 @@ class Chunk{
return $this->getSubChunk($y >> 4)->getBlockId($x, $y & 0x0f, $z);
}
/**
* Sets the block ID at the specified chunk block coordinates
*
* @param int $x 0-15
* @param int $y
* @param int $z 0-15
* @param int $id 0-255
*/
public function setBlockId(int $x, int $y, int $z, int $id){
if($this->getSubChunk($y >> 4, true)->setBlockId($x, $y & 0x0f, $z, $id)){
$this->hasChanged = true;
}
}
/**
* Returns the block meta value at the specified chunk block coordinates
*
@ -232,20 +218,6 @@ class Chunk{
return $this->getSubChunk($y >> 4)->getBlockData($x, $y & 0x0f, $z);
}
/**
* Sets the block meta value at the specified chunk block coordinates
*
* @param int $x 0-15
* @param int $y
* @param int $z 0-15
* @param int $data 0-15
*/
public function setBlockData(int $x, int $y, int $z, int $data){
if($this->getSubChunk($y >> 4, true)->setBlockData($x, $y & 0x0f, $z, $data)){
$this->hasChanged = true;
}
}
/**
* Returns the sky light level at the specified chunk block coordinates
*

View File

@ -43,23 +43,15 @@ class EmptySubChunk implements SubChunkInterface{
return 0;
}
public function setBlockId(int $x, int $y, int $z, int $id) : bool{
return false;
}
public function getBlockData(int $x, int $y, int $z) : int{
return 0;
}
public function setBlockData(int $x, int $y, int $z, int $data) : bool{
return false;
}
public function getFullBlock(int $x, int $y, int $z) : int{
return 0;
}
public function setBlock(int $x, int $y, int $z, ?int $id = null, ?int $data = null) : bool{
public function setBlock(int $x, int $y, int $z, int $id, int $data) : bool{
return false;
}

View File

@ -64,43 +64,24 @@ class SubChunk implements SubChunkInterface{
return ord($this->ids{($x << 8) | ($z << 4) | $y});
}
public function setBlockId(int $x, int $y, int $z, int $id) : bool{
$this->ids{($x << 8) | ($z << 4) | $y} = chr($id);
return true;
}
public function getBlockData(int $x, int $y, int $z) : int{
return (ord($this->data{($x << 7) | ($z << 3) | ($y >> 1)}) >> (($y & 1) << 2)) & 0xf;
}
public function setBlockData(int $x, int $y, int $z, int $data) : bool{
$i = ($x << 7) | ($z << 3) | ($y >> 1);
$shift = ($y & 1) << 2;
$byte = ord($this->data{$i});
$this->data{$i} = chr(($byte & ~(0xf << $shift)) | (($data & 0xf) << $shift));
return true;
}
public function getFullBlock(int $x, int $y, int $z) : int{
$i = ($x << 8) | ($z << 4) | $y;
return (ord($this->ids{$i}) << 4) | ((ord($this->data{$i >> 1}) >> (($y & 1) << 2)) & 0xf);
}
public function setBlock(int $x, int $y, int $z, ?int $id = null, ?int $data = null) : bool{
public function setBlock(int $x, int $y, int $z, int $id, int $data) : bool{
$i = ($x << 8) | ($z << 4) | $y;
$changed = false;
if($id !== null){
$block = chr($id);
if($this->ids{$i} !== $block){
$this->ids{$i} = $block;
$changed = true;
}
}
if($data !== null){
$i >>= 1;
$shift = ($y & 1) << 2;
$oldPair = ord($this->data{$i});
@ -109,7 +90,6 @@ class SubChunk implements SubChunkInterface{
$this->data{$i} = chr($newPair);
$changed = true;
}
}
return $changed;
}

View File

@ -41,16 +41,6 @@ interface SubChunkInterface{
*/
public function getBlockId(int $x, int $y, int $z) : int;
/**
* @param int $x
* @param int $y
* @param int $z
* @param int $id
*
* @return bool
*/
public function setBlockId(int $x, int $y, int $z, int $id) : bool;
/**
* @param int $x
* @param int $y
@ -60,16 +50,6 @@ interface SubChunkInterface{
*/
public function getBlockData(int $x, int $y, int $z) : int;
/**
* @param int $x
* @param int $y
* @param int $z
* @param int $data
*
* @return bool
*/
public function setBlockData(int $x, int $y, int $z, int $data) : bool;
/**
* @param int $x
* @param int $y
@ -83,12 +63,12 @@ interface SubChunkInterface{
* @param int $x
* @param int $y
* @param int $z
* @param int|null $id
* @param int|null $data
* @param int $id
* @param int $data
*
* @return bool
*/
public function setBlock(int $x, int $y, int $z, ?int $id = null, ?int $data = null) : bool;
public function setBlock(int $x, int $y, int $z, int $id, int $data) : bool;
/**
* @param int $x

View File

@ -88,16 +88,16 @@ class Nether extends Generator{
for($y = 0; $y < 128; ++$y){
if($y === 0 or $y === 127){
$chunk->setBlockId($x, $y, $z, Block::BEDROCK);
$chunk->setBlock($x, $y, $z, Block::BEDROCK, 0);
continue;
}
$noiseValue = (abs($this->emptyHeight - $y) / $this->emptyHeight) * $this->emptyAmplitude - $noise[$x][$z][$y];
$noiseValue -= 1 - $this->density;
if($noiseValue > 0){
$chunk->setBlockId($x, $y, $z, Block::NETHERRACK);
$chunk->setBlock($x, $y, $z, Block::NETHERRACK, 0);
}elseif($y <= $this->waterHeight){
$chunk->setBlockId($x, $y, $z, Block::STILL_LAVA);
$chunk->setBlock($x, $y, $z, Block::STILL_LAVA, 0);
}
}
}

View File

@ -208,15 +208,15 @@ class Normal extends Generator{
for($y = 0; $y < 128; ++$y){
if($y === 0){
$chunk->setBlockId($x, $y, $z, Block::BEDROCK);
$chunk->setBlock($x, $y, $z, Block::BEDROCK, 0);
continue;
}
$noiseValue = $noise[$x][$z][$y] - 1 / $smoothHeight * ($y - $smoothHeight - $minSum);
if($noiseValue > 0){
$chunk->setBlockId($x, $y, $z, Block::STONE);
$chunk->setBlock($x, $y, $z, Block::STONE, 0);
}elseif($y <= $this->waterHeight){
$chunk->setBlockId($x, $y, $z, Block::STILL_WATER);
$chunk->setBlock($x, $y, $z, Block::STILL_WATER, 0);
}
}
}

View File

@ -85,10 +85,7 @@ class Ore{
$sizeZ *= $sizeZ;
if(($sizeX + $sizeY + $sizeZ) < 1 and $level->getBlockIdAt($x, $y, $z) === Block::STONE){
$level->setBlockIdAt($x, $y, $z, $this->type->material->getId());
if($this->type->material->getDamage() !== 0){
$level->setBlockDataAt($x, $y, $z, $this->type->material->getDamage());
}
$level->setBlockIdAndDataAt($x, $y, $z, $this->type->material->getId(), $this->type->material->getDamage());
}
}
}

View File

@ -59,8 +59,7 @@ class SpruceTree extends Tree{
}
if(!BlockFactory::get($level->getBlockIdAt($xx, $yyy, $zz))->isSolid()){
$level->setBlockIdAt($xx, $yyy, $zz, $this->leafBlock);
$level->setBlockDataAt($xx, $yyy, $zz, $this->blockMeta);
$level->setBlockIdAndDataAt($xx, $yyy, $zz, $this->leafBlock, $this->blockMeta);
}
}
}

View File

@ -45,8 +45,7 @@ class TallGrass{
$z = $random->nextRange($pos->z - $radius, $pos->z + $radius);
if($level->getBlockIdAt($x, $pos->y + 1, $z) === Block::AIR and $level->getBlockIdAt($x, $pos->y, $z) === Block::GRASS){
$t = $arr[$random->nextRange(0, $arrC)];
$level->setBlockIdAt($x, $pos->y + 1, $z, $t[0]);
$level->setBlockDataAt($x, $pos->y + 1, $z, $t[1]);
$level->setBlockIdAndDataAt($x, $pos->y + 1, $z, $t[0], $t[1]);
}
}
}

View File

@ -115,8 +115,7 @@ abstract class Tree{
continue;
}
if(!BlockFactory::get($level->getBlockIdAt($xx, $yy, $zz))->isSolid()){
$level->setBlockIdAt($xx, $yy, $zz, $this->leafBlock);
$level->setBlockDataAt($xx, $yy, $zz, $this->blockMeta);
$level->setBlockIdAndDataAt($xx, $yy, $zz, $this->leafBlock, $this->blockMeta);
}
}
}
@ -125,13 +124,12 @@ abstract class Tree{
protected function placeTrunk(ChunkManager $level, int $x, int $y, int $z, Random $random, int $trunkHeight) : void{
// The base dirt block
$level->setBlockIdAt($x, $y - 1, $z, Block::DIRT);
$level->setBlockIdAndDataAt($x, $y - 1, $z, Block::DIRT, 0);
for($yy = 0; $yy < $trunkHeight; ++$yy){
$blockId = $level->getBlockIdAt($x, $y + $yy, $z);
if($this->canOverride(BlockFactory::get($blockId))){
$level->setBlockIdAt($x, $y + $yy, $z, $this->trunkBlock);
$level->setBlockDataAt($x, $y + $yy, $z, $this->blockMeta);
$level->setBlockIdAndDataAt($x, $y + $yy, $z, $this->trunkBlock, $this->blockMeta);
}
}
}

View File

@ -61,14 +61,11 @@ class GroundCover extends Populator{
if($b->canBeFlowedInto() and BlockFactory::get($id) instanceof Liquid){
continue;
}
if($b->getDamage() === 0){
$chunk->setBlockId($x, $y, $z, $b->getId());
}else{
$chunk->setBlock($x, $y, $z, $b->getId(), $b->getDamage());
}
}
}
}
}
}
}

View File

@ -50,8 +50,7 @@ class TallGrass extends Populator{
$y = $this->getHighestWorkableBlock($x, $z);
if($y !== -1 and $this->canTallGrassStay($x, $y, $z)){
$this->level->setBlockIdAt($x, $y, $z, Block::TALL_GRASS);
$this->level->setBlockDataAt($x, $y, $z, 1);
$this->level->setBlockIdAndDataAt($x, $y, $z, Block::TALL_GRASS, 1);
}
}
}