first shot making Block not extend Position

this makes some stuff a lot less pretty, but this seems to be the bare minimum necessary to do this task. It can be enhanced later.
This commit is contained in:
Dylan K. Taylor 2019-08-05 16:44:09 +01:00
parent cf271dab2b
commit 53ab860db5
75 changed files with 337 additions and 325 deletions

View File

@ -63,7 +63,7 @@ class Anvil extends Transparent implements Fallable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$player->setCurrentWindow(new AnvilInventory($this)); $player->setCurrentWindow(new AnvilInventory($this->pos));
} }
return true; return true;

View File

@ -95,7 +95,7 @@ class Banner extends Transparent{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileBanner){ if($tile instanceof TileBanner){
$this->baseColor = $tile->getBaseColor(); $this->baseColor = $tile->getBaseColor();
$this->setPatterns($tile->getPatterns()); $this->setPatterns($tile->getPatterns());
@ -104,7 +104,7 @@ class Banner extends Transparent{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
assert($tile instanceof TileBanner); assert($tile instanceof TileBanner);
$tile->setBaseColor($this->baseColor); $tile->setBaseColor($this->baseColor);
$tile->setPatterns($this->patterns); $tile->setPatterns($this->patterns);
@ -163,7 +163,7 @@ class Banner extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::opposite($this->facing))->getId() === BlockLegacyIds::AIR){ if($this->getSide(Facing::opposite($this->facing))->getId() === BlockLegacyIds::AIR){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -36,6 +36,7 @@ use function array_shift;
use function count; use function count;
use function implode; use function implode;
use function in_array; use function in_array;
use pocketmine\world\Position;
abstract class BaseRail extends Flowable{ abstract class BaseRail extends Flowable{
@ -244,7 +245,7 @@ abstract class BaseRail extends Flowable{
if(isset($otherPossible[$otherSide])){ if(isset($otherPossible[$otherSide])){
$otherConnections[] = $otherSide; $otherConnections[] = $otherSide;
$other->setConnections($otherConnections); $other->setConnections($otherConnections);
$other->world->setBlock($other, $other); $this->pos->getWorld()->setBlock($other->pos, $other);
$changed = true; $changed = true;
$thisConnections[] = $thisSide; $thisConnections[] = $thisSide;
@ -257,7 +258,7 @@ abstract class BaseRail extends Flowable{
if($changed){ if($changed){
$this->setConnections($thisConnections); $this->setConnections($thisConnections);
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }
@ -273,11 +274,11 @@ abstract class BaseRail extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
}else{ }else{
foreach($this->connections as $connection){ foreach($this->connections as $connection){
if(($connection & self::FLAG_ASCEND) !== 0 and $this->getSide($connection & ~self::FLAG_ASCEND)->isTransparent()){ if(($connection & self::FLAG_ASCEND) !== 0 and $this->getSide($connection & ~self::FLAG_ASCEND)->isTransparent()){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
break; break;
} }
} }

View File

@ -73,7 +73,7 @@ class Bed extends Transparent{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
//read extra state information from the tile - this is an ugly hack //read extra state information from the tile - this is an ugly hack
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileBed){ if($tile instanceof TileBed){
$this->color = $tile->getColor(); $this->color = $tile->getColor();
} }
@ -82,7 +82,7 @@ class Bed extends Transparent{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
//extra block properties storage hack //extra block properties storage hack
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileBed){ if($tile instanceof TileBed){
$tile->setColor($this->color); $tile->setColor($this->color);
} }
@ -105,11 +105,11 @@ class Bed extends Transparent{
public function setOccupied(bool $occupied = true) : void{ public function setOccupied(bool $occupied = true) : void{
$this->occupied = $occupied; $this->occupied = $occupied;
$this->world->setBlock($this, $this, false); $this->pos->getWorld()->setBlock($this->pos, $this, false);
if(($other = $this->getOtherHalf()) !== null){ if(($other = $this->getOtherHalf()) !== null){
$other->occupied = $occupied; $other->occupied = $occupied;
$this->world->setBlock($other, $other, false); $this->pos->getWorld()->setBlock($other->pos, $other, false);
} }
} }
@ -139,12 +139,12 @@ class Bed extends Transparent{
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete"); $player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
return true; return true;
}elseif($player->distanceSquared($this) > 4 and $player->distanceSquared($other) > 4){ }elseif($player->distanceSquared($this->pos) > 4 and $player->distanceSquared($other->pos) > 4){
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.tooFar")); $player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.tooFar"));
return true; return true;
} }
$time = $this->getWorld()->getTimeOfDay(); $time = $this->pos->getWorld()->getTimeOfDay();
$isNight = ($time >= World::TIME_NIGHT and $time < World::TIME_SUNRISE); $isNight = ($time >= World::TIME_NIGHT and $time < World::TIME_SUNRISE);
@ -162,7 +162,7 @@ class Bed extends Transparent{
return true; return true;
} }
$player->sleepOn($b); $player->sleepOn($b->pos);
} }
return true; return true;
@ -181,7 +181,7 @@ class Bed extends Transparent{
if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){ if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){
$nextState = clone $this; $nextState = clone $this;
$nextState->head = true; $nextState->head = true;
$tx->addBlock($blockReplace, $this)->addBlock($next, $nextState); $tx->addBlock($blockReplace->pos, $this)->addBlock($next->pos, $nextState);
return true; return true;
} }
} }

View File

@ -49,7 +49,7 @@ use function assert;
use function dechex; use function dechex;
use const PHP_INT_MAX; use const PHP_INT_MAX;
class Block extends Position{ class Block{
/** @var BlockIdentifier */ /** @var BlockIdentifier */
protected $idInfo; protected $idInfo;
@ -60,6 +60,8 @@ class Block extends Position{
/** @var BlockBreakInfo */ /** @var BlockBreakInfo */
protected $breakInfo; protected $breakInfo;
/** @var Position */
protected $pos;
/** @var AxisAlignedBB */ /** @var AxisAlignedBB */
protected $boundingBox = null; protected $boundingBox = null;
@ -78,6 +80,11 @@ class Block extends Position{
$this->idInfo = $idInfo; $this->idInfo = $idInfo;
$this->fallbackName = $name; $this->fallbackName = $name;
$this->breakInfo = $breakInfo; $this->breakInfo = $breakInfo;
$this->pos = new Position(0, 0, 0, null);
}
public function __clone(){
$this->pos = Position::fromObject($this->pos, $this->pos->getWorld());
} }
public function getIdInfo() : BlockIdentifier{ public function getIdInfo() : BlockIdentifier{
@ -164,10 +171,10 @@ class Block extends Position{
} }
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
$this->world->getChunkAtPosition($this)->setFullBlock($this->x & 0xf, $this->y, $this->z & 0xf, $this->getFullId()); $this->pos->getWorld()->getChunkAtPosition($this->pos)->setFullBlock($this->pos->x & 0xf, $this->pos->y, $this->pos->z & 0xf, $this->getFullId());
$tileType = $this->idInfo->getTileClass(); $tileType = $this->idInfo->getTileClass();
$oldTile = $this->world->getTile($this); $oldTile = $this->pos->getWorld()->getTile($this->pos);
if($oldTile !== null){ if($oldTile !== null){
if($tileType === null or !($oldTile instanceof $tileType)){ if($tileType === null or !($oldTile instanceof $tileType)){
$oldTile->close(); $oldTile->close();
@ -177,7 +184,7 @@ class Block extends Position{
} }
} }
if($oldTile === null and $tileType !== null){ if($oldTile === null and $tileType !== null){
$this->world->addTile(TileFactory::create($tileType, $this->world, $this->asVector3())); $this->pos->getWorld()->addTile(TileFactory::create($tileType, $this->pos->getWorld(), $this->pos->asVector3()));
} }
} }
@ -239,7 +246,7 @@ class Block extends Position{
* @return bool * @return bool
*/ */
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$tx->addBlock($blockReplace, $this); $tx->addBlock($blockReplace->pos, $this);
return true; return true;
} }
@ -265,10 +272,10 @@ class Block extends Position{
* @return bool * @return bool
*/ */
public function onBreak(Item $item, ?Player $player = null) : bool{ public function onBreak(Item $item, ?Player $player = null) : bool{
if(($t = $this->world->getTile($this)) !== null){ if(($t = $this->pos->getWorld()->getTile($this->pos)) !== null){
$t->onBlockDestroyed(); $t->onBlockDestroyed();
} }
$this->getWorld()->setBlock($this, VanillaBlocks::AIR()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::AIR());
return true; return true;
} }
@ -404,6 +411,10 @@ class Block extends Position{
} }
final public function getPos() : Position{
return $this->pos;
}
/** /**
* @internal * @internal
* *
@ -413,10 +424,10 @@ class Block extends Position{
* @param int $z * @param int $z
*/ */
final public function position(World $world, int $x, int $y, int $z) : void{ final public function position(World $world, int $x, int $y, int $z) : void{
$this->x = $x; $this->pos->x = $x;
$this->y = $y; $this->pos->y = $y;
$this->z = $z; $this->pos->z = $z;
$this->world = $world; $this->pos->world = $world;
} }
/** /**
@ -504,7 +515,7 @@ class Block extends Position{
public function getPickedItem(bool $addUserData = false) : Item{ public function getPickedItem(bool $addUserData = false) : Item{
$item = $this->asItem(); $item = $this->asItem();
if($addUserData){ if($addUserData){
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof Tile){ if($tile instanceof Tile){
$nbt = $tile->getCleanedNBT(); $nbt = $tile->getCleanedNBT();
if($nbt instanceof CompoundTag){ if($nbt instanceof CompoundTag){
@ -577,8 +588,8 @@ class Block extends Position{
* @return Block * @return Block
*/ */
public function getSide(int $side, int $step = 1){ public function getSide(int $side, int $step = 1){
if($this->isValid()){ if($this->pos->isValid()){
return $this->getWorld()->getBlock(Vector3::getSide($side, $step)); return $this->pos->getWorld()->getBlock($this->pos->getSide($side, $step));
} }
throw new \InvalidStateException("Block does not have a valid world"); throw new \InvalidStateException("Block does not have a valid world");
@ -664,7 +675,7 @@ class Block extends Position{
if($this->collisionBoxes === null){ if($this->collisionBoxes === null){
$this->collisionBoxes = $this->recalculateCollisionBoxes(); $this->collisionBoxes = $this->recalculateCollisionBoxes();
foreach($this->collisionBoxes as $bb){ foreach($this->collisionBoxes as $bb){
$bb->offset($this->x, $this->y, $this->z); $bb->offset($this->pos->x, $this->pos->y, $this->pos->z);
} }
} }
@ -689,7 +700,7 @@ class Block extends Position{
if($this->boundingBox === null){ if($this->boundingBox === null){
$this->boundingBox = $this->recalculateBoundingBox(); $this->boundingBox = $this->recalculateBoundingBox();
if($this->boundingBox !== null){ if($this->boundingBox !== null){
$this->boundingBox->offset($this->x, $this->y, $this->z); $this->boundingBox->offset($this->pos->x, $this->pos->y, $this->pos->z);
} }
} }
return $this->boundingBox; return $this->boundingBox;

View File

@ -60,7 +60,7 @@ class BrewingStand extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$stand = $this->getWorld()->getTile($this); $stand = $this->pos->getWorld()->getTile($this->pos);
if($stand instanceof TileBrewingStand and $stand->canOpenWith($item->getCustomName())){ if($stand instanceof TileBrewingStand and $stand->canOpenWith($item->getCustomName())){
$player->setCurrentWindow($stand->getInventory()); $player->setCurrentWindow($stand->getInventory());
} }

View File

@ -64,9 +64,9 @@ abstract class Button extends Flowable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->powered){ if(!$this->powered){
$this->powered = true; $this->powered = true;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->scheduleDelayedBlockUpdate($this, $this->getActivationTime()); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, $this->getActivationTime());
$this->world->addSound($this->add(0.5, 0.5, 0.5), new RedstonePowerOnSound()); $this->pos->getWorld()->addSound($this->pos->add(0.5, 0.5, 0.5), new RedstonePowerOnSound());
} }
return true; return true;
@ -75,8 +75,8 @@ abstract class Button extends Flowable{
public function onScheduledUpdate() : void{ public function onScheduledUpdate() : void{
if($this->powered){ if($this->powered){
$this->powered = false; $this->powered = false;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->addSound($this->add(0.5, 0.5, 0.5), new RedstonePowerOffSound()); $this->pos->getWorld()->addSound($this->pos->add(0.5, 0.5, 0.5), new RedstonePowerOffSound());
} }
} }
} }

View File

@ -73,12 +73,12 @@ class Cactus extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN); $down = $this->getSide(Facing::DOWN);
if($down->getId() !== BlockLegacyIds::SAND and !$down->isSameType($this)){ if($down->getId() !== BlockLegacyIds::SAND and !$down->isSameType($this)){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
}else{ }else{
foreach(Facing::HORIZONTAL as $side){ foreach(Facing::HORIZONTAL as $side){
$b = $this->getSide($side); $b = $this->getSide($side);
if($b->isSolid()){ if($b->isSolid()){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
break; break;
} }
} }
@ -93,23 +93,23 @@ class Cactus extends Transparent{
if(!$this->getSide(Facing::DOWN)->isSameType($this)){ if(!$this->getSide(Facing::DOWN)->isSameType($this)){
if($this->age === 15){ if($this->age === 15){
for($y = 1; $y < 3; ++$y){ for($y = 1; $y < 3; ++$y){
$b = $this->getWorld()->getBlockAt($this->x, $this->y + $y, $this->z); $b = $this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + $y, $this->pos->z);
if($b->getId() === BlockLegacyIds::AIR){ if($b->getId() === BlockLegacyIds::AIR){
$ev = new BlockGrowEvent($b, VanillaBlocks::CACTUS()); $ev = new BlockGrowEvent($b, VanillaBlocks::CACTUS());
$ev->call(); $ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){
break; break;
} }
$this->getWorld()->setBlock($b, $ev->getNewState()); $this->pos->getWorld()->setBlock($b->pos, $ev->getNewState());
}else{ }else{
break; break;
} }
} }
$this->age = 0; $this->age = 0;
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
}else{ }else{
++$this->age; ++$this->age;
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }
} }

View File

@ -73,7 +73,7 @@ class Cake extends Transparent implements FoodSource{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){ //Replace with common break method if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){ //Replace with common break method
$this->getWorld()->setBlock($this, VanillaBlocks::AIR()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::AIR());
} }
} }
@ -126,6 +126,6 @@ class Cake extends Transparent implements FoodSource{
} }
public function onConsume(Living $consumer) : void{ public function onConsume(Living $consumer) : void{
$this->world->setBlock($this, $this->getResidue()); $this->pos->getWorld()->setBlock($this->pos, $this->getResidue());
} }
} }

View File

@ -55,7 +55,7 @@ class Carpet extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){ if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -67,7 +67,7 @@ class Chest extends Transparent{
} }
public function onPostPlace() : void{ public function onPostPlace() : void{
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileChest){ if($tile instanceof TileChest){
foreach([ foreach([
Facing::rotateY($this->facing, true), Facing::rotateY($this->facing, true),
@ -75,7 +75,7 @@ class Chest extends Transparent{
] as $side){ ] as $side){
$c = $this->getSide($side); $c = $this->getSide($side);
if($c instanceof Chest and $c->isSameType($this) and $c->facing === $this->facing){ if($c instanceof Chest and $c->isSameType($this) and $c->facing === $this->facing){
$pair = $this->world->getTile($c); $pair = $this->pos->getWorld()->getTile($c->pos);
if($pair instanceof TileChest and !$pair->isPaired()){ if($pair instanceof TileChest and !$pair->isPaired()){
$pair->pairWith($tile); $pair->pairWith($tile);
$tile->pairWith($pair); $tile->pairWith($pair);
@ -89,7 +89,7 @@ class Chest extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$chest = $this->getWorld()->getTile($this); $chest = $this->pos->getWorld()->getTile($this->pos);
if($chest instanceof TileChest){ if($chest instanceof TileChest){
if( if(
!$this->getSide(Facing::UP)->isTransparent() or !$this->getSide(Facing::UP)->isTransparent() or

View File

@ -34,7 +34,7 @@ class CoarseDirt extends Dirt{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP and $item instanceof Hoe){ if($face === Facing::UP and $item instanceof Hoe){
$item->applyDamage(1); $item->applyDamage(1);
$this->getWorld()->setBlock($this, VanillaBlocks::DIRT()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::DIRT());
return true; return true;
} }

View File

@ -84,7 +84,7 @@ class CocoaBlock extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->age < 2 and $item instanceof Fertilizer){ if($this->age < 2 and $item instanceof Fertilizer){
$this->age++; $this->age++;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$item->pop(); $item->pop();
@ -97,7 +97,7 @@ class CocoaBlock extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$side = $this->getSide(Facing::opposite($this->facing)); $side = $this->getSide(Facing::opposite($this->facing));
if(!($side instanceof Wood) or !$side->getTreeType()->equals(TreeType::JUNGLE())){ if(!($side instanceof Wood) or !$side->getTreeType()->equals(TreeType::JUNGLE())){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
@ -108,7 +108,7 @@ class CocoaBlock extends Transparent{
public function onRandomTick() : void{ public function onRandomTick() : void{
if($this->age < 2 and mt_rand(1, 5) === 1){ if($this->age < 2 and mt_rand(1, 5) === 1){
$this->age++; $this->age++;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }

View File

@ -38,7 +38,7 @@ class ConcretePowder extends Opaque implements Fallable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(($block = $this->checkAdjacentWater()) !== null){ if(($block = $this->checkAdjacentWater()) !== null){
$this->world->setBlock($this, $block); $this->pos->getWorld()->setBlock($this->pos, $block);
}else{ }else{
$this->startFalling(); $this->startFalling();
} }

View File

@ -73,7 +73,7 @@ abstract class Crops extends Flowable{
$ev = new BlockGrowEvent($this, $block); $ev = new BlockGrowEvent($this, $block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getWorld()->setBlock($this, $ev->getNewState()); $this->pos->getWorld()->setBlock($this->pos, $ev->getNewState());
} }
$item->pop(); $item->pop();
@ -86,7 +86,7 @@ abstract class Crops extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getId() !== BlockLegacyIds::FARMLAND){ if($this->getSide(Facing::DOWN)->getId() !== BlockLegacyIds::FARMLAND){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
@ -101,7 +101,7 @@ abstract class Crops extends Flowable{
$ev = new BlockGrowEvent($this, $block); $ev = new BlockGrowEvent($this, $block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getWorld()->setBlock($this, $ev->getNewState()); $this->pos->getWorld()->setBlock($this->pos, $ev->getNewState());
} }
} }
} }

View File

@ -90,23 +90,23 @@ class DaylightSensor extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->inverted = !$this->inverted; $this->inverted = !$this->inverted;
$this->power = $this->recalculatePower(); $this->power = $this->recalculatePower();
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
return true; return true;
} }
public function onScheduledUpdate() : void{ public function onScheduledUpdate() : void{
$this->power = $this->recalculatePower(); $this->power = $this->recalculatePower();
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->scheduleDelayedBlockUpdate($this, 20); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, 20);
} }
private function recalculatePower() : int{ private function recalculatePower() : int{
$lightLevel = $this->world->getRealBlockSkyLightAt($this->x, $this->y, $this->z); $lightLevel = $this->pos->getWorld()->getRealBlockSkyLightAt($this->pos->x, $this->pos->y, $this->pos->z);
if($this->inverted){ if($this->inverted){
return 15 - $lightLevel; return 15 - $lightLevel;
} }
$sunAngle = $this->world->getSunAnglePercentage(); $sunAngle = $this->pos->getWorld()->getSunAnglePercentage();
return max(0, (int) round($lightLevel * cos(($sunAngle + ((($sunAngle < 0.5 ? 0 : 1) - $sunAngle) / 5)) * 2 * M_PI))); return max(0, (int) round($lightLevel * cos(($sunAngle + ((($sunAngle < 0.5 ? 0 : 1) - $sunAngle) / 5)) * 2 * M_PI)));
} }

View File

@ -47,7 +47,7 @@ class DeadBush extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -38,7 +38,7 @@ class Dirt extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP and $item instanceof Hoe){ if($face === Facing::UP and $item instanceof Hoe){
$item->applyDamage(1); $item->applyDamage(1);
$this->getWorld()->setBlock($this, VanillaBlocks::FARMLAND()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::FARMLAND());
return true; return true;
} }

View File

@ -100,7 +100,7 @@ class Door extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){ //Replace with common break method if($this->getSide(Facing::DOWN)->getId() === BlockLegacyIds::AIR){ //Replace with common break method
$this->getWorld()->useBreakOn($this); //this will delete both halves if they exist $this->pos->getWorld()->useBreakOn($this->pos); //this will delete both halves if they exist
} }
} }
@ -126,7 +126,7 @@ class Door extends Transparent{
$topHalf = clone $this; $topHalf = clone $this;
$topHalf->top = true; $topHalf->top = true;
$tx->addBlock($blockReplace, $this)->addBlock($blockUp, $topHalf); $tx->addBlock($blockReplace->pos, $this)->addBlock($blockUp->pos, $topHalf);
return true; return true;
} }
@ -139,11 +139,11 @@ class Door extends Transparent{
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP); $other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
if($other instanceof Door and $other->isSameType($this)){ if($other instanceof Door and $other->isSameType($this)){
$other->open = $this->open; $other->open = $this->open;
$this->world->setBlock($other, $other); $this->pos->getWorld()->setBlock($other->pos, $other);
} }
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->addSound($this, new DoorSound()); $this->pos->getWorld()->addSound($this->pos, new DoorSound());
return true; return true;
} }

View File

@ -55,7 +55,7 @@ class DoublePlant extends Flowable{
if(($id === BlockLegacyIds::GRASS or $id === BlockLegacyIds::DIRT) and $blockReplace->getSide(Facing::UP)->canBeReplaced()){ if(($id === BlockLegacyIds::GRASS or $id === BlockLegacyIds::DIRT) and $blockReplace->getSide(Facing::UP)->canBeReplaced()){
$top = clone $this; $top = clone $this;
$top->top = true; $top->top = true;
$tx->addBlock($blockReplace, $this)->addBlock($blockReplace->getSide(Facing::UP), $top); $tx->addBlock($blockReplace->pos, $this)->addBlock($blockReplace->pos->getSide(Facing::UP), $top);
return true; return true;
} }
@ -78,7 +78,7 @@ class DoublePlant extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->isValidHalfPlant() or (!$this->top and $this->getSide(Facing::DOWN)->isTransparent())){ if(!$this->isValidHalfPlant() or (!$this->top and $this->getSide(Facing::DOWN)->isTransparent())){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -63,22 +63,22 @@ class DragonEgg extends Transparent implements Fallable{
public function teleport() : void{ public function teleport() : void{
for($tries = 0; $tries < 16; ++$tries){ for($tries = 0; $tries < 16; ++$tries){
$block = $this->world->getBlockAt( $block = $this->pos->getWorld()->getBlockAt(
$this->x + mt_rand(-16, 16), $this->pos->x + mt_rand(-16, 16),
max(0, min(World::Y_MAX - 1, $this->y + mt_rand(-8, 8))), max(0, min(World::Y_MAX - 1, $this->pos->y + mt_rand(-8, 8))),
$this->z + mt_rand(-16, 16) $this->pos->z + mt_rand(-16, 16)
); );
if($block instanceof Air){ if($block instanceof Air){
$ev = new BlockTeleportEvent($this, $block); $ev = new BlockTeleportEvent($this, $block->pos);
$ev->call(); $ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){
break; break;
}else{
$block = $ev->getTo();
} }
$this->world->addParticle($this, new DragonEggTeleportParticle($this->x - $block->x, $this->y - $block->y, $this->z - $block->z));
$this->world->setBlock($this, VanillaBlocks::AIR()); $blockPos = $ev->getTo();
$this->world->setBlock($block, $this); $this->pos->getWorld()->addParticle($this->pos, new DragonEggTeleportParticle($this->pos->x - $blockPos->x, $this->pos->y - $blockPos->y, $this->pos->z - $blockPos->z));
$this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::AIR());
$this->pos->getWorld()->setBlock($blockPos, $this);
break; break;
} }
} }

View File

@ -45,7 +45,7 @@ class EnchantingTable extends Transparent{
if($player instanceof Player){ if($player instanceof Player){
//TODO lock //TODO lock
$player->setCurrentWindow(new EnchantInventory($this)); $player->setCurrentWindow(new EnchantInventory($this->pos));
} }
return true; return true;

View File

@ -72,7 +72,7 @@ class EnderChest extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$enderChest = $this->getWorld()->getTile($this); $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($enderChest);
$player->setCurrentWindow($player->getEnderChestInventory()); $player->setCurrentWindow($player->getEnderChestInventory());

View File

@ -55,7 +55,7 @@ class Farmland extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::UP)->isSolid()){ if($this->getSide(Facing::UP)->isSolid()){
$this->world->setBlock($this, VanillaBlocks::DIRT()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::DIRT());
} }
} }
@ -67,24 +67,24 @@ class Farmland extends Transparent{
if(!$this->canHydrate()){ if(!$this->canHydrate()){
if($this->wetness > 0){ if($this->wetness > 0){
$this->wetness--; $this->wetness--;
$this->world->setBlock($this, $this, false); $this->pos->getWorld()->setBlock($this->pos, $this, false);
}else{ }else{
$this->world->setBlock($this, VanillaBlocks::DIRT()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::DIRT());
} }
}elseif($this->wetness < 7){ }elseif($this->wetness < 7){
$this->wetness = 7; $this->wetness = 7;
$this->world->setBlock($this, $this, false); $this->pos->getWorld()->setBlock($this->pos, $this, false);
} }
} }
protected function canHydrate() : bool{ protected function canHydrate() : bool{
//TODO: check rain //TODO: check rain
$start = $this->add(-4, 0, -4); $start = $this->pos->add(-4, 0, -4);
$end = $this->add(4, 1, 4); $end = $this->pos->add(4, 1, 4);
for($y = $start->y; $y <= $end->y; ++$y){ for($y = $start->y; $y <= $end->y; ++$y){
for($z = $start->z; $z <= $end->z; ++$z){ for($z = $start->z; $z <= $end->z; ++$z){
for($x = $start->x; $x <= $end->x; ++$x){ for($x = $start->x; $x <= $end->x; ++$x){
if($this->world->getBlockAt($x, $y, $z) instanceof Water){ if($this->pos->getWorld()->getBlockAt($x, $y, $z) instanceof Water){
return true; return true;
} }
} }

View File

@ -89,7 +89,7 @@ class FenceGate extends Transparent{
$inWall = $this->checkInWall(); $inWall = $this->checkInWall();
if($inWall !== $this->inWall){ if($inWall !== $this->inWall){
$this->inWall = $inWall; $this->inWall = $inWall;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }
@ -102,8 +102,8 @@ class FenceGate extends Transparent{
} }
} }
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->addSound($this, new DoorSound()); $this->pos->getWorld()->addSound($this->pos, new DoorSound());
return true; return true;
} }

View File

@ -88,9 +88,9 @@ class Fire extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->getSide(Facing::DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){ if(!$this->getSide(Facing::DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
$this->getWorld()->setBlock($this, VanillaBlocks::AIR()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::AIR());
}else{ }else{
$this->world->scheduleDelayedBlockUpdate($this, mt_rand(30, 40)); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, mt_rand(30, 40));
} }
} }
@ -124,10 +124,10 @@ class Fire extends Flowable{
} }
if($result !== null){ if($result !== null){
$this->world->setBlock($this, $result); $this->pos->getWorld()->setBlock($this->pos, $result);
} }
$this->world->scheduleDelayedBlockUpdate($this, mt_rand(30, 40)); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, mt_rand(30, 40));
if($canSpread){ if($canSpread){
//TODO: raise upper bound for chance in humid biomes //TODO: raise upper bound for chance in humid biomes
@ -168,9 +168,9 @@ class Fire extends Flowable{
if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain
$fire = clone $this; $fire = clone $this;
$fire->age = min(15, $fire->age + (mt_rand(0, 4) >> 2)); $fire->age = min(15, $fire->age + (mt_rand(0, 4) >> 2));
$this->world->setBlock($block, $fire); $this->pos->getWorld()->setBlock($block->pos, $fire);
}else{ }else{
$this->world->setBlock($block, VanillaBlocks::AIR()); $this->pos->getWorld()->setBlock($block->pos, VanillaBlocks::AIR());
} }
} }
} }

View File

@ -46,7 +46,7 @@ class Flower extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -61,7 +61,7 @@ class FlowerPot extends Flowable{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileFlowerPot){ if($tile instanceof TileFlowerPot){
$this->setPlant($tile->getPlant()); $this->setPlant($tile->getPlant());
}else{ }else{
@ -72,7 +72,7 @@ class FlowerPot extends Flowable{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
assert($tile instanceof TileFlowerPot); assert($tile instanceof TileFlowerPot);
$tile->setPlant($this->plant); $tile->setPlant($this->plant);
} }
@ -125,7 +125,7 @@ class FlowerPot extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
@ -137,7 +137,7 @@ class FlowerPot extends Flowable{
$this->setPlant($plant); $this->setPlant($plant);
$item->pop(); $item->pop();
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
return true; return true;
} }

View File

@ -50,17 +50,17 @@ class FrostedIce extends Ice{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->checkAdjacentBlocks(2)){ if(!$this->checkAdjacentBlocks(2)){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
}else{ }else{
$this->world->scheduleDelayedBlockUpdate($this, mt_rand(20, 40)); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, mt_rand(20, 40));
} }
} }
public function onRandomTick() : void{ public function onRandomTick() : void{
if((!$this->checkAdjacentBlocks(4) or mt_rand(0, 2) === 0) and if((!$this->checkAdjacentBlocks(4) or mt_rand(0, 2) === 0) and
max( //TODO: move this to World max( //TODO: move this to World
$this->world->getHighestAdjacentBlockLight($this->x, $this->y, $this->z), $this->pos->getWorld()->getHighestAdjacentBlockLight($this->pos->x, $this->pos->y, $this->pos->z),
$this->world->getHighestAdjacentBlockSkyLight($this->x, $this->y, $this->z) - $this->world->getSkyLightReduction() $this->pos->getWorld()->getHighestAdjacentBlockSkyLight($this->pos->x, $this->pos->y, $this->pos->z) - $this->pos->getWorld()->getSkyLightReduction()
) >= 12 - $this->age){ ) >= 12 - $this->age){
if($this->tryMelt()){ if($this->tryMelt()){
foreach($this->getAllSides() as $block){ foreach($this->getAllSides() as $block){
@ -70,7 +70,7 @@ class FrostedIce extends Ice{
} }
} }
}else{ }else{
$this->world->scheduleDelayedBlockUpdate($this, mt_rand(20, 40)); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, mt_rand(20, 40));
} }
} }
@ -86,7 +86,7 @@ class FrostedIce extends Ice{
continue; continue;
} }
if( if(
$this->world->getBlockAt($this->x + $x, $this->y, $this->z + $z) instanceof FrostedIce and $this->pos->getWorld()->getBlockAt($this->pos->x + $x, $this->pos->y, $this->pos->z + $z) instanceof FrostedIce and
++$found >= $requirement ++$found >= $requirement
){ ){
return true; return true;
@ -103,13 +103,13 @@ class FrostedIce extends Ice{
*/ */
private function tryMelt() : bool{ private function tryMelt() : bool{
if($this->age >= 3){ if($this->age >= 3){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
return true; return true;
} }
$this->age++; $this->age++;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->scheduleDelayedBlockUpdate($this, mt_rand(20, 40)); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, mt_rand(20, 40));
return false; return false;
} }
} }

View File

@ -90,7 +90,7 @@ class Furnace extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$furnace = $this->getWorld()->getTile($this); $furnace = $this->pos->getWorld()->getTile($this->pos);
if($furnace instanceof TileFurnace and $furnace->canOpenWith($item->getCustomName())){ if($furnace instanceof TileFurnace and $furnace->canOpenWith($item->getCustomName())){
$player->setCurrentWindow($furnace->getInventory()); $player->setCurrentWindow($furnace->getInventory());
} }
@ -100,9 +100,9 @@ class Furnace extends Opaque{
} }
public function onScheduledUpdate() : void{ public function onScheduledUpdate() : void{
$furnace = $this->getWorld()->getTile($this); $furnace = $this->pos->getWorld()->getTile($this->pos);
if($furnace instanceof TileFurnace and $furnace->onUpdate()){ if($furnace instanceof TileFurnace and $furnace->onUpdate()){
$this->world->scheduleDelayedBlockUpdate($this, 1); //TODO: check this $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, 1); //TODO: check this
} }
} }
} }

View File

@ -52,27 +52,27 @@ class Grass extends Opaque{
} }
public function onRandomTick() : void{ public function onRandomTick() : void{
$lightAbove = $this->world->getFullLightAt($this->x, $this->y + 1, $this->z); $lightAbove = $this->pos->getWorld()->getFullLightAt($this->pos->x, $this->pos->y + 1, $this->pos->z);
if($lightAbove < 4 and $this->world->getBlockAt($this->x, $this->y + 1, $this->z)->getLightFilter() >= 2){ if($lightAbove < 4 and $this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + 1, $this->pos->z)->getLightFilter() >= 2){
//grass dies //grass dies
$ev = new BlockSpreadEvent($this, $this, VanillaBlocks::DIRT()); $ev = new BlockSpreadEvent($this, $this, VanillaBlocks::DIRT());
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->world->setBlock($this, $ev->getNewState(), false); $this->pos->getWorld()->setBlock($this->pos, $ev->getNewState(), false);
} }
}elseif($lightAbove >= 9){ }elseif($lightAbove >= 9){
//try grass spread //try grass spread
for($i = 0; $i < 4; ++$i){ for($i = 0; $i < 4; ++$i){
$x = mt_rand($this->x - 1, $this->x + 1); $x = mt_rand($this->pos->x - 1, $this->pos->x + 1);
$y = mt_rand($this->y - 3, $this->y + 1); $y = mt_rand($this->pos->y - 3, $this->pos->y + 1);
$z = mt_rand($this->z - 1, $this->z + 1); $z = mt_rand($this->pos->z - 1, $this->pos->z + 1);
$b = $this->world->getBlockAt($x, $y, $z); $b = $this->pos->getWorld()->getBlockAt($x, $y, $z);
if( if(
!($b instanceof Dirt) or !($b instanceof Dirt) or
$b instanceof CoarseDirt or $b instanceof CoarseDirt or
$this->world->getFullLightAt($x, $y + 1, $z) < 4 or $this->pos->getWorld()->getFullLightAt($x, $y + 1, $z) < 4 or
$this->world->getBlockAt($x, $y + 1, $z)->getLightFilter() >= 2 $this->pos->getWorld()->getBlockAt($x, $y + 1, $z)->getLightFilter() >= 2
){ ){
continue; continue;
} }
@ -80,7 +80,7 @@ class Grass extends Opaque{
$ev = new BlockSpreadEvent($b, $this, VanillaBlocks::GRASS()); $ev = new BlockSpreadEvent($b, $this, VanillaBlocks::GRASS());
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->world->setBlock($b, $ev->getNewState(), false); $this->pos->getWorld()->setBlock($b->pos, $ev->getNewState(), false);
} }
} }
} }
@ -92,17 +92,17 @@ class Grass extends Opaque{
} }
if($item instanceof Fertilizer){ if($item instanceof Fertilizer){
$item->pop(); $item->pop();
TallGrassObject::growGrass($this->getWorld(), $this, new Random(mt_rand()), 8, 2); TallGrassObject::growGrass($this->pos->getWorld(), $this->pos, new Random(mt_rand()), 8, 2);
return true; return true;
}elseif($item instanceof Hoe){ }elseif($item instanceof Hoe){
$item->applyDamage(1); $item->applyDamage(1);
$this->getWorld()->setBlock($this, VanillaBlocks::FARMLAND()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::FARMLAND());
return true; return true;
}elseif($item instanceof Shovel and $this->getSide(Facing::UP)->getId() === BlockLegacyIds::AIR){ }elseif($item instanceof Shovel and $this->getSide(Facing::UP)->getId() === BlockLegacyIds::AIR){
$item->applyDamage(1); $item->applyDamage(1);
$this->getWorld()->setBlock($this, VanillaBlocks::GRASS_PATH()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::GRASS_PATH());
return true; return true;
} }

View File

@ -39,7 +39,7 @@ class GrassPath extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::UP)->isSolid()){ if($this->getSide(Facing::UP)->isSolid()){
$this->world->setBlock($this, VanillaBlocks::DIRT()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::DIRT());
} }
} }

View File

@ -76,7 +76,7 @@ class Hopper extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){ if($player !== null){
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileHopper){ //TODO: find a way to have inventories open on click without this boilerplate in every block if($tile instanceof TileHopper){ //TODO: find a way to have inventories open on click without this boilerplate in every block
$player->setCurrentWindow($tile->getInventory()); $player->setCurrentWindow($tile->getInventory());
} }

View File

@ -43,7 +43,7 @@ class Ice extends Transparent{
public function onBreak(Item $item, ?Player $player = null) : bool{ public function onBreak(Item $item, ?Player $player = null) : bool{
if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(Enchantment::SILK_TOUCH())){ if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(Enchantment::SILK_TOUCH())){
$this->getWorld()->setBlock($this, VanillaBlocks::WATER()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::WATER());
return true; return true;
} }
return parent::onBreak($item, $player); return parent::onBreak($item, $player);
@ -54,8 +54,8 @@ class Ice extends Transparent{
} }
public function onRandomTick() : void{ public function onRandomTick() : void{
if($this->world->getHighestAdjacentBlockLight($this->x, $this->y, $this->z) >= 12){ if($this->pos->getWorld()->getHighestAdjacentBlockLight($this->pos->x, $this->pos->y, $this->pos->z) >= 12){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -61,7 +61,7 @@ class ItemFrame extends Flowable{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileItemFrame){ if($tile instanceof TileItemFrame){
$this->framedItem = $tile->getItem(); $this->framedItem = $tile->getItem();
if($this->framedItem->isNull()){ if($this->framedItem->isNull()){
@ -74,7 +74,7 @@ class ItemFrame extends Flowable{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileItemFrame){ if($tile instanceof TileItemFrame){
$tile->setItem($this->framedItem); $tile->setItem($this->framedItem);
$tile->setItemRotation($this->itemRotation); $tile->setItemRotation($this->itemRotation);
@ -156,7 +156,7 @@ class ItemFrame extends Flowable{
return true; return true;
} }
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
return true; return true;
} }
@ -166,16 +166,16 @@ class ItemFrame extends Flowable{
return false; return false;
} }
if(lcg_value() <= $this->itemDropChance){ if(lcg_value() <= $this->itemDropChance){
$this->world->dropItem($this->add(0.5, 0.5, 0.5), $this->getFramedItem()); $this->pos->getWorld()->dropItem($this->pos->add(0.5, 0.5, 0.5), $this->getFramedItem());
} }
$this->setFramedItem(null); $this->setFramedItem(null);
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
return true; return true;
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){ if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -66,7 +66,7 @@ class Ladder extends Transparent{
} }
public function onEntityInside(Entity $entity) : void{ public function onEntityInside(Entity $entity) : void{
if($entity->asVector3()->floor()->distanceSquared($this) < 1){ //entity coordinates must be inside block if($entity->asVector3()->floor()->distanceSquared($this->pos) < 1){ //entity coordinates must be inside block
$entity->resetFallDistance(); $entity->resetFallDistance();
$entity->onGround = true; $entity->onGround = true;
} }
@ -88,7 +88,7 @@ class Ladder extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){ //Replace with common break method if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){ //Replace with common break method
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
} }

View File

@ -64,17 +64,17 @@ class Lantern extends Transparent{
} }
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canAttachTo($this->world->getBlock($blockReplace->up())) and !$this->canAttachTo($this->world->getBlock($blockReplace->down()))){ if(!$this->canAttachTo($this->pos->getWorld()->getBlock($blockReplace->getPos()->up())) and !$this->canAttachTo($this->pos->getWorld()->getBlock($blockReplace->getPos()->down()))){
return false; return false;
} }
$this->hanging = ($face === Facing::DOWN or !$this->canAttachTo($this->world->getBlock($blockReplace->down()))); $this->hanging = ($face === Facing::DOWN or !$this->canAttachTo($this->pos->getWorld()->getBlock($blockReplace->getPos()->down())));
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->canAttachTo($this->world->getBlock($this->hanging ? $this->up() : $this->down()))){ if(!$this->canAttachTo($this->pos->getWorld()->getBlock($this->hanging ? $this->pos->up() : $this->pos->down()))){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
} }

View File

@ -68,18 +68,19 @@ class Leaves extends Transparent{
} }
protected function findLog(Block $pos, array &$visited = [], int $distance = 0) : bool{ protected function findLog(Vector3 $pos, array &$visited = [], int $distance = 0) : bool{
$index = World::blockHash($pos->x, $pos->y, $pos->z); $index = World::blockHash($pos->x, $pos->y, $pos->z);
if(isset($visited[$index])){ if(isset($visited[$index])){
return false; return false;
} }
$visited[$index] = true; $visited[$index] = true;
$block = $this->pos->getWorld()->getBlock($pos);
if($pos instanceof Wood){ //type doesn't matter if($pos instanceof Wood){ //type doesn't matter
return true; return true;
} }
if($pos->getId() === $this->getId() and $distance <= 4){ if($block->getId() === $this->getId() and $distance <= 4){
foreach(Facing::ALL as $side){ foreach(Facing::ALL as $side){
if($this->findLog($pos->getSide($side), $visited, $distance + 1)){ if($this->findLog($pos->getSide($side), $visited, $distance + 1)){
return true; return true;
@ -93,7 +94,7 @@ class Leaves extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->noDecay and !$this->checkDecay){ if(!$this->noDecay and !$this->checkDecay){
$this->checkDecay = true; $this->checkDecay = true;
$this->getWorld()->setBlock($this, $this, false); $this->pos->getWorld()->setBlock($this->pos, $this, false);
} }
} }
@ -105,11 +106,11 @@ class Leaves extends Transparent{
if(!$this->noDecay and $this->checkDecay){ if(!$this->noDecay and $this->checkDecay){
$ev = new LeavesDecayEvent($this); $ev = new LeavesDecayEvent($this);
$ev->call(); $ev->call();
if($ev->isCancelled() or $this->findLog($this)){ if($ev->isCancelled() or $this->findLog($this->pos)){
$this->checkDecay = false; $this->checkDecay = false;
$this->getWorld()->setBlock($this, $this, false); $this->pos->getWorld()->setBlock($this->pos, $this, false);
}else{ }else{
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
} }

View File

@ -38,7 +38,7 @@ class Lever extends Flowable{
protected const TOP = 2; protected const TOP = 2;
/** @var int */ /** @var int */
protected $position = self::BOTTOM; protected $leverPos = self::BOTTOM;
/** @var int */ /** @var int */
protected $facing = Facing::NORTH; protected $facing = Facing::NORTH;
/** @var bool */ /** @var bool */
@ -49,9 +49,9 @@ class Lever extends Flowable{
} }
protected function writeStateToMeta() : int{ protected function writeStateToMeta() : int{
if($this->position === self::BOTTOM){ if($this->leverPos === self::BOTTOM){
$rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 7 : 0; $rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 7 : 0;
}elseif($this->position === self::TOP){ }elseif($this->leverPos === self::TOP){
$rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 5 : 6; $rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 5 : 6;
}else{ }else{
$rotationMeta = 6 - BlockDataSerializer::writeHorizontalFacing($this->facing); $rotationMeta = 6 - BlockDataSerializer::writeHorizontalFacing($this->facing);
@ -62,13 +62,13 @@ class Lever extends Flowable{
public function readStateFromData(int $id, int $stateMeta) : void{ public function readStateFromData(int $id, int $stateMeta) : void{
$rotationMeta = $stateMeta & 0x07; $rotationMeta = $stateMeta & 0x07;
if($rotationMeta === 5 or $rotationMeta === 6){ if($rotationMeta === 5 or $rotationMeta === 6){
$this->position = self::TOP; $this->leverPos = self::TOP;
$this->facing = $rotationMeta === 5 ? Facing::SOUTH : Facing::EAST; $this->facing = $rotationMeta === 5 ? Facing::SOUTH : Facing::EAST;
}elseif($rotationMeta === 7 or $rotationMeta === 0){ }elseif($rotationMeta === 7 or $rotationMeta === 0){
$this->position = self::BOTTOM; $this->leverPos = self::BOTTOM;
$this->facing = $rotationMeta === 7 ? Facing::SOUTH : Facing::EAST; $this->facing = $rotationMeta === 7 ? Facing::SOUTH : Facing::EAST;
}else{ }else{
$this->position = self::SIDE; $this->leverPos = self::SIDE;
$this->facing = BlockDataSerializer::readHorizontalFacing(6 - $rotationMeta); $this->facing = BlockDataSerializer::readHorizontalFacing(6 - $rotationMeta);
} }
@ -88,34 +88,34 @@ class Lever extends Flowable{
if($player !== null){ if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing()); $this->facing = Facing::opposite($player->getHorizontalFacing());
} }
$this->position = $face === Facing::DOWN ? self::BOTTOM : self::TOP; $this->leverPos = $face === Facing::DOWN ? self::BOTTOM : self::TOP;
}else{ }else{
$this->facing = $face; $this->facing = $face;
$this->position = self::SIDE; $this->leverPos = self::SIDE;
} }
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->position === self::BOTTOM){ if($this->leverPos === self::BOTTOM){
$face = Facing::UP; $face = Facing::UP;
}elseif($this->position === self::TOP){ }elseif($this->leverPos === self::TOP){
$face = Facing::DOWN; $face = Facing::DOWN;
}else{ }else{
$face = Facing::opposite($this->facing); $face = Facing::opposite($this->facing);
} }
if(!$this->getSide($face)->isSolid()){ if(!$this->getSide($face)->isSolid()){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->powered = !$this->powered; $this->powered = !$this->powered;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->addSound( $this->pos->getWorld()->addSound(
$this->add(0.5, 0.5, 0.5), $this->pos->add(0.5, 0.5, 0.5),
$this->powered ? new RedstonePowerOnSound() : new RedstonePowerOffSound() $this->powered ? new RedstonePowerOnSound() : new RedstonePowerOffSound()
); );
return true; return true;

View File

@ -169,9 +169,9 @@ abstract class Liquid extends Transparent{
for($j = 0; $j < 4; ++$j){ for($j = 0; $j < 4; ++$j){
$x = $this->x; $x = $this->pos->x;
$y = $this->y; $y = $this->pos->y;
$z = $this->z; $z = $this->pos->z;
if($j === 0){ if($j === 0){
--$x; --$x;
@ -182,7 +182,8 @@ abstract class Liquid extends Transparent{
}elseif($j === 3){ }elseif($j === 3){
++$z; ++$z;
} }
$sideBlock = $this->world->getBlockAt($x, $y, $z);
$sideBlock = $this->pos->getWorld()->getBlockAt($x, $y, $z);
$blockDecay = $this->getEffectiveFlowDecay($sideBlock); $blockDecay = $this->getEffectiveFlowDecay($sideBlock);
if($blockDecay < 0){ if($blockDecay < 0){
@ -190,34 +191,34 @@ abstract class Liquid extends Transparent{
continue; continue;
} }
$blockDecay = $this->getEffectiveFlowDecay($this->world->getBlockAt($x, $y - 1, $z)); $blockDecay = $this->getEffectiveFlowDecay($this->pos->getWorld()->getBlockAt($x, $y - 1, $z));
if($blockDecay >= 0){ if($blockDecay >= 0){
$realDecay = $blockDecay - ($decay - 8); $realDecay = $blockDecay - ($decay - 8);
$vector->x += ($sideBlock->x - $this->x) * $realDecay; $vector->x += ($x - $this->pos->x) * $realDecay;
$vector->y += ($sideBlock->y - $this->y) * $realDecay; $vector->y += ($y - $this->pos->y) * $realDecay;
$vector->z += ($sideBlock->z - $this->z) * $realDecay; $vector->z += ($z - $this->pos->z) * $realDecay;
} }
continue; continue;
}else{ }else{
$realDecay = $blockDecay - $decay; $realDecay = $blockDecay - $decay;
$vector->x += ($sideBlock->x - $this->x) * $realDecay; $vector->x += ($x - $this->pos->x) * $realDecay;
$vector->y += ($sideBlock->y - $this->y) * $realDecay; $vector->y += ($y - $this->pos->y) * $realDecay;
$vector->z += ($sideBlock->z - $this->z) * $realDecay; $vector->z += ($z - $this->pos->z) * $realDecay;
} }
} }
if($this->falling){ if($this->falling){
if( if(
!$this->canFlowInto($this->world->getBlockAt($this->x, $this->y, $this->z - 1)) or !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y, $this->pos->z - 1)) or
!$this->canFlowInto($this->world->getBlockAt($this->x, $this->y, $this->z + 1)) or !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y, $this->pos->z + 1)) or
!$this->canFlowInto($this->world->getBlockAt($this->x - 1, $this->y, $this->z)) or !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x - 1, $this->pos->y, $this->pos->z)) or
!$this->canFlowInto($this->world->getBlockAt($this->x + 1, $this->y, $this->z)) or !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x + 1, $this->pos->y, $this->pos->z)) or
!$this->canFlowInto($this->world->getBlockAt($this->x, $this->y + 1, $this->z - 1)) or !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + 1, $this->pos->z - 1)) or
!$this->canFlowInto($this->world->getBlockAt($this->x, $this->y + 1, $this->z + 1)) or !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + 1, $this->pos->z + 1)) or
!$this->canFlowInto($this->world->getBlockAt($this->x - 1, $this->y + 1, $this->z)) or !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x - 1, $this->pos->y + 1, $this->pos->z)) or
!$this->canFlowInto($this->world->getBlockAt($this->x + 1, $this->y + 1, $this->z)) !$this->canFlowInto($this->pos->getWorld()->getBlockAt($this->pos->x + 1, $this->pos->y + 1, $this->pos->z))
){ ){
$vector = $vector->normalize()->add(0, -6, 0); $vector = $vector->normalize()->add(0, -6, 0);
} }
@ -248,7 +249,7 @@ abstract class Liquid extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$this->checkForHarden(); $this->checkForHarden();
$this->world->scheduleDelayedBlockUpdate($this, $this->tickRate()); $this->pos->getWorld()->scheduleDelayedBlockUpdate($this->pos, $this->tickRate());
} }
public function onScheduledUpdate() : void{ public function onScheduledUpdate() : void{
@ -257,10 +258,10 @@ abstract class Liquid extends Transparent{
if(!$this->isSource()){ if(!$this->isSource()){
$smallestFlowDecay = -100; $smallestFlowDecay = -100;
$this->adjacentSources = 0; $this->adjacentSources = 0;
$smallestFlowDecay = $this->getSmallestFlowDecay($this->world->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay); $smallestFlowDecay = $this->getSmallestFlowDecay($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y, $this->pos->z - 1), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->world->getBlockAt($this->x, $this->y, $this->z + 1), $smallestFlowDecay); $smallestFlowDecay = $this->getSmallestFlowDecay($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y, $this->pos->z + 1), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->world->getBlockAt($this->x - 1, $this->y, $this->z), $smallestFlowDecay); $smallestFlowDecay = $this->getSmallestFlowDecay($this->pos->getWorld()->getBlockAt($this->pos->x - 1, $this->pos->y, $this->pos->z), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->world->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay); $smallestFlowDecay = $this->getSmallestFlowDecay($this->pos->getWorld()->getBlockAt($this->pos->x + 1, $this->pos->y, $this->pos->z), $smallestFlowDecay);
$newDecay = $smallestFlowDecay + $multiplier; $newDecay = $smallestFlowDecay + $multiplier;
$falling = false; $falling = false;
@ -269,12 +270,12 @@ abstract class Liquid extends Transparent{
$newDecay = -1; $newDecay = -1;
} }
if($this->getEffectiveFlowDecay($this->world->getBlockAt($this->x, $this->y + 1, $this->z)) >= 0){ if($this->getEffectiveFlowDecay($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + 1, $this->pos->z)) >= 0){
$falling = true; $falling = true;
} }
if($this->adjacentSources >= 2 and $this instanceof Water){ if($this->adjacentSources >= 2 and $this instanceof Water){
$bottomBlock = $this->world->getBlockAt($this->x, $this->y - 1, $this->z); $bottomBlock = $this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y - 1, $this->pos->z);
if($bottomBlock->isSolid() or ($bottomBlock instanceof Water and $bottomBlock->isSource())){ if($bottomBlock->isSolid() or ($bottomBlock instanceof Water and $bottomBlock->isSource())){
$newDecay = 0; $newDecay = 0;
$falling = false; $falling = false;
@ -283,17 +284,17 @@ abstract class Liquid extends Transparent{
if($falling !== $this->falling or (!$falling and $newDecay !== $this->decay)){ if($falling !== $this->falling or (!$falling and $newDecay !== $this->decay)){
if(!$falling and $newDecay < 0){ if(!$falling and $newDecay < 0){
$this->world->setBlock($this, VanillaBlocks::AIR()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::AIR());
return; return;
} }
$this->falling = $falling; $this->falling = $falling;
$this->decay = $falling ? 0 : $newDecay; $this->decay = $falling ? 0 : $newDecay;
$this->world->setBlock($this, $this); //local block update will cause an update to be scheduled $this->pos->getWorld()->setBlock($this->pos, $this); //local block update will cause an update to be scheduled
} }
} }
$bottomBlock = $this->world->getBlockAt($this->x, $this->y - 1, $this->z); $bottomBlock = $this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y - 1, $this->pos->z);
$this->flowIntoBlock($bottomBlock, 0, true); $this->flowIntoBlock($bottomBlock, 0, true);
@ -308,19 +309,19 @@ abstract class Liquid extends Transparent{
$flags = $this->getOptimalFlowDirections(); $flags = $this->getOptimalFlowDirections();
if($flags[0]){ if($flags[0]){
$this->flowIntoBlock($this->world->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay, false); $this->flowIntoBlock($this->pos->getWorld()->getBlockAt($this->pos->x - 1, $this->pos->y, $this->pos->z), $adjacentDecay, false);
} }
if($flags[1]){ if($flags[1]){
$this->flowIntoBlock($this->world->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay, false); $this->flowIntoBlock($this->pos->getWorld()->getBlockAt($this->pos->x + 1, $this->pos->y, $this->pos->z), $adjacentDecay, false);
} }
if($flags[2]){ if($flags[2]){
$this->flowIntoBlock($this->world->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay, false); $this->flowIntoBlock($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y, $this->pos->z - 1), $adjacentDecay, false);
} }
if($flags[3]){ if($flags[3]){
$this->flowIntoBlock($this->world->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay, false); $this->flowIntoBlock($this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y, $this->pos->z + 1), $adjacentDecay, false);
} }
} }
} }
@ -338,10 +339,10 @@ abstract class Liquid extends Transparent{
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
if($block->getId() > 0){ if($block->getId() > 0){
$this->world->useBreakOn($block); $this->pos->getWorld()->useBreakOn($block->pos);
} }
$this->world->setBlock($block, $ev->getNewState()); $this->pos->getWorld()->setBlock($block->pos, $ev->getNewState());
} }
} }
} }
@ -369,10 +370,10 @@ abstract class Liquid extends Transparent{
} }
if(!isset($this->flowCostVisited[$hash = World::blockHash($x, $y, $z)])){ if(!isset($this->flowCostVisited[$hash = World::blockHash($x, $y, $z)])){
$blockSide = $this->world->getBlockAt($x, $y, $z); $blockSide = $this->pos->getWorld()->getBlockAt($x, $y, $z);
if(!$this->canFlowInto($blockSide)){ if(!$this->canFlowInto($blockSide)){
$this->flowCostVisited[$hash] = self::BLOCKED; $this->flowCostVisited[$hash] = self::BLOCKED;
}elseif($this->world->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){ }elseif($this->pos->getWorld()->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
$this->flowCostVisited[$hash] = self::CAN_FLOW_DOWN; $this->flowCostVisited[$hash] = self::CAN_FLOW_DOWN;
}else{ }else{
$this->flowCostVisited[$hash] = self::CAN_FLOW; $this->flowCostVisited[$hash] = self::CAN_FLOW;
@ -408,9 +409,9 @@ abstract class Liquid extends Transparent{
$flowCost = array_fill(0, 4, 1000); $flowCost = array_fill(0, 4, 1000);
$maxCost = intdiv(4, $this->getFlowDecayPerBlock()); $maxCost = intdiv(4, $this->getFlowDecayPerBlock());
for($j = 0; $j < 4; ++$j){ for($j = 0; $j < 4; ++$j){
$x = $this->x; $x = $this->pos->x;
$y = $this->y; $y = $this->pos->y;
$z = $this->z; $z = $this->pos->z;
if($j === 0){ if($j === 0){
--$x; --$x;
@ -421,12 +422,12 @@ abstract class Liquid extends Transparent{
}elseif($j === 3){ }elseif($j === 3){
++$z; ++$z;
} }
$block = $this->world->getBlockAt($x, $y, $z); $block = $this->pos->getWorld()->getBlockAt($x, $y, $z);
if(!$this->canFlowInto($block)){ if(!$this->canFlowInto($block)){
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::BLOCKED; $this->flowCostVisited[World::blockHash($x, $y, $z)] = self::BLOCKED;
continue; continue;
}elseif($this->world->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){ }elseif($this->pos->getWorld()->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW_DOWN; $this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW_DOWN;
$flowCost[$j] = $maxCost = 0; $flowCost[$j] = $maxCost = 0;
}elseif($maxCost > 0){ }elseif($maxCost > 0){
@ -473,13 +474,13 @@ abstract class Liquid extends Transparent{
$ev = new BlockFormEvent($this, $result); $ev = new BlockFormEvent($this, $result);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->world->setBlock($this, $ev->getNewState()); $this->pos->getWorld()->setBlock($this->pos, $ev->getNewState());
$this->world->addSound($this->add(0.5, 0.5, 0.5), new FizzSound(2.6 + (lcg_value() - lcg_value()) * 0.8)); $this->pos->getWorld()->addSound($this->pos->add(0.5, 0.5, 0.5), new FizzSound(2.6 + (lcg_value() - lcg_value()) * 0.8));
} }
return true; return true;
} }
protected function canFlowInto(Block $block) : bool{ protected function canFlowInto(Block $block) : bool{
return $this->world->isInWorld($block->x, $block->y, $block->z) and $block->canBeFlowedInto() and !($block instanceof Liquid and $block->isSource()); //TODO: I think this should only be liquids of the same type return $this->pos->getWorld()->isInWorld($block->pos->x, $block->pos->y, $block->pos->z) and $block->canBeFlowedInto() and !($block instanceof Liquid and $block->isSource()); //TODO: I think this should only be liquids of the same type
} }
} }

View File

@ -27,6 +27,7 @@ use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\math\Facing; use pocketmine\math\Facing;
use function mt_rand; use function mt_rand;
use pocketmine\world\Position;
class Mycelium extends Opaque{ class Mycelium extends Opaque{
@ -46,16 +47,16 @@ class Mycelium extends Opaque{
public function onRandomTick() : void{ public function onRandomTick() : void{
//TODO: light levels //TODO: light levels
$x = mt_rand($this->x - 1, $this->x + 1); $x = mt_rand($this->pos->x - 1, $this->pos->x + 1);
$y = mt_rand($this->y - 2, $this->y + 2); $y = mt_rand($this->pos->y - 2, $this->pos->y + 2);
$z = mt_rand($this->z - 1, $this->z + 1); $z = mt_rand($this->pos->z - 1, $this->pos->z + 1);
$block = $this->getWorld()->getBlockAt($x, $y, $z); $block = $this->pos->getWorld()->getBlockAt($x, $y, $z);
if($block->getId() === BlockLegacyIds::DIRT){ if($block->getId() === BlockLegacyIds::DIRT){
if($block->getSide(Facing::UP) instanceof Transparent){ if($block->getSide(Facing::UP) instanceof Transparent){
$ev = new BlockSpreadEvent($block, $this, VanillaBlocks::MYCELIUM()); $ev = new BlockSpreadEvent($block, $this, VanillaBlocks::MYCELIUM());
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getWorld()->setBlock($block, $ev->getNewState()); $this->pos->getWorld()->setBlock($block->pos, $ev->getNewState());
} }
} }
} }

View File

@ -65,7 +65,7 @@ class NetherWartPlant extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->getId() !== BlockLegacyIds::SOUL_SAND){ if($this->getSide(Facing::DOWN)->getId() !== BlockLegacyIds::SOUL_SAND){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
@ -80,7 +80,7 @@ class NetherWartPlant extends Flowable{
$ev = new BlockGrowEvent($this, $block); $ev = new BlockGrowEvent($this, $block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getWorld()->setBlock($this, $ev->getNewState()); $this->pos->getWorld()->setBlock($this->pos, $ev->getNewState());
} }
} }
} }

View File

@ -39,7 +39,7 @@ class Note extends Opaque{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileNote){ if($tile instanceof TileNote){
$this->pitch = $tile->getPitch(); $this->pitch = $tile->getPitch();
}else{ }else{
@ -49,7 +49,7 @@ class Note extends Opaque{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
assert($tile instanceof TileNote); assert($tile instanceof TileNote);
$tile->setPitch($this->pitch); $tile->setPitch($this->pitch);
} }

View File

@ -41,7 +41,7 @@ class RedMushroom extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -72,7 +72,7 @@ class RedstoneComparator extends Flowable{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof Comparator){ if($tile instanceof Comparator){
$this->signalStrength = $tile->getSignalStrength(); $this->signalStrength = $tile->getSignalStrength();
} }
@ -80,7 +80,7 @@ class RedstoneComparator extends Flowable{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
assert($tile instanceof Comparator); assert($tile instanceof Comparator);
$tile->setSignalStrength($this->signalStrength); $tile->setSignalStrength($this->signalStrength);
} }
@ -160,13 +160,13 @@ class RedstoneComparator extends Flowable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->isSubtractMode = !$this->isSubtractMode; $this->isSubtractMode = !$this->isSubtractMode;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
return true; return true;
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -70,7 +70,7 @@ class RedstoneOre extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->lit){ if(!$this->lit){
$this->lit = true; $this->lit = true;
$this->getWorld()->setBlock($this, $this); //no return here - this shouldn't prevent block placement $this->pos->getWorld()->setBlock($this->pos, $this); //no return here - this shouldn't prevent block placement
} }
return false; return false;
} }
@ -78,7 +78,7 @@ class RedstoneOre extends Opaque{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->lit){ if(!$this->lit){
$this->lit = true; $this->lit = true;
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }
@ -89,7 +89,7 @@ class RedstoneOre extends Opaque{
public function onRandomTick() : void{ public function onRandomTick() : void{
if($this->lit){ if($this->lit){
$this->lit = false; $this->lit = false;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }

View File

@ -98,13 +98,13 @@ class RedstoneRepeater extends Flowable{
if(++$this->delay > 4){ if(++$this->delay > 4){
$this->delay = 1; $this->delay = 1;
} }
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
return true; return true;
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -69,7 +69,7 @@ class Sapling extends Flowable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Fertilizer){ if($item instanceof Fertilizer){
Tree::growTree($this->getWorld(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->treeType); Tree::growTree($this->pos->getWorld(), $this->pos->x, $this->pos->y, $this->pos->z, new Random(mt_rand()), $this->treeType);
$item->pop(); $item->pop();
@ -81,7 +81,7 @@ class Sapling extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ if($this->getSide(Facing::DOWN)->isTransparent()){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
@ -90,12 +90,12 @@ class Sapling extends Flowable{
} }
public function onRandomTick() : void{ public function onRandomTick() : void{
if($this->world->getFullLightAt($this->x, $this->y, $this->z) >= 8 and mt_rand(1, 7) === 1){ if($this->pos->getWorld()->getFullLightAt($this->pos->x, $this->pos->y, $this->pos->z) >= 8 and mt_rand(1, 7) === 1){
if($this->ready){ if($this->ready){
Tree::growTree($this->getWorld(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->treeType); Tree::growTree($this->pos->getWorld(), $this->pos->x, $this->pos->y, $this->pos->z, new Random(mt_rand()), $this->treeType);
}else{ }else{
$this->ready = true; $this->ready = true;
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }
} }

View File

@ -85,7 +85,7 @@ class Sign extends Transparent{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileSign){ if($tile instanceof TileSign){
$this->text = $tile->getText(); $this->text = $tile->getText();
} }
@ -93,7 +93,7 @@ class Sign extends Transparent{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
assert($tile instanceof TileSign); assert($tile instanceof TileSign);
$tile->setText($this->text); $tile->setText($this->text);
} }
@ -125,7 +125,7 @@ class Sign extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::opposite($this->facing))->getId() === BlockLegacyIds::AIR){ if($this->getSide(Facing::opposite($this->facing))->getId() === BlockLegacyIds::AIR){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
@ -162,7 +162,7 @@ class Sign extends Transparent{
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->text = clone $ev->getNewText(); $this->text = clone $ev->getNewText();
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
return true; return true;
} }

View File

@ -67,7 +67,7 @@ class Skull extends Flowable{
public function readStateFromWorld() : void{ public function readStateFromWorld() : void{
parent::readStateFromWorld(); parent::readStateFromWorld();
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
if($tile instanceof TileSkull){ if($tile instanceof TileSkull){
$this->skullType = $tile->getSkullType(); $this->skullType = $tile->getSkullType();
$this->rotation = $tile->getRotation(); $this->rotation = $tile->getRotation();
@ -77,7 +77,7 @@ class Skull extends Flowable{
public function writeStateToWorld() : void{ public function writeStateToWorld() : void{
parent::writeStateToWorld(); parent::writeStateToWorld();
//extra block properties storage hack //extra block properties storage hack
$tile = $this->world->getTile($this); $tile = $this->pos->getWorld()->getTile($this->pos);
assert($tile instanceof TileSkull); assert($tile instanceof TileSkull);
$tile->setRotation($this->rotation); $tile->setRotation($this->rotation);
$tile->setSkullType($this->skullType); $tile->setSkullType($this->skullType);

View File

@ -88,8 +88,8 @@ class SnowLayer extends Flowable implements Fallable{
} }
public function onRandomTick() : void{ public function onRandomTick() : void{
if($this->world->getBlockLightAt($this->x, $this->y, $this->z) >= 12){ if($this->pos->getWorld()->getBlockLightAt($this->pos->x, $this->pos->y, $this->pos->z) >= 12){
$this->getWorld()->setBlock($this, VanillaBlocks::AIR(), false); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::AIR(), false);
} }
} }

View File

@ -45,7 +45,7 @@ abstract class Stem extends Crops{
$ev = new BlockGrowEvent($this, $block); $ev = new BlockGrowEvent($this, $block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getWorld()->setBlock($this, $ev->getNewState()); $this->pos->getWorld()->setBlock($this->pos, $ev->getNewState());
} }
}else{ }else{
$grow = $this->getPlant(); $grow = $this->getPlant();
@ -61,7 +61,7 @@ abstract class Stem extends Crops{
$ev = new BlockGrowEvent($side, $grow); $ev = new BlockGrowEvent($side, $grow);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getWorld()->setBlock($side, $ev->getNewState()); $this->pos->getWorld()->setBlock($side->pos, $ev->getNewState());
} }
} }
} }

View File

@ -57,20 +57,20 @@ class Sugarcane extends Flowable{
if($item instanceof Fertilizer){ if($item instanceof Fertilizer){
if(!$this->getSide(Facing::DOWN)->isSameType($this)){ if(!$this->getSide(Facing::DOWN)->isSameType($this)){
for($y = 1; $y < 3; ++$y){ for($y = 1; $y < 3; ++$y){
$b = $this->getWorld()->getBlockAt($this->x, $this->y + $y, $this->z); $b = $this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + $y, $this->pos->z);
if($b->getId() === BlockLegacyIds::AIR){ if($b->getId() === BlockLegacyIds::AIR){
$ev = new BlockGrowEvent($b, VanillaBlocks::SUGARCANE()); $ev = new BlockGrowEvent($b, VanillaBlocks::SUGARCANE());
$ev->call(); $ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){
break; break;
} }
$this->getWorld()->setBlock($b, $ev->getNewState()); $this->pos->getWorld()->setBlock($b->pos, $ev->getNewState());
}else{ }else{
break; break;
} }
} }
$this->age = 0; $this->age = 0;
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
$item->pop(); $item->pop();
@ -84,7 +84,7 @@ class Sugarcane extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN); $down = $this->getSide(Facing::DOWN);
if($down->isTransparent() and !$down->isSameType($this)){ if($down->isTransparent() and !$down->isSameType($this)){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
@ -96,17 +96,17 @@ class Sugarcane extends Flowable{
if(!$this->getSide(Facing::DOWN)->isSameType($this)){ if(!$this->getSide(Facing::DOWN)->isSameType($this)){
if($this->age === 15){ if($this->age === 15){
for($y = 1; $y < 3; ++$y){ for($y = 1; $y < 3; ++$y){
$b = $this->getWorld()->getBlockAt($this->x, $this->y + $y, $this->z); $b = $this->pos->getWorld()->getBlockAt($this->pos->x, $this->pos->y + $y, $this->pos->z);
if($b->getId() === BlockLegacyIds::AIR){ if($b->getId() === BlockLegacyIds::AIR){
$this->getWorld()->setBlock($b, VanillaBlocks::SUGARCANE()); $this->pos->getWorld()->setBlock($b->pos, VanillaBlocks::SUGARCANE());
break; break;
} }
} }
$this->age = 0; $this->age = 0;
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
}else{ }else{
++$this->age; ++$this->age;
$this->getWorld()->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }
} }

View File

@ -90,14 +90,14 @@ class TNT extends Opaque{
} }
public function ignite(int $fuse = 80) : void{ public function ignite(int $fuse = 80) : void{
$this->getWorld()->setBlock($this, VanillaBlocks::AIR()); $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::AIR());
$mot = (new Random())->nextSignedFloat() * M_PI * 2; $mot = (new Random())->nextSignedFloat() * M_PI * 2;
$nbt = EntityFactory::createBaseNBT($this->add(0.5, 0, 0.5), new Vector3(-sin($mot) * 0.02, 0.2, -cos($mot) * 0.02)); $nbt = EntityFactory::createBaseNBT($this->pos->add(0.5, 0, 0.5), new Vector3(-sin($mot) * 0.02, 0.2, -cos($mot) * 0.02));
$nbt->setShort("Fuse", $fuse); $nbt->setShort("Fuse", $fuse);
/** @var PrimedTNT $tnt */ /** @var PrimedTNT $tnt */
$tnt = EntityFactory::create(PrimedTNT::class, $this->getWorld(), $nbt); $tnt = EntityFactory::create(PrimedTNT::class, $this->pos->getWorld(), $nbt);
$tnt->spawnToAll(); $tnt->spawnToAll();
} }

View File

@ -52,7 +52,7 @@ class TallGrass extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){ //Replace with common break method if($this->getSide(Facing::DOWN)->isTransparent()){ //Replace with common break method
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -60,7 +60,7 @@ class Torch extends Flowable{
$face = Facing::opposite($this->facing); $face = Facing::opposite($this->facing);
if($this->getSide($face)->isTransparent() and !($face === Facing::DOWN and ($below->getId() === BlockLegacyIds::FENCE or $below->getId() === BlockLegacyIds::COBBLESTONE_WALL))){ if($this->getSide($face)->isTransparent() and !($face === Facing::DOWN and ($below->getId() === BlockLegacyIds::FENCE or $below->getId() === BlockLegacyIds::COBBLESTONE_WALL))){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }

View File

@ -74,8 +74,8 @@ class Trapdoor extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->open = !$this->open; $this->open = !$this->open;
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
$this->world->addSound($this, new DoorSound()); $this->pos->getWorld()->addSound($this->pos, new DoorSound());
return true; return true;
} }
} }

View File

@ -128,9 +128,9 @@ class Vine extends Flowable{
if($changed){ if($changed){
if(empty($this->faces)){ if(empty($this->faces)){
$this->world->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
}else{ }else{
$this->world->setBlock($this, $this); $this->pos->getWorld()->setBlock($this->pos, $this);
} }
} }
} }

View File

@ -53,7 +53,7 @@ class WaterLily extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!($this->getSide(Facing::DOWN) instanceof Water)){ if(!($this->getSide(Facing::DOWN) instanceof Water)){
$this->getWorld()->useBreakOn($this); $this->pos->getWorld()->useBreakOn($this->pos);
} }
} }
} }

View File

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

View File

@ -133,7 +133,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, $block); $this->getWorld()->setBlock($block->getPos(), $block);
} }
if($this->remainingFuelTime > 0 and $ev->isBurning()){ if($this->remainingFuelTime > 0 and $ev->isBurning()){
@ -196,7 +196,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, $block); $this->getWorld()->setBlock($block->getPos(), $block);
} }
$this->remainingFuelTime = $this->cookTime = $this->maxFuelTime = 0; $this->remainingFuelTime = $this->cookTime = $this->maxFuelTime = 0;
} }

View File

@ -39,14 +39,14 @@ use pocketmine\world\Position;
*/ */
trait FallableTrait{ trait FallableTrait{
abstract protected function asPosition() : Position; abstract protected function getPos() : Position;
abstract protected function getId() : int; abstract protected function getId() : int;
abstract protected function getMeta() : int; abstract protected function getMeta() : int;
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$pos = $this->asPosition(); $pos = $this->getPos();
$down = $pos->world->getBlock($pos->getSide(Facing::DOWN)); $down = $pos->world->getBlock($pos->getSide(Facing::DOWN));
if($down->getId() === BlockLegacyIds::AIR or $down instanceof Liquid or $down instanceof Fire){ if($down->getId() === BlockLegacyIds::AIR or $down instanceof Liquid or $down instanceof Fire){
$pos->world->setBlock($pos, VanillaBlocks::AIR()); $pos->world->setBlock($pos, VanillaBlocks::AIR());

View File

@ -1180,10 +1180,10 @@ abstract class Entity extends Location{
} }
public function isUnderwater() : bool{ public function isUnderwater() : bool{
$block = $this->world->getBlockAt((int) floor($this->x), (int) floor($y = ($this->y + $this->getEyeHeight())), (int) floor($this->z)); $block = $this->world->getBlockAt((int) floor($this->x), $blockY = (int) floor($y = ($this->y + $this->getEyeHeight())), (int) floor($this->z));
if($block instanceof Water){ if($block instanceof Water){
$f = ($block->y + 1) - ($block->getFluidHeightPercent() - 0.1111111); $f = ($blockY + 1) - ($block->getFluidHeightPercent() - 0.1111111);
return $y < $f; return $y < $f;
} }

View File

@ -40,7 +40,8 @@ class EnderPearl extends Throwable{
protected function calculateInterceptWithBlock(Block $block, Vector3 $start, Vector3 $end) : ?RayTraceResult{ protected function calculateInterceptWithBlock(Block $block, Vector3 $start, Vector3 $end) : ?RayTraceResult{
if($block->getId() !== BlockLegacyIds::AIR and empty($block->getCollisionBoxes())){ if($block->getId() !== BlockLegacyIds::AIR and empty($block->getCollisionBoxes())){
//TODO: remove this once block collision boxes are fixed properly //TODO: remove this once block collision boxes are fixed properly
return AxisAlignedBB::one()->offset($block->x, $block->y, $block->z)->calculateIntercept($start, $end); $pos = $block->getPos();
return AxisAlignedBB::one()->offset($pos->x, $pos->y, $pos->z)->calculateIntercept($start, $end);
} }
return parent::calculateInterceptWithBlock($block, $start, $end); return parent::calculateInterceptWithBlock($block, $start, $end);

View File

@ -146,9 +146,10 @@ abstract class Projectile extends Entity{
$nbt->setDouble("damage", $this->damage); $nbt->setDouble("damage", $this->damage);
if($this->blockHit !== null){ if($this->blockHit !== null){
$nbt->setInt("tileX", $this->blockHit->x); $pos = $this->blockHit->getPos();
$nbt->setInt("tileY", $this->blockHit->y); $nbt->setInt("tileX", $pos->x);
$nbt->setInt("tileZ", $this->blockHit->z); $nbt->setInt("tileY", $pos->y);
$nbt->setInt("tileZ", $pos->z);
//we intentionally use different ones to PC because we don't have stringy IDs //we intentionally use different ones to PC because we don't have stringy IDs
$nbt->setInt("blockId", $this->blockHit->getId()); $nbt->setInt("blockId", $this->blockHit->getId());
@ -163,7 +164,7 @@ abstract class Projectile extends Entity{
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->blockHit !== null and $this->world->isInLoadedTerrain($this->blockHit) and !$this->blockHit->isSameState($this->world->getBlock($this->blockHit))){ if($this->blockHit !== null and $this->world->isInLoadedTerrain($this->blockHit->getPos()) and !$this->blockHit->isSameState($this->world->getBlock($this->blockHit->getPos()))){
$this->blockHit = null; $this->blockHit = null;
} }

View File

@ -129,11 +129,11 @@ class SplashPotion extends Throwable{
$blockIn = $event->getBlockHit()->getSide($event->getRayTraceResult()->getHitFace()); $blockIn = $event->getBlockHit()->getSide($event->getRayTraceResult()->getHitFace());
if($blockIn->getId() === BlockLegacyIds::FIRE){ if($blockIn->getId() === BlockLegacyIds::FIRE){
$this->world->setBlock($blockIn, VanillaBlocks::AIR()); $this->world->setBlock($blockIn->getPos(), VanillaBlocks::AIR());
} }
foreach($blockIn->getHorizontalSides() as $horizontalSide){ foreach($blockIn->getHorizontalSides() as $horizontalSide){
if($horizontalSide->getId() === BlockLegacyIds::FIRE){ if($horizontalSide->getId() === BlockLegacyIds::FIRE){
$this->world->setBlock($horizontalSide, VanillaBlocks::AIR()); $this->world->setBlock($horizontalSide->getPos(), VanillaBlocks::AIR());
} }
} }
} }

View File

@ -46,8 +46,8 @@ class Bucket extends Item{
$ev = new PlayerBucketFillEvent($player, $blockReplace, $face, $this, $resultItem); $ev = new PlayerBucketFillEvent($player, $blockReplace, $face, $this, $resultItem);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$player->getWorld()->setBlock($blockClicked, VanillaBlocks::AIR()); $player->getWorld()->setBlock($blockClicked->getPos(), VanillaBlocks::AIR());
$player->getWorld()->addSound($blockClicked->add(0.5, 0.5, 0.5), $blockClicked->getBucketFillSound()); $player->getWorld()->addSound($blockClicked->getPos()->add(0.5, 0.5, 0.5), $blockClicked->getBucketFillSound());
if($player->hasFiniteResources()){ if($player->hasFiniteResources()){
if($stack->getCount() === 0){ if($stack->getCount() === 0){
$player->getInventory()->setItemInHand($ev->getItem()); $player->getInventory()->setItemInHand($ev->getItem());

View File

@ -37,8 +37,8 @@ class FlintSteel extends Tool{
if($blockReplace->getId() === BlockLegacyIds::AIR){ if($blockReplace->getId() === BlockLegacyIds::AIR){
$world = $player->getWorld(); $world = $player->getWorld();
assert($world !== null); assert($world !== null);
$world->setBlock($blockReplace, VanillaBlocks::FIRE()); $world->setBlock($blockReplace->getPos(), VanillaBlocks::FIRE());
$world->addSound($blockReplace->add(0.5, 0.5, 0.5), new FlintSteelSound()); $world->addSound($blockReplace->getPos()->add(0.5, 0.5, 0.5), new FlintSteelSound());
$this->applyDamage(1); $this->applyDamage(1);

View File

@ -63,8 +63,8 @@ class LiquidBucket extends Item{
$ev = new PlayerBucketEmptyEvent($player, $blockReplace, $face, $this, VanillaItems::BUCKET()); $ev = new PlayerBucketEmptyEvent($player, $blockReplace, $face, $this, VanillaItems::BUCKET());
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$player->getWorld()->setBlock($blockReplace, $resultBlock->getFlowingForm()); $player->getWorld()->setBlock($blockReplace->getPos(), $resultBlock->getFlowingForm());
$player->getWorld()->addSound($blockReplace->add(0.5, 0.5, 0.5), $resultBlock->getBucketEmptySound()); $player->getWorld()->addSound($blockReplace->getPos()->add(0.5, 0.5, 0.5), $resultBlock->getBucketEmptySound());
if($player->hasFiniteResources()){ if($player->hasFiniteResources()){
$player->getInventory()->setItemInHand($ev->getItem()); $player->getInventory()->setItemInHand($ev->getItem());

View File

@ -49,7 +49,7 @@ class PaintingItem extends Item{
continue; continue;
} }
if(Painting::canFit($player->getWorld(), $blockReplace, $face, true, $motive)){ if(Painting::canFit($player->getWorld(), $blockReplace->getPos(), $face, true, $motive)){
if($currentTotalDimension > $totalDimension){ if($currentTotalDimension > $totalDimension){
$totalDimension = $currentTotalDimension; $totalDimension = $currentTotalDimension;
/* /*
@ -83,19 +83,21 @@ class PaintingItem extends Item{
return ItemUseResult::NONE(); return ItemUseResult::NONE();
} }
$nbt = EntityFactory::createBaseNBT($blockReplace, null, $direction * 90, 0); $replacePos = $blockReplace->getPos();
$clickedPos = $blockClicked->getPos();
$nbt = EntityFactory::createBaseNBT($replacePos, null, $direction * 90, 0);
$nbt->setByte("Direction", $direction); $nbt->setByte("Direction", $direction);
$nbt->setString("Motive", $motive->getName()); $nbt->setString("Motive", $motive->getName());
$nbt->setInt("TileX", $blockClicked->getFloorX()); $nbt->setInt("TileX", $clickedPos->getFloorX());
$nbt->setInt("TileY", $blockClicked->getFloorY()); $nbt->setInt("TileY", $clickedPos->getFloorY());
$nbt->setInt("TileZ", $blockClicked->getFloorZ()); $nbt->setInt("TileZ", $clickedPos->getFloorZ());
/** @var Painting $entity */ /** @var Painting $entity */
$entity = EntityFactory::create(Painting::class, $blockReplace->getWorld(), $nbt); $entity = EntityFactory::create(Painting::class, $replacePos->getWorld(), $nbt);
$this->pop(); $this->pop();
$entity->spawnToAll(); $entity->spawnToAll();
$player->getWorld()->addSound($blockReplace->add(0.5, 0.5, 0.5), new PaintingPlaceSound()); $player->getWorld()->addSound($replacePos->add(0.5, 0.5, 0.5), new PaintingPlaceSound());
return ItemUseResult::SUCCESS(); return ItemUseResult::SUCCESS();
} }
} }

View File

@ -52,7 +52,7 @@ class SpawnEgg extends Item{
} }
public function onActivate(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{ public function onActivate(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
$nbt = EntityFactory::createBaseNBT($blockReplace->add(0.5, 0, 0.5), null, lcg_value() * 360, 0); $nbt = EntityFactory::createBaseNBT($blockReplace->getPos()->add(0.5, 0, 0.5), null, lcg_value() * 360, 0);
if($this->hasCustomName()){ if($this->hasCustomName()){
$nbt->setString("CustomName", $this->getCustomName()); $nbt->setString("CustomName", $this->getCustomName());

View File

@ -532,7 +532,7 @@ class InGamePacketHandler extends PacketHandler{
try{ try{
if(!$block->updateText($this->player, $text)){ if(!$block->updateText($this->player, $text)){
$this->player->getWorld()->sendBlocks([$this->player], [$block]); $this->player->getWorld()->sendBlocks([$this->player], [$pos]);
} }
}catch(\UnexpectedValueException $e){ }catch(\UnexpectedValueException $e){
throw new BadPacketException($e->getMessage(), 0, $e); throw new BadPacketException($e->getMessage(), 0, $e);

View File

@ -1696,7 +1696,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
$block = $target->getSide($face); $block = $target->getSide($face);
if($block->getId() === BlockLegacyIds::FIRE){ if($block->getId() === BlockLegacyIds::FIRE){
$this->world->setBlock($block, VanillaBlocks::AIR()); $this->world->setBlock($block->getPos(), VanillaBlocks::AIR());
return true; return true;
} }

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\world; namespace pocketmine\world;
use pocketmine\block\Block;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\world\format\Chunk; use pocketmine\world\format\Chunk;
@ -74,7 +73,7 @@ interface ChunkListener{
/** /**
* This method will be called when a block changes in a registered chunk * This method will be called when a block changes in a registered chunk
* *
* @param Block|Vector3 $block * @param Vector3 $block
*/ */
public function onBlockChanged(Vector3 $block) : void; public function onBlockChanged(Vector3 $block) : void;
} }

View File

@ -776,7 +776,7 @@ class World implements ChunkManager{
$ev = new BlockUpdateEvent($block); $ev = new BlockUpdateEvent($block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
foreach($this->getNearbyEntities(AxisAlignedBB::one()->offset($block->x, $block->y, $block->z)) as $entity){ foreach($this->getNearbyEntities(AxisAlignedBB::one()->offset($x, $y, $z)) as $entity){
$entity->onNearbyBlockChange(); $entity->onNearbyBlockChange();
} }
$block->onNearbyBlockChange(); $block->onNearbyBlockChange();
@ -896,12 +896,8 @@ class World implements ChunkManager{
throw new \TypeError("Expected Vector3 in blocks array, got " . (is_object($b) ? get_class($b) : gettype($b))); throw new \TypeError("Expected Vector3 in blocks array, got " . (is_object($b) ? get_class($b) : gettype($b)));
} }
if($b instanceof Block){ $fullBlock = $this->getBlockAt($b->x, $b->y, $b->z);
$packets[] = UpdateBlockPacket::create($b->x, $b->y, $b->z, $b->getRuntimeId()); $packets[] = UpdateBlockPacket::create($b->x, $b->y, $b->z, $fullBlock->getRuntimeId());
}else{
$fullBlock = $this->getFullBlock($b->x, $b->y, $b->z);
$packets[] = UpdateBlockPacket::create($b->x, $b->y, $b->z, RuntimeBlockMapping::toStaticRuntimeId($fullBlock >> 4, $fullBlock & 0xf));
}
$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){
@ -1125,19 +1121,15 @@ class World implements ChunkManager{
} }
/** /**
* @param Vector3 $pos * @param Block $pos
* *
* @return bool * @return bool
*/ */
public function isFullBlock(Vector3 $pos) : bool{ public function isFullBlock(Block $pos) : bool{
if($pos instanceof Block){
if($pos->isSolid()){ if($pos->isSolid()){
return true; return true;
} }
$bb = $pos->getBoundingBox(); $bb = $pos->getBoundingBox();
}else{
$bb = $this->getBlock($pos)->getBoundingBox();
}
return $bb !== null and $bb->getAverageEdgeLength() >= 1; return $bb !== null and $bb->getAverageEdgeLength() >= 1;
} }
@ -1489,6 +1481,7 @@ class World implements ChunkManager{
$block->position($this, $x, $y, $z); $block->position($this, $x, $y, $z);
$block->writeStateToWorld(); $block->writeStateToWorld();
$pos = $block->getPos();
$chunkHash = World::chunkHash($x >> 4, $z >> 4); $chunkHash = World::chunkHash($x >> 4, $z >> 4);
$relativeBlockHash = World::chunkBlockHash($x, $y, $z); $relativeBlockHash = World::chunkBlockHash($x, $y, $z);
@ -1498,18 +1491,18 @@ class World implements ChunkManager{
if(!isset($this->changedBlocks[$chunkHash])){ if(!isset($this->changedBlocks[$chunkHash])){
$this->changedBlocks[$chunkHash] = []; $this->changedBlocks[$chunkHash] = [];
} }
$this->changedBlocks[$chunkHash][$relativeBlockHash] = $block; $this->changedBlocks[$chunkHash][$relativeBlockHash] = $pos;
foreach($this->getChunkListeners($x >> 4, $z >> 4) as $listener){ foreach($this->getChunkListeners($x >> 4, $z >> 4) as $listener){
$listener->onBlockChanged($block); $listener->onBlockChanged($pos);
} }
if($update){ if($update){
if($oldBlock->getLightFilter() !== $block->getLightFilter() or $oldBlock->getLightLevel() !== $block->getLightLevel()){ if($oldBlock->getLightFilter() !== $block->getLightFilter() or $oldBlock->getLightLevel() !== $block->getLightLevel()){
$this->updateAllLight($block); $this->updateAllLight($pos);
} }
$this->tryAddToNeighbourUpdateQueue($block); $this->tryAddToNeighbourUpdateQueue($pos);
foreach($block->sides() as $side){ foreach($pos->sides() as $side){
$this->tryAddToNeighbourUpdateQueue($side); $this->tryAddToNeighbourUpdateQueue($side);
} }
} }
@ -1585,6 +1578,7 @@ class World implements ChunkManager{
* @return bool * @return bool
*/ */
public function useBreakOn(Vector3 $vector, Item &$item = null, ?Player $player = null, bool $createParticles = false) : bool{ public function useBreakOn(Vector3 $vector, Item &$item = null, ?Player $player = null, bool $createParticles = false) : bool{
$vector = $vector->floor();
$target = $this->getBlock($vector); $target = $this->getBlock($vector);
$affectedBlocks = $target->getAffectedBlocks(); $affectedBlocks = $target->getAffectedBlocks();
@ -1641,7 +1635,7 @@ class World implements ChunkManager{
$item->onDestroyBlock($target); $item->onDestroyBlock($target);
if(!empty($drops)){ if(!empty($drops)){
$dropPos = $target->add(0.5, 0.5, 0.5); $dropPos = $vector->add(0.5, 0.5, 0.5);
foreach($drops as $drop){ foreach($drops as $drop){
if(!$drop->isNull()){ if(!$drop->isNull()){
$this->dropItem($dropPos, $drop); $this->dropItem($dropPos, $drop);
@ -1650,7 +1644,7 @@ class World implements ChunkManager{
} }
if($xpDrop > 0){ if($xpDrop > 0){
$this->dropExperience($target->add(0.5, 0.5, 0.5), $xpDrop); $this->dropExperience($vector->add(0.5, 0.5, 0.5), $xpDrop);
} }
return true; return true;
@ -1658,12 +1652,12 @@ class World implements ChunkManager{
private function destroyBlockInternal(Block $target, Item $item, ?Player $player = null, bool $createParticles = false) : void{ private function destroyBlockInternal(Block $target, Item $item, ?Player $player = null, bool $createParticles = false) : void{
if($createParticles){ if($createParticles){
$this->addParticle($target->add(0.5, 0.5, 0.5), new DestroyBlockParticle($target)); $this->addParticle($target->getPos()->add(0.5, 0.5, 0.5), new DestroyBlockParticle($target));
} }
$target->onBreak($item, $player); $target->onBreak($item, $player);
$tile = $this->getTile($target); $tile = $this->getTile($target->getPos());
if($tile !== null){ if($tile !== null){
$tile->onBlockDestroyed(); $tile->onBlockDestroyed();
} }
@ -1689,7 +1683,7 @@ class World implements ChunkManager{
$clickVector = new Vector3(0.0, 0.0, 0.0); $clickVector = new Vector3(0.0, 0.0, 0.0);
} }
if(!$this->isInWorld($blockReplace->x, $blockReplace->y, $blockReplace->z)){ if(!$this->isInWorld($blockReplace->getPos()->x, $blockReplace->getPos()->y, $blockReplace->getPos()->z)){
//TODO: build height limit messages for custom world heights and mcregion cap //TODO: build height limit messages for custom world heights and mcregion cap
return false; return false;
} }
@ -1721,14 +1715,14 @@ class World implements ChunkManager{
if($item->canBePlaced()){ if($item->canBePlaced()){
$hand = $item->getBlock(); $hand = $item->getBlock();
$hand->position($this, $blockReplace->x, $blockReplace->y, $blockReplace->z); $hand->position($this, $blockReplace->getPos()->x, $blockReplace->getPos()->y, $blockReplace->getPos()->z);
}else{ }else{
return false; return false;
} }
if($hand->canBePlacedAt($blockClicked, $clickVector, $face, true)){ if($hand->canBePlacedAt($blockClicked, $clickVector, $face, true)){
$blockReplace = $blockClicked; $blockReplace = $blockClicked;
$hand->position($this, $blockReplace->x, $blockReplace->y, $blockReplace->z); $hand->position($this, $blockReplace->getPos()->x, $blockReplace->getPos()->y, $blockReplace->getPos()->z);
}elseif(!$hand->canBePlacedAt($blockReplace, $clickVector, $face, false)){ }elseif(!$hand->canBePlacedAt($blockReplace, $clickVector, $face, false)){
return false; return false;
} }
@ -1785,7 +1779,7 @@ class World implements ChunkManager{
} }
if($playSound){ if($playSound){
$this->addSound($hand, new BlockPlaceSound($hand)); $this->addSound($hand->getPos(), new BlockPlaceSound($hand));
} }
$item->pop(); $item->pop();