Tiles now encapsulate positions instead of extending them

This commit is contained in:
Dylan K. Taylor 2019-08-05 19:33:34 +01:00
parent d355d5b5b5
commit 4e5b296c8c
10 changed files with 58 additions and 45 deletions

View File

@ -74,7 +74,7 @@ class EnderChest extends Transparent{
if($player instanceof Player){ if($player instanceof Player){
$enderChest = $this->pos->getWorld()->getTile($this->pos); $enderChest = $this->pos->getWorld()->getTile($this->pos);
if($enderChest instanceof TileEnderChest and $this->getSide(Facing::UP)->isTransparent()){ if($enderChest instanceof TileEnderChest and $this->getSide(Facing::UP)->isTransparent()){
$player->getEnderChestInventory()->setHolderPosition($enderChest); $player->getEnderChestInventory()->setHolderPosition($this->pos);
$player->setCurrentWindow($player->getEnderChestInventory()); $player->setCurrentWindow($player->getEnderChestInventory());
} }
} }

View File

@ -54,9 +54,9 @@ class BrewingStand extends Spawnable implements Container, Nameable{
public function __construct(World $world, Vector3 $pos){ public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos); parent::__construct($world, $pos);
$this->inventory = new BrewingStandInventory($this); $this->inventory = new BrewingStandInventory($this->pos);
$this->inventory->addChangeListeners(CallbackInventoryChangeListener::onAnyChange(function(Inventory $unused){ $this->inventory->addChangeListeners(CallbackInventoryChangeListener::onAnyChange(function(Inventory $unused){
$this->world->scheduleDelayedBlockUpdate($this->getBlock()->getPos(), 1); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, 1);
})); }));
} }

View File

@ -55,7 +55,7 @@ class Chest extends Spawnable implements Container, Nameable{
public function __construct(World $world, Vector3 $pos){ public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos); parent::__construct($world, $pos);
$this->inventory = new ChestInventory($this); $this->inventory = new ChestInventory($this->pos);
} }
public function readSaveData(CompoundTag $nbt) : void{ public function readSaveData(CompoundTag $nbt) : void{
@ -63,8 +63,8 @@ class Chest extends Spawnable implements Container, Nameable{
$pairX = $nbt->getInt(self::TAG_PAIRX); $pairX = $nbt->getInt(self::TAG_PAIRX);
$pairZ = $nbt->getInt(self::TAG_PAIRZ); $pairZ = $nbt->getInt(self::TAG_PAIRZ);
if( if(
($this->x === $pairX and abs($this->z - $pairZ) === 1) or ($this->pos->x === $pairX and abs($this->pos->z - $pairZ) === 1) or
($this->z === $pairZ and abs($this->x - $pairX) === 1) ($this->pos->z === $pairZ and abs($this->pos->x - $pairX) === 1)
){ ){
$this->pairX = $pairX; $this->pairX = $pairX;
$this->pairZ = $pairZ; $this->pairZ = $pairZ;
@ -99,7 +99,7 @@ class Chest extends Spawnable implements Container, Nameable{
$this->inventory->removeAllViewers(); $this->inventory->removeAllViewers();
if($this->doubleInventory !== null){ if($this->doubleInventory !== null){
if($this->isPaired() and $this->world->isChunkLoaded($this->pairX >> 4, $this->pairZ >> 4)){ if($this->isPaired() and $this->pos->getWorld()->isChunkLoaded($this->pairX >> 4, $this->pairZ >> 4)){
$this->doubleInventory->removeAllViewers(); $this->doubleInventory->removeAllViewers();
if(($pair = $this->getPair()) !== null){ if(($pair = $this->getPair()) !== null){
$pair->doubleInventory = null; $pair->doubleInventory = null;
@ -137,7 +137,7 @@ class Chest extends Spawnable implements Container, Nameable{
} }
protected function checkPairing(){ protected function checkPairing(){
if($this->isPaired() and !$this->getWorld()->isInLoadedTerrain(new Vector3($this->pairX, $this->y, $this->pairZ))){ if($this->isPaired() and !$this->pos->getWorld()->isInLoadedTerrain(new Vector3($this->pairX, $this->pos->y, $this->pairZ))){
//paired to a tile in an unloaded chunk //paired to a tile in an unloaded chunk
$this->doubleInventory = null; $this->doubleInventory = null;
@ -150,7 +150,7 @@ class Chest extends Spawnable implements Container, Nameable{
if($pair->doubleInventory !== null){ if($pair->doubleInventory !== null){
$this->doubleInventory = $pair->doubleInventory; $this->doubleInventory = $pair->doubleInventory;
}else{ }else{
if(($pair->x + ($pair->z << 15)) > ($this->x + ($this->z << 15))){ //Order them correctly if(($pair->getPos()->x + ($pair->getPos()->z << 15)) > ($this->pos->x + ($this->pos->z << 15))){ //Order them correctly
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($pair->inventory, $this->inventory); $this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($pair->inventory, $this->inventory);
}else{ }else{
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($this->inventory, $pair->inventory); $this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($this->inventory, $pair->inventory);
@ -179,7 +179,7 @@ class Chest extends Spawnable implements Container, Nameable{
*/ */
public function getPair() : ?Chest{ public function getPair() : ?Chest{
if($this->isPaired()){ if($this->isPaired()){
$tile = $this->getWorld()->getTileAt($this->pairX, $this->y, $this->pairZ); $tile = $this->pos->getWorld()->getTileAt($this->pairX, $this->pos->y, $this->pairZ);
if($tile instanceof Chest){ if($tile instanceof Chest){
return $tile; return $tile;
} }
@ -203,11 +203,11 @@ class Chest extends Spawnable implements Container, Nameable{
} }
private function createPair(Chest $tile){ private function createPair(Chest $tile){
$this->pairX = $tile->x; $this->pairX = $tile->getPos()->x;
$this->pairZ = $tile->z; $this->pairZ = $tile->getPos()->z;
$tile->pairX = $this->x; $tile->pairX = $this->getPos()->x;
$tile->pairZ = $this->z; $tile->pairZ = $this->getPos()->z;
} }
public function unpair(){ public function unpair(){

View File

@ -91,14 +91,14 @@ trait ContainerTrait{
* @see Position::asPosition() * @see Position::asPosition()
* @return Position * @return Position
*/ */
abstract protected function asPosition() : Position; abstract protected function getPos() : Position;
/** /**
* @see Tile::onBlockDestroyedHook() * @see Tile::onBlockDestroyedHook()
*/ */
protected function onBlockDestroyedHook() : void{ protected function onBlockDestroyedHook() : void{
$inv = $this->getRealInventory(); $inv = $this->getRealInventory();
$pos = $this->asPosition(); $pos = $this->getPos();
foreach($inv->getContents() as $k => $item){ foreach($inv->getContents() as $k => $item){
$pos->world->dropItem($pos->add(0.5, 0.5, 0.5), $item); $pos->world->dropItem($pos->add(0.5, 0.5, 0.5), $item);

View File

@ -57,10 +57,10 @@ class Furnace extends Spawnable implements Container, Nameable{
public function __construct(World $world, Vector3 $pos){ public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos); parent::__construct($world, $pos);
$this->inventory = new FurnaceInventory($this); $this->inventory = new FurnaceInventory($this->pos);
$this->inventory->addChangeListeners(CallbackInventoryChangeListener::onAnyChange( $this->inventory->addChangeListeners(CallbackInventoryChangeListener::onAnyChange(
function(Inventory $unused) : void{ function(Inventory $unused) : void{
$this->world->scheduleDelayedBlockUpdate($this->asVector3(), 1); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, 1);
}) })
); );
} }
@ -132,7 +132,7 @@ class Furnace extends Spawnable implements Container, Nameable{
$block = $this->getBlock(); $block = $this->getBlock();
if($block instanceof BlockFurnace and !$block->isLit()){ if($block instanceof BlockFurnace and !$block->isLit()){
$block->setLit(true); $block->setLit(true);
$this->getWorld()->setBlock($block->getPos(), $block); $this->pos->getWorld()->setBlock($block->getPos(), $block);
} }
if($this->remainingFuelTime > 0 and $ev->isBurning()){ if($this->remainingFuelTime > 0 and $ev->isBurning()){
@ -158,7 +158,7 @@ class Furnace extends Spawnable implements Container, Nameable{
$fuel = $this->inventory->getFuel(); $fuel = $this->inventory->getFuel();
$raw = $this->inventory->getSmelting(); $raw = $this->inventory->getSmelting();
$product = $this->inventory->getResult(); $product = $this->inventory->getResult();
$smelt = $this->world->getServer()->getCraftingManager()->matchFurnaceRecipe($raw); $smelt = $this->pos->getWorld()->getServer()->getCraftingManager()->matchFurnaceRecipe($raw);
$canSmelt = ($smelt instanceof FurnaceRecipe and $raw->getCount() > 0 and (($smelt->getResult()->equals($product) and $product->getCount() < $product->getMaxStackSize()) or $product->isNull())); $canSmelt = ($smelt instanceof FurnaceRecipe and $raw->getCount() > 0 and (($smelt->getResult()->equals($product) and $product->getCount() < $product->getMaxStackSize()) or $product->isNull()));
if($this->remainingFuelTime <= 0 and $canSmelt and $fuel->getFuelTime() > 0 and $fuel->getCount() > 0){ if($this->remainingFuelTime <= 0 and $canSmelt and $fuel->getFuelTime() > 0 and $fuel->getCount() > 0){
@ -195,7 +195,7 @@ class Furnace extends Spawnable implements Container, Nameable{
$block = $this->getBlock(); $block = $this->getBlock();
if($block instanceof BlockFurnace and $block->isLit()){ if($block instanceof BlockFurnace and $block->isLit()){
$block->setLit(false); $block->setLit(false);
$this->getWorld()->setBlock($block->getPos(), $block); $this->pos->getWorld()->setBlock($block->getPos(), $block);
} }
$this->remainingFuelTime = $this->cookTime = $this->maxFuelTime = 0; $this->remainingFuelTime = $this->cookTime = $this->maxFuelTime = 0;
} }

View File

@ -43,7 +43,7 @@ class Hopper extends Spawnable implements Container, Nameable{
public function __construct(World $world, Vector3 $pos){ public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos); parent::__construct($world, $pos);
$this->inventory = new HopperInventory($this); $this->inventory = new HopperInventory($this->pos);
} }
public function readSaveData(CompoundTag $nbt) : void{ public function readSaveData(CompoundTag $nbt) : void{

View File

@ -80,9 +80,9 @@ abstract class Spawnable extends Tile{
final public function getSpawnCompound() : CompoundTag{ final public function getSpawnCompound() : CompoundTag{
$nbt = CompoundTag::create() $nbt = CompoundTag::create()
->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this))) //TODO: disassociate network ID from save ID ->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this))) //TODO: disassociate network ID from save ID
->setInt(self::TAG_X, $this->x) ->setInt(self::TAG_X, $this->pos->x)
->setInt(self::TAG_Y, $this->y) ->setInt(self::TAG_Y, $this->pos->y)
->setInt(self::TAG_Z, $this->z); ->setInt(self::TAG_Z, $this->pos->z);
$this->addAdditionalSpawnData($nbt); $this->addAdditionalSpawnData($nbt);
return $nbt; return $nbt;
} }

View File

@ -37,20 +37,22 @@ use pocketmine\world\Position;
use pocketmine\world\World; use pocketmine\world\World;
use function get_class; use function get_class;
abstract class Tile extends Position{ abstract class Tile{
public const TAG_ID = "id"; public const TAG_ID = "id";
public const TAG_X = "x"; public const TAG_X = "x";
public const TAG_Y = "y"; public const TAG_Y = "y";
public const TAG_Z = "z"; public const TAG_Z = "z";
/** @var Position */
protected $pos;
/** @var bool */ /** @var bool */
public $closed = false; public $closed = false;
/** @var TimingsHandler */ /** @var TimingsHandler */
protected $timings; protected $timings;
public function __construct(World $world, Vector3 $pos){ public function __construct(World $world, Vector3 $pos){
parent::__construct($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ(), $world); $this->pos = Position::fromObject($pos, $world);
$this->timings = Timings::getTileEntityTimings($this); $this->timings = Timings::getTileEntityTimings($this);
} }
@ -72,9 +74,9 @@ abstract class Tile extends Position{
public function saveNBT() : CompoundTag{ public function saveNBT() : CompoundTag{
$nbt = CompoundTag::create() $nbt = CompoundTag::create()
->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this))) ->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this)))
->setInt(self::TAG_X, $this->x) ->setInt(self::TAG_X, $this->pos->getFloorX())
->setInt(self::TAG_Y, $this->y) ->setInt(self::TAG_Y, $this->pos->getFloorY())
->setInt(self::TAG_Z, $this->z); ->setInt(self::TAG_Z, $this->pos->getFloorZ());
$this->writeSaveData($nbt); $this->writeSaveData($nbt);
return $nbt; return $nbt;
@ -102,7 +104,14 @@ abstract class Tile extends Position{
* @return Block * @return Block
*/ */
public function getBlock() : Block{ public function getBlock() : Block{
return $this->world->getBlockAt($this->x, $this->y, $this->z); return $this->pos->getWorld()->getBlock($this->pos);
}
/**
* @return Position
*/
public function getPos() : Position{
return $this->pos;
} }
public function isClosed() : bool{ public function isClosed() : bool{
@ -132,9 +141,9 @@ abstract class Tile extends Position{
if(!$this->closed){ if(!$this->closed){
$this->closed = true; $this->closed = true;
if($this->isValid()){ if($this->pos->isValid()){
$this->world->removeTile($this); $this->pos->getWorld()->removeTile($this);
$this->setWorld(null); $this->pos->setWorld(null);
} }
} }
} }

View File

@ -901,7 +901,7 @@ class World implements ChunkManager{
$tile = $this->getTileAt($b->x, $b->y, $b->z); $tile = $this->getTileAt($b->x, $b->y, $b->z);
if($tile instanceof Spawnable){ if($tile instanceof Spawnable){
$packets[] = BlockActorDataPacket::create($tile->x, $tile->y, $tile->z, $tile->getSerializedSpawnCompound()); $packets[] = BlockActorDataPacket::create($b->x, $b->y, $b->z, $tile->getSerializedSpawnCompound());
} }
} }
@ -2348,12 +2348,13 @@ class World implements ChunkManager{
if($tile->isClosed()){ if($tile->isClosed()){
throw new \InvalidArgumentException("Attempted to add a garbage closed Tile to world"); throw new \InvalidArgumentException("Attempted to add a garbage closed Tile to world");
} }
if($tile->getWorld() !== $this){ $pos = $tile->getPos();
if($pos->getWorld() !== $this){
throw new \InvalidArgumentException("Invalid Tile world"); throw new \InvalidArgumentException("Invalid Tile world");
} }
$chunkX = $tile->getFloorX() >> 4; $chunkX = $pos->getFloorX() >> 4;
$chunkZ = $tile->getFloorZ() >> 4; $chunkZ = $pos->getFloorZ() >> 4;
if(isset($this->chunks[$hash = World::chunkHash($chunkX, $chunkZ)])){ if(isset($this->chunks[$hash = World::chunkHash($chunkX, $chunkZ)])){
$this->chunks[$hash]->addTile($tile); $this->chunks[$hash]->addTile($tile);
@ -2362,7 +2363,7 @@ class World implements ChunkManager{
} }
//delegate tile ticking to the corresponding block //delegate tile ticking to the corresponding block
$this->scheduleDelayedBlockUpdate($tile->asVector3(), 1); $this->scheduleDelayedBlockUpdate($pos->asVector3(), 1);
} }
/** /**
@ -2371,18 +2372,19 @@ class World implements ChunkManager{
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function removeTile(Tile $tile){ public function removeTile(Tile $tile){
if($tile->getWorld() !== $this){ $pos = $tile->getPos();
if($pos->getWorld() !== $this){
throw new \InvalidArgumentException("Invalid Tile world"); throw new \InvalidArgumentException("Invalid Tile world");
} }
$chunkX = $tile->getFloorX() >> 4; $chunkX = $pos->getFloorX() >> 4;
$chunkZ = $tile->getFloorZ() >> 4; $chunkZ = $pos->getFloorZ() >> 4;
if(isset($this->chunks[$hash = World::chunkHash($chunkX, $chunkZ)])){ if(isset($this->chunks[$hash = World::chunkHash($chunkX, $chunkZ)])){
$this->chunks[$hash]->removeTile($tile); $this->chunks[$hash]->removeTile($tile);
} }
foreach($this->getChunkListeners($chunkX, $chunkZ) as $listener){ foreach($this->getChunkListeners($chunkX, $chunkZ) as $listener){
$listener->onBlockChanged($tile); $listener->onBlockChanged($pos->asVector3());
} }
} }

View File

@ -473,7 +473,8 @@ class Chunk{
throw new \InvalidArgumentException("Attempted to add a garbage closed Tile to a chunk"); throw new \InvalidArgumentException("Attempted to add a garbage closed Tile to a chunk");
} }
if(isset($this->tiles[$index = Chunk::blockHash($tile->x, $tile->y, $tile->z)]) and $this->tiles[$index] !== $tile){ $pos = $tile->getPos();
if(isset($this->tiles[$index = Chunk::blockHash($pos->x, $pos->y, $pos->z)]) and $this->tiles[$index] !== $tile){
$this->tiles[$index]->close(); $this->tiles[$index]->close();
} }
$this->tiles[$index] = $tile; $this->tiles[$index] = $tile;
@ -484,7 +485,8 @@ class Chunk{
* @param Tile $tile * @param Tile $tile
*/ */
public function removeTile(Tile $tile) : void{ public function removeTile(Tile $tile) : void{
unset($this->tiles[Chunk::blockHash($tile->x, $tile->y, $tile->z)]); $pos = $tile->getPos();
unset($this->tiles[Chunk::blockHash($pos->x, $pos->y, $pos->z)]);
$this->hasChanged = true; $this->hasChanged = true;
} }