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){
$enderChest = $this->pos->getWorld()->getTile($this->pos);
if($enderChest instanceof TileEnderChest and $this->getSide(Facing::UP)->isTransparent()){
$player->getEnderChestInventory()->setHolderPosition($enderChest);
$player->getEnderChestInventory()->setHolderPosition($this->pos);
$player->setCurrentWindow($player->getEnderChestInventory());
}
}

View File

@ -54,9 +54,9 @@ class BrewingStand extends Spawnable implements Container, Nameable{
public function __construct(World $world, Vector3 $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->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){
parent::__construct($world, $pos);
$this->inventory = new ChestInventory($this);
$this->inventory = new ChestInventory($this->pos);
}
public function readSaveData(CompoundTag $nbt) : void{
@ -63,8 +63,8 @@ class Chest extends Spawnable implements Container, Nameable{
$pairX = $nbt->getInt(self::TAG_PAIRX);
$pairZ = $nbt->getInt(self::TAG_PAIRZ);
if(
($this->x === $pairX and abs($this->z - $pairZ) === 1) or
($this->z === $pairZ and abs($this->x - $pairX) === 1)
($this->pos->x === $pairX and abs($this->pos->z - $pairZ) === 1) or
($this->pos->z === $pairZ and abs($this->pos->x - $pairX) === 1)
){
$this->pairX = $pairX;
$this->pairZ = $pairZ;
@ -99,7 +99,7 @@ class Chest extends Spawnable implements Container, Nameable{
$this->inventory->removeAllViewers();
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();
if(($pair = $this->getPair()) !== null){
$pair->doubleInventory = null;
@ -137,7 +137,7 @@ class Chest extends Spawnable implements Container, Nameable{
}
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
$this->doubleInventory = null;
@ -150,7 +150,7 @@ class Chest extends Spawnable implements Container, Nameable{
if($pair->doubleInventory !== null){
$this->doubleInventory = $pair->doubleInventory;
}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);
}else{
$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{
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){
return $tile;
}
@ -203,11 +203,11 @@ class Chest extends Spawnable implements Container, Nameable{
}
private function createPair(Chest $tile){
$this->pairX = $tile->x;
$this->pairZ = $tile->z;
$this->pairX = $tile->getPos()->x;
$this->pairZ = $tile->getPos()->z;
$tile->pairX = $this->x;
$tile->pairZ = $this->z;
$tile->pairX = $this->getPos()->x;
$tile->pairZ = $this->getPos()->z;
}
public function unpair(){

View File

@ -91,14 +91,14 @@ trait ContainerTrait{
* @see Position::asPosition()
* @return Position
*/
abstract protected function asPosition() : Position;
abstract protected function getPos() : Position;
/**
* @see Tile::onBlockDestroyedHook()
*/
protected function onBlockDestroyedHook() : void{
$inv = $this->getRealInventory();
$pos = $this->asPosition();
$pos = $this->getPos();
foreach($inv->getContents() as $k => $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){
parent::__construct($world, $pos);
$this->inventory = new FurnaceInventory($this);
$this->inventory = new FurnaceInventory($this->pos);
$this->inventory->addChangeListeners(CallbackInventoryChangeListener::onAnyChange(
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();
if($block instanceof BlockFurnace and !$block->isLit()){
$block->setLit(true);
$this->getWorld()->setBlock($block->getPos(), $block);
$this->pos->getWorld()->setBlock($block->getPos(), $block);
}
if($this->remainingFuelTime > 0 and $ev->isBurning()){
@ -158,7 +158,7 @@ class Furnace extends Spawnable implements Container, Nameable{
$fuel = $this->inventory->getFuel();
$raw = $this->inventory->getSmelting();
$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()));
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();
if($block instanceof BlockFurnace and $block->isLit()){
$block->setLit(false);
$this->getWorld()->setBlock($block->getPos(), $block);
$this->pos->getWorld()->setBlock($block->getPos(), $block);
}
$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){
parent::__construct($world, $pos);
$this->inventory = new HopperInventory($this);
$this->inventory = new HopperInventory($this->pos);
}
public function readSaveData(CompoundTag $nbt) : void{

View File

@ -80,9 +80,9 @@ abstract class Spawnable extends Tile{
final public function getSpawnCompound() : CompoundTag{
$nbt = CompoundTag::create()
->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_Y, $this->y)
->setInt(self::TAG_Z, $this->z);
->setInt(self::TAG_X, $this->pos->x)
->setInt(self::TAG_Y, $this->pos->y)
->setInt(self::TAG_Z, $this->pos->z);
$this->addAdditionalSpawnData($nbt);
return $nbt;
}

View File

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

View File

@ -901,7 +901,7 @@ class World implements ChunkManager{
$tile = $this->getTileAt($b->x, $b->y, $b->z);
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()){
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");
}
$chunkX = $tile->getFloorX() >> 4;
$chunkZ = $tile->getFloorZ() >> 4;
$chunkX = $pos->getFloorX() >> 4;
$chunkZ = $pos->getFloorZ() >> 4;
if(isset($this->chunks[$hash = World::chunkHash($chunkX, $chunkZ)])){
$this->chunks[$hash]->addTile($tile);
@ -2362,7 +2363,7 @@ class World implements ChunkManager{
}
//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
*/
public function removeTile(Tile $tile){
if($tile->getWorld() !== $this){
$pos = $tile->getPos();
if($pos->getWorld() !== $this){
throw new \InvalidArgumentException("Invalid Tile world");
}
$chunkX = $tile->getFloorX() >> 4;
$chunkZ = $tile->getFloorZ() >> 4;
$chunkX = $pos->getFloorX() >> 4;
$chunkZ = $pos->getFloorZ() >> 4;
if(isset($this->chunks[$hash = World::chunkHash($chunkX, $chunkZ)])){
$this->chunks[$hash]->removeTile($tile);
}
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");
}
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] = $tile;
@ -484,7 +485,8 @@ class Chunk{
* @param Tile $tile
*/
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;
}