Position: add getLevelNonNull()

this allows assuming that a position has a valid world in places where it's never expected to not be valid. Since this is the vast majority of usages, it eliminates a lot of possible null-pointer warnings given by static analysers.
TODO: Consider whether we can make Position->getLevel/World use this behaviour out of the box in the next major version.
This commit is contained in:
Dylan K. Taylor 2020-04-14 11:08:37 +01:00
parent 6e08b622b3
commit a2543ff80d
76 changed files with 229 additions and 183 deletions

View File

@ -1207,7 +1207,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
if(!($pos instanceof Position)){ if(!($pos instanceof Position)){
$level = $this->level; $level = $this->level;
}else{ }else{
$level = $pos->getLevel(); $level = $pos->getLevelNonNull();
} }
$this->spawnPosition = new Position($pos->x, $pos->y, $pos->z, $level); $this->spawnPosition = new Position($pos->x, $pos->y, $pos->z, $level);
$pk = new SetSpawnPositionPacket(); $pk = new SetSpawnPositionPacket();
@ -2244,7 +2244,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
public function handleLevelSoundEvent(LevelSoundEventPacket $packet) : bool{ public function handleLevelSoundEvent(LevelSoundEventPacket $packet) : bool{
//TODO: add events so plugins can change this //TODO: add events so plugins can change this
$this->getLevel()->broadcastPacketToViewers($this, $packet); $this->getLevelNonNull()->broadcastPacketToViewers($this, $packet);
return true; return true;
} }
@ -2706,7 +2706,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$item = $block->getPickedItem(); $item = $block->getPickedItem();
if($packet->addUserData){ if($packet->addUserData){
$tile = $this->getLevel()->getTile($block); $tile = $this->getLevelNonNull()->getTile($block);
if($tile instanceof Tile){ if($tile instanceof Tile){
$nbt = $tile->getCleanedNBT(); $nbt = $tile->getCleanedNBT();
if($nbt instanceof CompoundTag){ if($nbt instanceof CompoundTag){
@ -3583,7 +3583,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
} }
if($this->hasValidSpawnPosition()){ if($this->hasValidSpawnPosition()){
$this->namedtag->setString("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName()); $this->namedtag->setString("SpawnLevel", $this->spawnPosition->getLevelNonNull()->getFolderName());
$this->namedtag->setInt("SpawnX", $this->spawnPosition->getFloorX()); $this->namedtag->setInt("SpawnX", $this->spawnPosition->getFloorX());
$this->namedtag->setInt("SpawnY", $this->spawnPosition->getFloorY()); $this->namedtag->setInt("SpawnY", $this->spawnPosition->getFloorY());
$this->namedtag->setInt("SpawnZ", $this->spawnPosition->getFloorZ()); $this->namedtag->setInt("SpawnZ", $this->spawnPosition->getFloorZ());
@ -3666,7 +3666,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$ev = new PlayerRespawnEvent($this, $this->getSpawn()); $ev = new PlayerRespawnEvent($this, $this->getSpawn());
$ev->call(); $ev->call();
$realSpawn = Position::fromObject($ev->getRespawnPosition()->add(0.5, 0, 0.5), $ev->getRespawnPosition()->getLevel()); $realSpawn = Position::fromObject($ev->getRespawnPosition()->add(0.5, 0, 0.5), $ev->getRespawnPosition()->getLevelNonNull());
$this->teleport($realSpawn); $this->teleport($realSpawn);
$this->setSprinting(false); $this->setSprinting(false);

View File

@ -110,6 +110,6 @@ class Anvil extends Fallable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03; $direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
$this->meta = $this->getVariant() | $direction; $this->meta = $this->getVariant() | $direction;
return $this->getLevel()->setBlock($blockReplace, $this, true, true); return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
} }
} }

View File

@ -91,7 +91,7 @@ abstract class BaseRail extends Flowable{
} }
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if(!$blockReplace->getSide(Vector3::SIDE_DOWN)->isTransparent() and $this->getLevel()->setBlock($blockReplace, $this, true, true)){ if(!$blockReplace->getSide(Vector3::SIDE_DOWN)->isTransparent() and $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true)){
$this->tryReconnect(); $this->tryReconnect();
return true; return true;
} }
@ -279,7 +279,7 @@ abstract class BaseRail extends Flowable{
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent() $this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
)){ )){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -83,7 +83,7 @@ class Bed extends Transparent{
$this->meta &= ~self::BITFLAG_OCCUPIED; $this->meta &= ~self::BITFLAG_OCCUPIED;
} }
$this->getLevel()->setBlock($this, $this, false, false); $this->getLevelNonNull()->setBlock($this, $this, false, false);
if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){ if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){
$other->setOccupied($occupied); $other->setOccupied($occupied);
@ -137,7 +137,7 @@ class Bed extends Transparent{
return true; return true;
} }
$time = $this->getLevel()->getTimeOfDay(); $time = $this->getLevelNonNull()->getTimeOfDay();
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE); $isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
@ -168,11 +168,11 @@ class Bed extends Transparent{
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03; $meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
$next = $this->getSide(self::getOtherHalfSide($meta)); $next = $this->getSide(self::getOtherHalfSide($meta));
if($next->canBeReplaced() and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){ if($next->canBeReplaced() and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true); $this->getLevelNonNull()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::BED, $this->getLevelNonNull(), TileBed::createNBT($this, $face, $item, $player));
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player)); Tile::createTile(Tile::BED, $this->getLevelNonNull(), TileBed::createNBT($next, $face, $item, $player));
return true; return true;
} }
@ -194,7 +194,7 @@ class Bed extends Transparent{
} }
private function getItem() : Item{ private function getItem() : Item{
$tile = $this->getLevel()->getTile($this); $tile = $this->getLevelNonNull()->getTile($this);
if($tile instanceof TileBed){ if($tile instanceof TileBed){
return ItemFactory::get($this->getItemId(), $tile->getColor()); return ItemFactory::get($this->getItemId(), $tile->getColor());
} }

View File

@ -154,7 +154,7 @@ class Block extends Position implements BlockIds, Metadatable{
* Places the Block, using block space and block target, and side. Returns if the block has been placed. * Places the Block, using block space and block target, and side. Returns if the block has been placed.
*/ */
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, $this, true, true); return $this->getLevelNonNull()->setBlock($this, $this, true, true);
} }
/** /**
@ -204,7 +204,7 @@ class Block extends Position implements BlockIds, Metadatable{
* Do the actions needed so the block is broken with the Item * Do the actions needed so the block is broken with the Item
*/ */
public function onBreak(Item $item, Player $player = null) : bool{ public function onBreak(Item $item, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true); return $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
} }
/** /**
@ -479,7 +479,7 @@ class Block extends Position implements BlockIds, Metadatable{
*/ */
public function getSide(int $side, int $step = 1){ public function getSide(int $side, int $step = 1){
if($this->isValid()){ if($this->isValid()){
return $this->getLevel()->getBlock(Vector3::getSide($side, $step)); return $this->getLevelNonNull()->getBlock(Vector3::getSide($side, $step));
} }
return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step))); return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));

View File

@ -55,7 +55,7 @@ class BoneBlock extends Solid{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
return $this->getLevel()->setBlock($blockReplace, $this, true, true); return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
} }
public function getVariantBitmask() : int{ public function getVariantBitmask() : int{

View File

@ -68,18 +68,18 @@ class BurningFurnace extends Solid{
3 => 3 3 => 3
]; ];
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0]; $this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::FURNACE, $this->getLevelNonNull(), TileFurnace::createNBT($this, $face, $item, $player));
return true; return true;
} }
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$furnace = $this->getLevel()->getTile($this); $furnace = $this->getLevelNonNull()->getTile($this);
if(!($furnace instanceof TileFurnace)){ if(!($furnace instanceof TileFurnace)){
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this)); $furnace = Tile::createTile(Tile::FURNACE, $this->getLevelNonNull(), TileFurnace::createNBT($this));
if(!($furnace instanceof TileFurnace)){ if(!($furnace instanceof TileFurnace)){
return true; return true;
} }

View File

@ -72,12 +72,12 @@ class Cactus extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){ if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
}else{ }else{
for($side = 2; $side <= 5; ++$side){ for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side); $b = $this->getSide($side);
if($b->isSolid()){ if($b->isSolid()){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
break; break;
} }
} }
@ -92,23 +92,23 @@ class Cactus extends Transparent{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){ if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
if($this->meta === 0x0f){ if($this->meta === 0x0f){
for($y = 1; $y < 3; ++$y){ for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z); $b = $this->getLevelNonNull()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){ if($b->getId() === self::AIR){
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)); $ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
$ev->call(); $ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){
break; break;
} }
$this->getLevel()->setBlock($b, $ev->getNewState(), true); $this->getLevelNonNull()->setBlock($b, $ev->getNewState(), true);
}else{ }else{
break; break;
} }
} }
$this->meta = 0; $this->meta = 0;
$this->getLevel()->setBlock($this, $this); $this->getLevelNonNull()->setBlock($this, $this);
}else{ }else{
++$this->meta; ++$this->meta;
$this->getLevel()->setBlock($this, $this); $this->getLevelNonNull()->setBlock($this, $this);
} }
} }
} }
@ -121,7 +121,7 @@ class Cactus extends Transparent{
$block2 = $this->getSide(Vector3::SIDE_WEST); $block2 = $this->getSide(Vector3::SIDE_WEST);
$block3 = $this->getSide(Vector3::SIDE_EAST); $block3 = $this->getSide(Vector3::SIDE_EAST);
if(!$block0->isSolid() and !$block1->isSolid() and !$block2->isSolid() and !$block3->isSolid()){ if(!$block0->isSolid() and !$block1->isSolid() and !$block2->isSolid() and !$block3->isSolid()){
$this->getLevel()->setBlock($this, $this, true); $this->getLevelNonNull()->setBlock($this, $this, true);
return true; return true;
} }

View File

@ -66,7 +66,7 @@ class Cake extends Transparent implements FoodSource{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::AIR){ if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }
@ -76,7 +76,7 @@ class Cake extends Transparent implements FoodSource{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true);
} }
} }

View File

@ -64,7 +64,7 @@ class Carpet extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::AIR){ if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }
@ -74,7 +74,7 @@ class Carpet extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -81,7 +81,7 @@ class Chest extends Transparent{
} }
$c = $this->getSide($side); $c = $this->getSide($side);
if($c->getId() === $this->id and $c->getDamage() === $this->meta){ if($c->getId() === $this->id and $c->getDamage() === $this->meta){
$tile = $this->getLevel()->getTile($c); $tile = $this->getLevelNonNull()->getTile($c);
if($tile instanceof TileChest and !$tile->isPaired()){ if($tile instanceof TileChest and !$tile->isPaired()){
$chest = $tile; $chest = $tile;
break; break;
@ -89,8 +89,8 @@ class Chest extends Transparent{
} }
} }
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
$tile = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this, $face, $item, $player)); $tile = Tile::createTile(Tile::CHEST, $this->getLevelNonNull(), TileChest::createNBT($this, $face, $item, $player));
if($chest instanceof TileChest and $tile instanceof TileChest){ if($chest instanceof TileChest and $tile instanceof TileChest){
$chest->pairWith($tile); $chest->pairWith($tile);
@ -103,12 +103,12 @@ class Chest extends Transparent{
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$t = $this->getLevel()->getTile($this); $t = $this->getLevelNonNull()->getTile($this);
$chest = null; $chest = null;
if($t instanceof TileChest){ if($t instanceof TileChest){
$chest = $t; $chest = $t;
}else{ }else{
$chest = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this)); $chest = Tile::createTile(Tile::CHEST, $this->getLevelNonNull(), TileChest::createNBT($this));
if(!($chest instanceof TileChest)){ if(!($chest instanceof TileChest)){
return true; return true;
} }

View File

@ -33,7 +33,7 @@ abstract class Crops extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($blockReplace->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){ if($blockReplace->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }
@ -52,7 +52,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->getLevel()->setBlock($this, $ev->getNewState(), true, true); $this->getLevelNonNull()->setBlock($this, $ev->getNewState(), true, true);
} }
$item->pop(); $item->pop();
@ -65,7 +65,7 @@ abstract class Crops extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){ if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
@ -81,7 +81,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->getLevel()->setBlock($this, $ev->getNewState(), true, true); $this->getLevelNonNull()->setBlock($this, $ev->getNewState(), true, true);
} }
} }
} }

View File

@ -42,7 +42,7 @@ class Dandelion extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){ if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }
@ -52,7 +52,7 @@ class Dandelion extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -51,7 +51,7 @@ class DeadBush extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -54,9 +54,9 @@ class Dirt extends Solid{
if($item instanceof Hoe){ if($item instanceof Hoe){
$item->applyDamage(1); $item->applyDamage(1);
if($this->meta === 1){ if($this->meta === 1){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::DIRT), true);
}else{ }else{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
} }
return true; return true;

View File

@ -201,9 +201,9 @@ abstract class Door extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), false);
if($this->getSide(Vector3::SIDE_UP) instanceof Door){ if($this->getSide(Vector3::SIDE_UP) instanceof Door){
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false); $this->getLevelNonNull()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
} }
} }
} }
@ -230,8 +230,8 @@ abstract class Door extends Transparent{
} }
$this->setDamage($player->getDirection() & 0x03); $this->setDamage($player->getDirection() & 0x03);
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true); //Bottom
$this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top $this->getLevelNonNull()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
return true; return true;
} }

View File

@ -57,8 +57,8 @@ class DoublePlant extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$id = $blockReplace->getSide(Vector3::SIDE_DOWN)->getId(); $id = $blockReplace->getSide(Vector3::SIDE_DOWN)->getId();
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Vector3::SIDE_UP)->canBeReplaced()){ if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Vector3::SIDE_UP)->canBeReplaced()){
$this->getLevel()->setBlock($blockReplace, $this, false, false); $this->getLevelNonNull()->setBlock($blockReplace, $this, false, false);
$this->getLevel()->setBlock($blockReplace->getSide(Vector3::SIDE_UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false); $this->getLevelNonNull()->setBlock($blockReplace->getSide(Vector3::SIDE_UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
return true; return true;
} }
@ -85,7 +85,7 @@ class DoublePlant extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){ if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -40,9 +40,9 @@ class EnchantingTable extends Transparent{
} }
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), TileEnchantTable::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevelNonNull(), TileEnchantTable::createNBT($this, $face, $item, $player));
return true; return true;
} }

View File

@ -69,8 +69,8 @@ class EnderChest extends Chest{
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0]; $this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::ENDER_CHEST, $this->getLevelNonNull(), TileEnderChest::createNBT($this, $face, $item, $player));
return true; return true;
} }
@ -78,12 +78,12 @@ class EnderChest extends Chest{
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
if($player instanceof Player){ if($player instanceof Player){
$t = $this->getLevel()->getTile($this); $t = $this->getLevelNonNull()->getTile($this);
$enderChest = null; $enderChest = null;
if($t instanceof TileEnderChest){ if($t instanceof TileEnderChest){
$enderChest = $t; $enderChest = $t;
}else{ }else{
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this)); $enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevelNonNull(), TileEnderChest::createNBT($this));
if(!($enderChest instanceof TileEnderChest)){ if(!($enderChest instanceof TileEnderChest)){
return true; return true;
} }

View File

@ -37,7 +37,7 @@ abstract class Fallable extends Solid{
$nbt->setInt("TileID", $this->getId()); $nbt->setInt("TileID", $this->getId());
$nbt->setByte("Data", $this->getDamage()); $nbt->setByte("Data", $this->getDamage());
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt); $fall = Entity::createEntity("FallingSand", $this->getLevelNonNull(), $nbt);
if($fall !== null){ if($fall !== null){
$fall->spawnToAll(); $fall->spawnToAll();

View File

@ -69,7 +69,7 @@ class FenceGate extends Transparent{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->meta = ($player instanceof Player ? ($player->getDirection() - 1) & 0x03 : 0); $this->meta = ($player instanceof Player ? ($player->getDirection() - 1) & 0x03 : 0);
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }
@ -85,7 +85,7 @@ class FenceGate extends Transparent{
$this->meta |= (($player->getDirection() - 1) & 0x02); $this->meta |= (($player->getDirection() - 1) & 0x02);
} }
$this->getLevel()->setBlock($this, $this, true); $this->getLevelNonNull()->setBlock($this, $this, true);
$this->level->addSound(new DoorSound($this)); $this->level->addSound(new DoorSound($this));
return true; return true;
} }

View File

@ -82,7 +82,7 @@ class Fire extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){ if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true);
}else{ }else{
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40)); $this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
} }

View File

@ -62,7 +62,7 @@ class Flower extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){ if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($blockReplace, $this, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true);
return true; return true;
} }
@ -72,7 +72,7 @@ class Flower extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -62,19 +62,19 @@ class FlowerPot extends Flowable{
return false; return false;
} }
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), TileFlowerPot::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::FLOWER_POT, $this->getLevelNonNull(), TileFlowerPot::createNBT($this, $face, $item, $player));
return true; return true;
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
$pot = $this->getLevel()->getTile($this); $pot = $this->getLevelNonNull()->getTile($this);
if(!($pot instanceof TileFlowerPot)){ if(!($pot instanceof TileFlowerPot)){
return false; return false;
} }
@ -83,7 +83,7 @@ class FlowerPot extends Flowable{
} }
$this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item. $this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item.
$this->getLevel()->setBlock($this, $this, true, false); $this->getLevelNonNull()->setBlock($this, $this, true, false);
$pot->setItem($item->pop()); $pot->setItem($item->pop());
return true; return true;
@ -96,7 +96,7 @@ class FlowerPot extends Flowable{
public function getDropsForCompatibleTool(Item $item) : array{ public function getDropsForCompatibleTool(Item $item) : array{
$items = parent::getDropsForCompatibleTool($item); $items = parent::getDropsForCompatibleTool($item);
$tile = $this->getLevel()->getTile($this); $tile = $this->getLevelNonNull()->getTile($this);
if($tile instanceof TileFlowerPot){ if($tile instanceof TileFlowerPot){
$item = $tile->getItem(); $item = $tile->getItem();
if($item->getId() !== Item::AIR){ if($item->getId() !== Item::AIR){

View File

@ -53,7 +53,7 @@ class GlazedTerracotta extends Solid{
$this->meta = $faces[(~($player->getDirection() - 1)) & 0x03]; $this->meta = $faces[(~($player->getDirection() - 1)) & 0x03];
} }
return $this->getLevel()->setBlock($blockReplace, $this, true, true); return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
} }
public function getVariantBitmask() : int{ public function getVariantBitmask() : int{

View File

@ -53,6 +53,6 @@ class GlowingRedstoneOre extends RedstoneOre{
} }
public function onRandomTick() : void{ public function onRandomTick() : void{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
} }
} }

View File

@ -100,17 +100,17 @@ class Grass extends Solid{
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){
$item->pop(); $item->pop();
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2); TallGrassObject::growGrass($this->getLevelNonNull(), $this, 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->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND)); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::FARMLAND));
return true; return true;
}elseif($item instanceof Shovel and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){ }elseif($item instanceof Shovel and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
$item->applyDamage(1); $item->applyDamage(1);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GRASS_PATH)); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
return true; return true;
} }

View File

@ -46,7 +46,7 @@ class HayBale extends Solid{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -57,7 +57,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)){
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true); return $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::WATER), true);
} }
return parent::onBreak($item, $player); return parent::onBreak($item, $player);
} }

View File

@ -46,7 +46,7 @@ class ItemFrame extends Flowable{
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
$tile = $this->level->getTile($this); $tile = $this->level->getTile($this);
if(!($tile instanceof TileItemFrame)){ if(!($tile instanceof TileItemFrame)){
$tile = Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this)); $tile = Tile::createTile(Tile::ITEM_FRAME, $this->getLevelNonNull(), TileItemFrame::createNBT($this));
if(!($tile instanceof TileItemFrame)){ if(!($tile instanceof TileItemFrame)){
return true; return true;
} }
@ -88,7 +88,7 @@ class ItemFrame extends Flowable{
$this->meta = $faces[$face]; $this->meta = $faces[$face];
$this->level->setBlock($blockReplace, $this, true, true); $this->level->setBlock($blockReplace, $this, true, true);
Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::ITEM_FRAME, $this->getLevelNonNull(), TileItemFrame::createNBT($this, $face, $item, $player));
return true; return true;

View File

@ -100,7 +100,7 @@ class Ladder extends Transparent{
]; ];
if(isset($faces[$face])){ if(isset($faces[$face])){
$this->meta = $faces[$face]; $this->meta = $faces[$face];
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -115,8 +115,8 @@ class Lava extends Liquid{
} }
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$ret = $this->getLevel()->setBlock($this, $this, true, false); $ret = $this->getLevelNonNull()->setBlock($this, $this, true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($this, $this->tickRate()); $this->getLevelNonNull()->scheduleDelayedBlockUpdate($this, $this->tickRate());
return $ret; return $ret;
} }

View File

@ -139,7 +139,7 @@ class Leaves extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(($this->meta & 0b00001100) === 0){ if(($this->meta & 0b00001100) === 0){
$this->meta |= 0x08; $this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, true, false); $this->getLevelNonNull()->setBlock($this, $this, true, false);
} }
} }
@ -155,16 +155,16 @@ class Leaves extends Transparent{
$ev = new LeavesDecayEvent($this); $ev = new LeavesDecayEvent($this);
$ev->call(); $ev->call();
if($ev->isCancelled() or $this->findLog($this, $visited, 0)){ if($ev->isCancelled() or $this->findLog($this, $visited, 0)){
$this->getLevel()->setBlock($this, $this, false, false); $this->getLevelNonNull()->setBlock($this, $this, false, false);
}else{ }else{
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
} }
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->meta |= 0x04; $this->meta |= 0x04;
return $this->getLevel()->setBlock($this, $this, true); return $this->getLevelNonNull()->setBlock($this, $this, true);
} }
public function getVariantBitmask() : int{ public function getVariantBitmask() : int{

View File

@ -49,7 +49,7 @@ class MelonStem extends Crops{
$ev = new BlockGrowEvent($this, $block); $ev = new BlockGrowEvent($this, $block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true); $this->getLevelNonNull()->setBlock($this, $ev->getNewState(), true);
} }
}else{ }else{
for($side = 2; $side <= 5; ++$side){ for($side = 2; $side <= 5; ++$side){
@ -64,7 +64,7 @@ class MelonStem extends Crops{
$ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK)); $ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK));
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true); $this->getLevelNonNull()->setBlock($side, $ev->getNewState(), true);
} }
} }
} }

View File

@ -64,13 +64,13 @@ class Mycelium extends Solid{
$x = mt_rand($this->x - 1, $this->x + 1); $x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 2, $this->y + 2); $y = mt_rand($this->y - 2, $this->y + 2);
$z = mt_rand($this->z - 1, $this->z + 1); $z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockAt($x, $y, $z); $block = $this->getLevelNonNull()->getBlockAt($x, $y, $z);
if($block->getId() === Block::DIRT){ if($block->getId() === Block::DIRT){
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){ if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
$ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM)); $ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM));
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getLevel()->setBlock($block, $ev->getNewState()); $this->getLevelNonNull()->setBlock($block, $ev->getNewState());
} }
} }
} }

View File

@ -46,7 +46,7 @@ class NetherWartPlant extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::SOUL_SAND){ if($down->getId() === Block::SOUL_SAND){
$this->getLevel()->setBlock($blockReplace, $this, false, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, false, true);
return true; return true;
} }
@ -56,7 +56,7 @@ class NetherWartPlant extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){ if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
@ -71,7 +71,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->getLevel()->setBlock($this, $ev->getNewState(), false, true); $this->getLevelNonNull()->setBlock($this, $ev->getNewState(), false, true);
} }
} }
} }

View File

@ -51,7 +51,7 @@ class Pumpkin extends Solid{
if($player instanceof Player){ if($player instanceof Player){
$this->meta = ((int) $player->getDirection() + 1) % 4; $this->meta = ((int) $player->getDirection() + 1) % 4;
} }
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -49,7 +49,7 @@ class PumpkinStem extends Crops{
$ev = new BlockGrowEvent($this, $block); $ev = new BlockGrowEvent($this, $block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true); $this->getLevelNonNull()->setBlock($this, $ev->getNewState(), true);
} }
}else{ }else{
for($side = 2; $side <= 5; ++$side){ for($side = 2; $side <= 5; ++$side){
@ -64,7 +64,7 @@ class PumpkinStem extends Crops{
$ev = new BlockGrowEvent($side, BlockFactory::get(Block::PUMPKIN)); $ev = new BlockGrowEvent($side, BlockFactory::get(Block::PUMPKIN));
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true); $this->getLevelNonNull()->setBlock($side, $ev->getNewState(), true);
} }
} }
} }

View File

@ -58,7 +58,7 @@ class Quartz extends Solid{
if($this->getVariant() !== self::NORMAL){ if($this->getVariant() !== self::NORMAL){
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
} }
return $this->getLevel()->setBlock($blockReplace, $this, true, true); return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
} }
public function getToolType() : int{ public function getToolType() : int{

View File

@ -45,14 +45,14 @@ class RedMushroom extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if(!$down->isTransparent()){ if(!$down->isTransparent()){
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -47,16 +47,16 @@ class RedstoneOre extends Solid{
} }
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, $this, true, false); return $this->getLevelNonNull()->setBlock($this, $this, true, false);
} }
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta)); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
return false; //this shouldn't prevent block placement return false; //this shouldn't prevent block placement
} }
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta)); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
} }
public function getToolType() : int{ public function getToolType() : int{

View File

@ -59,7 +59,7 @@ class Sapling extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::FARMLAND){ if($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::FARMLAND){
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }
@ -70,7 +70,7 @@ class Sapling extends Flowable{
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
//TODO: change log type //TODO: change log type
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant()); Tree::growTree($this->getLevelNonNull(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant());
$item->pop(); $item->pop();
@ -82,7 +82,7 @@ class Sapling extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
@ -93,10 +93,10 @@ class Sapling extends Flowable{
public function onRandomTick() : void{ public function onRandomTick() : void{
if($this->level->getFullLightAt($this->x, $this->y, $this->z) >= 8 and mt_rand(1, 7) === 1){ if($this->level->getFullLightAt($this->x, $this->y, $this->z) >= 8 and mt_rand(1, 7) === 1){
if(($this->meta & 0x08) === 0x08){ if(($this->meta & 0x08) === 0x08){
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant()); Tree::growTree($this->getLevelNonNull(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant());
}else{ }else{
$this->meta |= 0x08; $this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, true); $this->getLevelNonNull()->setBlock($this, $this, true);
} }
} }
} }

View File

@ -62,13 +62,13 @@ class SignPost extends Transparent{
if($face === Vector3::SIDE_UP){ if($face === Vector3::SIDE_UP){
$this->meta = $player !== null ? (floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0f) : 0; $this->meta = $player !== null ? (floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0f) : 0;
$this->getLevel()->setBlock($blockReplace, $this, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true);
}else{ }else{
$this->meta = $face; $this->meta = $face;
$this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_SIGN, $this->meta), true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get(Block::WALL_SIGN, $this->meta), true);
} }
Tile::createTile(Tile::SIGN, $this->getLevel(), TileSign::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::SIGN, $this->getLevelNonNull(), TileSign::createNBT($this, $face, $item, $player));
return true; return true;
} }
@ -78,7 +78,7 @@ class SignPost extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -65,8 +65,8 @@ class Skull extends Flowable{
} }
$this->meta = $face; $this->meta = $face;
$this->getLevel()->setBlock($blockReplace, $this, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true);
Tile::createTile(Tile::SKULL, $this->getLevel(), TileSkull::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::SKULL, $this->getLevelNonNull(), TileSkull::createNBT($this, $face, $item, $player));
return true; return true;
} }

View File

@ -56,11 +56,11 @@ abstract class Slab extends Transparent{
$this->meta &= 0x07; $this->meta &= 0x07;
if($face === Vector3::SIDE_DOWN){ if($face === Vector3::SIDE_DOWN){
if($blockClicked->getId() === $this->id and ($blockClicked->getDamage() & 0x08) === 0x08 and $blockClicked->getVariant() === $this->getVariant()){ if($blockClicked->getId() === $this->id and ($blockClicked->getDamage() & 0x08) === 0x08 and $blockClicked->getVariant() === $this->getVariant()){
$this->getLevel()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); $this->getLevelNonNull()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true);
return true; return true;
}elseif($blockReplace->getId() === $this->id and $blockReplace->getVariant() === $this->getVariant()){ }elseif($blockReplace->getId() === $this->id and $blockReplace->getVariant() === $this->getVariant()){
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true);
return true; return true;
}else{ }else{
@ -68,18 +68,18 @@ abstract class Slab extends Transparent{
} }
}elseif($face === Vector3::SIDE_UP){ }elseif($face === Vector3::SIDE_UP){
if($blockClicked->getId() === $this->id and ($blockClicked->getDamage() & 0x08) === 0 and $blockClicked->getVariant() === $this->getVariant()){ if($blockClicked->getId() === $this->id and ($blockClicked->getDamage() & 0x08) === 0 and $blockClicked->getVariant() === $this->getVariant()){
$this->getLevel()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); $this->getLevelNonNull()->setBlock($blockClicked, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true);
return true; return true;
}elseif($blockReplace->getId() === $this->id and $blockReplace->getVariant() === $this->getVariant()){ }elseif($blockReplace->getId() === $this->id and $blockReplace->getVariant() === $this->getVariant()){
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true);
return true; return true;
} }
}else{ //TODO: collision }else{ //TODO: collision
if($blockReplace->getId() === $this->id){ if($blockReplace->getId() === $this->id){
if($blockReplace->getVariant() === $this->getVariant()){ if($blockReplace->getVariant() === $this->getVariant()){
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true);
return true; return true;
} }
@ -95,7 +95,7 @@ abstract class Slab extends Transparent{
if($blockReplace->getId() === $this->id and $blockClicked->getVariant() !== $this->getVariant()){ if($blockReplace->getId() === $this->id and $blockClicked->getVariant() !== $this->getVariant()){
return false; return false;
} }
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -60,7 +60,7 @@ class SnowLayer extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($blockReplace->getSide(Vector3::SIDE_DOWN)->isSolid()){ if($blockReplace->getSide(Vector3::SIDE_DOWN)->isSolid()){
//TODO: fix placement //TODO: fix placement
$this->getLevel()->setBlock($blockReplace, $this, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true);
return true; return true;
} }
@ -70,7 +70,7 @@ class SnowLayer extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid()){ if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid()){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
} }
} }
@ -80,7 +80,7 @@ class SnowLayer extends Flowable{
public function onRandomTick() : void{ public function onRandomTick() : void{
if($this->level->getBlockLightAt($this->x, $this->y, $this->z) >= 12){ if($this->level->getBlockLightAt($this->x, $this->y, $this->z) >= 12){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
} }
} }

View File

@ -93,7 +93,7 @@ abstract class Stair extends Transparent{
if(($clickVector->y > 0.5 and $face !== Vector3::SIDE_UP) or $face === Vector3::SIDE_DOWN){ if(($clickVector->y > 0.5 and $face !== Vector3::SIDE_UP) or $face === Vector3::SIDE_DOWN){
$this->meta |= 0x04; //Upside-down stairs $this->meta |= 0x04; //Upside-down stairs
} }
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -62,13 +62,13 @@ class StandingBanner extends Transparent{
if($face !== Vector3::SIDE_DOWN){ if($face !== Vector3::SIDE_DOWN){
if($face === Vector3::SIDE_UP and $player !== null){ if($face === Vector3::SIDE_UP and $player !== null){
$this->meta = floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0f; $this->meta = floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0f;
$this->getLevel()->setBlock($blockReplace, $this, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true);
}else{ }else{
$this->meta = $face; $this->meta = $face;
$this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::WALL_BANNER, $this->meta), true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get(Block::WALL_BANNER, $this->meta), true);
} }
Tile::createTile(Tile::BANNER, $this->getLevel(), TileBanner::createNBT($this, $face, $item, $player)); Tile::createTile(Tile::BANNER, $this->getLevelNonNull(), TileBanner::createNBT($this, $face, $item, $player));
return true; return true;
} }
@ -77,7 +77,7 @@ class StandingBanner extends Transparent{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -46,20 +46,20 @@ class Sugarcane extends Flowable{
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::SUGARCANE_BLOCK){ if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::SUGARCANE_BLOCK){
for($y = 1; $y < 3; ++$y){ for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z); $b = $this->getLevelNonNull()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){ if($b->getId() === self::AIR){
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::SUGARCANE_BLOCK)); $ev = new BlockGrowEvent($b, BlockFactory::get(Block::SUGARCANE_BLOCK));
$ev->call(); $ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){
break; break;
} }
$this->getLevel()->setBlock($b, $ev->getNewState(), true); $this->getLevelNonNull()->setBlock($b, $ev->getNewState(), true);
}else{ }else{
break; break;
} }
} }
$this->meta = 0; $this->meta = 0;
$this->getLevel()->setBlock($this, $this, true); $this->getLevelNonNull()->setBlock($this, $this, true);
} }
$item->pop(); $item->pop();
@ -73,7 +73,7 @@ class Sugarcane extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->isTransparent() and $down->getId() !== self::SUGARCANE_BLOCK){ if($down->isTransparent() and $down->getId() !== self::SUGARCANE_BLOCK){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
@ -85,17 +85,17 @@ class Sugarcane extends Flowable{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::SUGARCANE_BLOCK){ if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::SUGARCANE_BLOCK){
if($this->meta === 0x0F){ if($this->meta === 0x0F){
for($y = 1; $y < 3; ++$y){ for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z); $b = $this->getLevelNonNull()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){ if($b->getId() === self::AIR){
$this->getLevel()->setBlock($b, BlockFactory::get(Block::SUGARCANE_BLOCK), true); $this->getLevelNonNull()->setBlock($b, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
break; break;
} }
} }
$this->meta = 0; $this->meta = 0;
$this->getLevel()->setBlock($this, $this, true); $this->getLevelNonNull()->setBlock($this, $this, true);
}else{ }else{
++$this->meta; ++$this->meta;
$this->getLevel()->setBlock($this, $this, true); $this->getLevelNonNull()->setBlock($this, $this, true);
} }
} }
} }
@ -103,7 +103,7 @@ class Sugarcane extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN); $down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::SUGARCANE_BLOCK){ if($down->getId() === self::SUGARCANE_BLOCK){
$this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::SUGARCANE_BLOCK), true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
return true; return true;
}elseif($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::SAND){ }elseif($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::SAND){
@ -112,7 +112,7 @@ class Sugarcane extends Flowable{
$block2 = $down->getSide(Vector3::SIDE_WEST); $block2 = $down->getSide(Vector3::SIDE_WEST);
$block3 = $down->getSide(Vector3::SIDE_EAST); $block3 = $down->getSide(Vector3::SIDE_EAST);
if(($block0 instanceof Water) or ($block1 instanceof Water) or ($block2 instanceof Water) or ($block3 instanceof Water)){ if(($block0 instanceof Water) or ($block1 instanceof Water) or ($block2 instanceof Water) or ($block3 instanceof Water)){
$this->getLevel()->setBlock($blockReplace, BlockFactory::get(Block::SUGARCANE_BLOCK), true); $this->getLevelNonNull()->setBlock($blockReplace, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
return true; return true;
} }

View File

@ -78,13 +78,13 @@ class TNT extends Solid{
* @return void * @return void
*/ */
public function ignite(int $fuse = 80){ public function ignite(int $fuse = 80){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true);
$mot = (new Random())->nextSignedFloat() * M_PI * 2; $mot = (new Random())->nextSignedFloat() * M_PI * 2;
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5), new Vector3(-sin($mot) * 0.02, 0.2, -cos($mot) * 0.02)); $nbt = Entity::createBaseNBT($this->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);
$tnt = Entity::createEntity("PrimedTNT", $this->getLevel(), $nbt); $tnt = Entity::createEntity("PrimedTNT", $this->getLevelNonNull(), $nbt);
if($tnt !== null){ if($tnt !== null){
$tnt->spawnToAll(); $tnt->spawnToAll();

View File

@ -53,7 +53,7 @@ class TallGrass extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN)->getId(); $down = $this->getSide(Vector3::SIDE_DOWN)->getId();
if($down === self::GRASS or $down === self::DIRT){ if($down === self::GRASS or $down === self::DIRT){
$this->getLevel()->setBlock($blockReplace, $this, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true);
return true; return true;
} }
@ -63,7 +63,7 @@ class TallGrass extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ //Replace with common break method if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){ //Replace with common break method
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
} }
} }

View File

@ -57,7 +57,7 @@ class Torch extends Flowable{
$face = $faces[$meta] ?? Vector3::SIDE_DOWN; $face = $faces[$meta] ?? Vector3::SIDE_DOWN;
if($this->getSide($face)->isTransparent() and !($face === Vector3::SIDE_DOWN and ($below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL))){ if($this->getSide($face)->isTransparent() and !($face === Vector3::SIDE_DOWN and ($below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL))){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
@ -73,12 +73,12 @@ class Torch extends Flowable{
Vector3::SIDE_EAST => 1 Vector3::SIDE_EAST => 1
]; ];
$this->meta = $faces[$face]; $this->meta = $faces[$face];
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
}elseif(!$below->isTransparent() or $below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL){ }elseif(!$below->isTransparent() or $below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL){
$this->meta = 0; $this->meta = 0;
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -136,7 +136,7 @@ class Trapdoor extends Transparent{
if(($clickVector->y > 0.5 and $face !== self::SIDE_UP) or $face === self::SIDE_DOWN){ if(($clickVector->y > 0.5 and $face !== self::SIDE_UP) or $face === self::SIDE_DOWN){
$this->meta |= self::MASK_UPPER; //top half of block $this->meta |= self::MASK_UPPER; //top half of block
} }
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }
@ -146,7 +146,7 @@ class Trapdoor extends Transparent{
public function onActivate(Item $item, Player $player = null) : bool{ public function onActivate(Item $item, Player $player = null) : bool{
$this->meta ^= self::MASK_OPENED; $this->meta ^= self::MASK_OPENED;
$this->getLevel()->setBlock($this, $this, true); $this->getLevelNonNull()->setBlock($this, $this, true);
$this->level->addSound(new DoorSound($this)); $this->level->addSound(new DoorSound($this));
return true; return true;
} }

View File

@ -150,7 +150,7 @@ class Vine extends Flowable{
$this->meta |= $blockReplace->meta; $this->meta |= $blockReplace->meta;
} }
$this->getLevel()->setBlock($blockReplace, $this, true, true); $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
return true; return true;
} }

View File

@ -33,7 +33,7 @@ class WallBanner extends StandingBanner{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){ if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
} }

View File

@ -33,7 +33,7 @@ class WallSign extends SignPost{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){ if($this->getSide($this->meta ^ 0x01)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }
} }

View File

@ -75,8 +75,8 @@ class Water extends Liquid{
} }
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$ret = $this->getLevel()->setBlock($this, $this, true, false); $ret = $this->getLevelNonNull()->setBlock($this, $this, true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($this, $this->tickRate()); $this->getLevelNonNull()->scheduleDelayedBlockUpdate($this, $this->tickRate());
return $ret; return $ret;
} }

View File

@ -59,7 +59,7 @@ class WaterLily extends Flowable{
if($blockClicked instanceof Water){ if($blockClicked instanceof Water){
$up = $blockClicked->getSide(Vector3::SIDE_UP); $up = $blockClicked->getSide(Vector3::SIDE_UP);
if($up->getId() === Block::AIR){ if($up->getId() === Block::AIR){
$this->getLevel()->setBlock($up, $this, true, true); $this->getLevelNonNull()->setBlock($up, $this, true, true);
return true; return true;
} }
} }
@ -69,7 +69,7 @@ class WaterLily extends Flowable{
public function onNearbyBlockChange() : void{ public function onNearbyBlockChange() : void{
if(!($this->getSide(Vector3::SIDE_DOWN) instanceof Water)){ if(!($this->getSide(Vector3::SIDE_DOWN) instanceof Water)){
$this->getLevel()->useBreakOn($this); $this->getLevelNonNull()->useBreakOn($this);
} }
} }

View File

@ -56,7 +56,7 @@ class Wood extends Solid{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{ public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face); $this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
return $this->getLevel()->setBlock($blockReplace, $this, true, true); return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
} }
public function getVariantBitmask() : int{ public function getVariantBitmask() : int{

View File

@ -1743,7 +1743,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
} }
if($pos instanceof Position and $pos->level !== null and $pos->level !== $this->level){ if($pos instanceof Position and $pos->level !== null and $pos->level !== $this->level){
if(!$this->switchLevel($pos->getLevel())){ if(!$this->switchLevel($pos->getLevelNonNull())){
return false; return false;
} }
} }
@ -1849,7 +1849,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$pitch = $pitch ?? $pos->pitch; $pitch = $pitch ?? $pos->pitch;
} }
$from = Position::fromObject($this, $this->level); $from = Position::fromObject($this, $this->level);
$to = Position::fromObject($pos, $pos instanceof Position ? $pos->getLevel() : $this->level); $to = Position::fromObject($pos, $pos instanceof Position ? $pos->getLevelNonNull() : $this->level);
$ev = new EntityTeleportEvent($this, $from, $to); $ev = new EntityTeleportEvent($this, $from, $to);
$ev->call(); $ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){

View File

@ -191,7 +191,7 @@ abstract class Living extends Entity implements Damageable{
public function hasLineOfSight(Entity $entity) : bool{ public function hasLineOfSight(Entity $entity) : bool{
//TODO: head height //TODO: head height
return true; return true;
//return $this->getLevel()->rayTraceBlocks(Vector3::createVector($this->x, $this->y + $this->height, $this->z), Vector3::createVector($entity->x, $entity->y + $entity->height, $entity->z)) === null; //return $this->getLevelNonNull()->rayTraceBlocks(Vector3::createVector($this->x, $this->y + $this->height, $this->z), Vector3::createVector($entity->x, $entity->y + $entity->height, $entity->z)) === null;
} }
/** /**
@ -615,7 +615,7 @@ abstract class Living extends Entity implements Damageable{
$ev = new EntityDeathEvent($this, $this->getDrops(), $this->getXpDropAmount()); $ev = new EntityDeathEvent($this, $this->getDrops(), $this->getXpDropAmount());
$ev->call(); $ev->call();
foreach($ev->getDrops() as $item){ foreach($ev->getDrops() as $item){
$this->getLevel()->dropItem($this, $item); $this->getLevelNonNull()->dropItem($this, $item);
} }
//TODO: check death conditions (must have been damaged by player < 5 seconds from death) //TODO: check death conditions (must have been damaged by player < 5 seconds from death)

View File

@ -98,7 +98,7 @@ class FallingBlock extends Entity{
$hasUpdate = parent::entityBaseTick($tickDiff); $hasUpdate = parent::entityBaseTick($tickDiff);
if(!$this->isFlaggedForDespawn()){ if(!$this->isFlaggedForDespawn()){
$pos = Position::fromObject($this->add(-$this->width / 2, $this->height, -$this->width / 2)->floor(), $this->getLevel()); $pos = Position::fromObject($this->add(-$this->width / 2, $this->height, -$this->width / 2)->floor(), $this->getLevelNonNull());
$this->block->position($pos); $this->block->position($pos);
@ -113,12 +113,12 @@ class FallingBlock extends Entity{
$block = $this->level->getBlock($pos); $block = $this->level->getBlock($pos);
if(($block->isTransparent() and !$block->canBeReplaced()) or ($this->onGround and abs($this->y - $this->getFloorY()) > 0.001)){ if(($block->isTransparent() and !$block->canBeReplaced()) or ($this->onGround and abs($this->y - $this->getFloorY()) > 0.001)){
//FIXME: anvils are supposed to destroy torches //FIXME: anvils are supposed to destroy torches
$this->getLevel()->dropItem($this, ItemFactory::get($this->getBlock(), $this->getDamage())); $this->getLevelNonNull()->dropItem($this, ItemFactory::get($this->getBlock(), $this->getDamage()));
}else{ }else{
$ev = new EntityBlockChangeEvent($this, $block, $blockTarget ?? $this->block); $ev = new EntityBlockChangeEvent($this, $block, $blockTarget ?? $this->block);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->getLevel()->setBlock($pos, $ev->getTo(), true); $this->getLevelNonNull()->setBlock($pos, $ev->getTo(), true);
} }
} }
$hasUpdate = true; $hasUpdate = true;

View File

@ -44,6 +44,6 @@ class EntityDamageByChildEntityEvent extends EntityDamageByEntityEvent{
* Returns the entity which caused the damage, or null if the entity has been killed or closed. * Returns the entity which caused the damage, or null if the entity has been killed or closed.
*/ */
public function getChild() : ?Entity{ public function getChild() : ?Entity{
return $this->getEntity()->getLevel()->getServer()->findEntity($this->childEntityEid); return $this->getEntity()->getLevelNonNull()->getServer()->findEntity($this->childEntityEid);
} }
} }

View File

@ -62,7 +62,7 @@ class EntityDamageByEntityEvent extends EntityDamageEvent{
* Returns the attacking entity, or null if the attacker has been killed or closed. * Returns the attacking entity, or null if the attacker has been killed or closed.
*/ */
public function getDamager() : ?Entity{ public function getDamager() : ?Entity{
return $this->getEntity()->getLevel()->getServer()->findEntity($this->damagerEntityId); return $this->getEntity()->getLevelNonNull()->getServer()->findEntity($this->damagerEntityId);
} }
public function getKnockBack() : float{ public function getKnockBack() : float{

View File

@ -74,7 +74,7 @@ class ChestInventory extends ContainerInventory{
if(count($this->getViewers()) === 1 and $this->getHolder()->isValid()){ if(count($this->getViewers()) === 1 and $this->getHolder()->isValid()){
//TODO: this crap really shouldn't be managed by the inventory //TODO: this crap really shouldn't be managed by the inventory
$this->broadcastBlockEventPacket(true); $this->broadcastBlockEventPacket(true);
$this->getHolder()->getLevel()->broadcastLevelSoundEvent($this->getHolder()->add(0.5, 0.5, 0.5), $this->getOpenSound()); $this->getHolder()->getLevelNonNull()->broadcastLevelSoundEvent($this->getHolder()->add(0.5, 0.5, 0.5), $this->getOpenSound());
} }
} }
@ -82,7 +82,7 @@ class ChestInventory extends ContainerInventory{
if(count($this->getViewers()) === 1 and $this->getHolder()->isValid()){ if(count($this->getViewers()) === 1 and $this->getHolder()->isValid()){
//TODO: this crap really shouldn't be managed by the inventory //TODO: this crap really shouldn't be managed by the inventory
$this->broadcastBlockEventPacket(false); $this->broadcastBlockEventPacket(false);
$this->getHolder()->getLevel()->broadcastLevelSoundEvent($this->getHolder()->add(0.5, 0.5, 0.5), $this->getCloseSound()); $this->getHolder()->getLevelNonNull()->broadcastLevelSoundEvent($this->getHolder()->add(0.5, 0.5, 0.5), $this->getCloseSound());
} }
parent::onClose($who); parent::onClose($who);
} }
@ -96,6 +96,6 @@ class ChestInventory extends ContainerInventory{
$pk->z = (int) $holder->z; $pk->z = (int) $holder->z;
$pk->eventType = 1; //it's always 1 for a chest $pk->eventType = 1; //it's always 1 for a chest
$pk->eventData = $isOpen ? 1 : 0; $pk->eventData = $isOpen ? 1 : 0;
$holder->getLevel()->broadcastPacketToViewers($holder, $pk); $holder->getLevelNonNull()->broadcastPacketToViewers($holder, $pk);
} }
} }

View File

@ -56,7 +56,7 @@ class EnderChestInventory extends ChestInventory{
*/ */
public function setHolderPosition(EnderChest $enderChest){ public function setHolderPosition(EnderChest $enderChest){
$this->holder->setComponents($enderChest->getFloorX(), $enderChest->getFloorY(), $enderChest->getFloorZ()); $this->holder->setComponents($enderChest->getFloorX(), $enderChest->getFloorY(), $enderChest->getFloorZ());
$this->holder->setLevel($enderChest->getLevel()); $this->holder->setLevel($enderChest->getLevelNonNull());
} }
protected function getOpenSound() : int{ protected function getOpenSound() : int{

View File

@ -173,7 +173,7 @@ class PlayerInventory extends BaseInventory{
$this->sendSlot($this->getHeldItemIndex(), $target); $this->sendSlot($this->getHeldItemIndex(), $target);
} }
}else{ }else{
$this->getHolder()->getLevel()->getServer()->broadcastPacket($target, $pk); $this->getHolder()->getLevelNonNull()->getServer()->broadcastPacket($target, $pk);
if(in_array($this->getHolder(), $target, true)){ if(in_array($this->getHolder(), $target, true)){
$this->sendSlot($this->getHeldItemIndex(), $this->getHolder()); $this->sendSlot($this->getHeldItemIndex(), $this->getHolder());
} }

View File

@ -50,11 +50,10 @@ class ChorusFruit extends Food{
} }
public function onConsume(Living $consumer){ public function onConsume(Living $consumer){
$level = $consumer->getLevel(); $level = $consumer->getLevelNonNull();
assert($level !== null);
$minX = $consumer->getFloorX() - 8; $minX = $consumer->getFloorX() - 8;
$minY = min($consumer->getFloorY(), $consumer->getLevel()->getWorldHeight()) - 8; $minY = min($consumer->getFloorY(), $consumer->getLevelNonNull()->getWorldHeight()) - 8;
$minZ = $consumer->getFloorZ() - 8; $minZ = $consumer->getFloorZ() - 8;
$maxX = $minX + 16; $maxX = $minX + 16;

View File

@ -93,7 +93,7 @@ class PaintingItem extends Item{
$nbt->setInt("TileY", $blockClicked->getFloorY()); $nbt->setInt("TileY", $blockClicked->getFloorY());
$nbt->setInt("TileZ", $blockClicked->getFloorZ()); $nbt->setInt("TileZ", $blockClicked->getFloorZ());
$entity = Entity::createEntity("Painting", $blockReplace->getLevel(), $nbt); $entity = Entity::createEntity("Painting", $blockReplace->getLevelNonNull(), $nbt);
if($entity instanceof Entity){ if($entity instanceof Entity){
$this->pop(); $this->pop();

View File

@ -74,7 +74,7 @@ class Explosion{
throw new \InvalidArgumentException("Position does not have a valid world"); throw new \InvalidArgumentException("Position does not have a valid world");
} }
$this->source = $center; $this->source = $center;
$this->level = $center->getLevel(); $this->level = $center->getLevelNonNull();
if($size <= 0){ if($size <= 0){
throw new \InvalidArgumentException("Explosion radius must be greater than 0, got $size"); throw new \InvalidArgumentException("Explosion radius must be greater than 0, got $size");

View File

@ -75,7 +75,7 @@ class Location extends Position{
} }
public function __toString(){ public function __toString(){
return "Location (level=" . ($this->isValid() ? $this->getLevel()->getName() : "null") . ", x=$this->x, y=$this->y, z=$this->z, yaw=$this->yaw, pitch=$this->pitch)"; return "Location (level=" . ($this->isValid() ? $this->getLevelNonNull()->getName() : "null") . ", x=$this->x, y=$this->y, z=$this->z, yaw=$this->yaw, pitch=$this->pitch)";
} }
public function equals(Vector3 $v) : bool{ public function equals(Vector3 $v) : bool{

View File

@ -25,6 +25,7 @@ namespace pocketmine\level;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\utils\MainLogger; use pocketmine\utils\MainLogger;
use pocketmine\utils\AssumptionFailedError;
use function assert; use function assert;
class Position extends Vector3{ class Position extends Vector3{
@ -71,6 +72,19 @@ class Position extends Vector3{
return $this->level; return $this->level;
} }
/**
* Returns the position's world if valid. Throws an error if the world is unexpectedly null.
*
* @throws AssumptionFailedError
*/
public function getLevelNonNull() : Level{
$world = $this->getLevel();
if($world === null){
throw new AssumptionFailedError("Position world is null");
}
return $world;
}
/** /**
* Sets the target Level of the position. * Sets the target Level of the position.
* *
@ -112,7 +126,7 @@ class Position extends Vector3{
} }
public function __toString(){ public function __toString(){
return "Position(level=" . ($this->isValid() ? $this->getLevel()->getName() : "null") . ",x=" . $this->x . ",y=" . $this->y . ",z=" . $this->z . ")"; return "Position(level=" . ($this->isValid() ? $this->getLevelNonNull()->getName() : "null") . ",x=" . $this->x . ",y=" . $this->y . ",z=" . $this->z . ")";
} }
public function equals(Vector3 $v) : bool{ public function equals(Vector3 $v) : bool{

View File

@ -121,7 +121,7 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{
* @return void * @return void
*/ */
protected function checkPairing(){ protected function checkPairing(){
if($this->isPaired() and !$this->getLevel()->isInLoadedTerrain(new Vector3($this->pairX, $this->y, $this->pairZ))){ if($this->isPaired() and !$this->getLevelNonNull()->isInLoadedTerrain(new Vector3($this->pairX, $this->y, $this->pairZ))){
//paired to a tile in an unloaded chunk //paired to a tile in an unloaded chunk
$this->doubleInventory = null; $this->doubleInventory = null;
@ -160,7 +160,7 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{
public function getPair() : ?Chest{ public function getPair() : ?Chest{
if($this->isPaired()){ if($this->isPaired()){
$tile = $this->getLevel()->getTileAt($this->pairX, $this->y, $this->pairZ); $tile = $this->getLevelNonNull()->getTileAt($this->pairX, $this->y, $this->pairZ);
if($tile instanceof Chest){ if($tile instanceof Chest){
return $tile; return $tile;
} }

View File

@ -148,7 +148,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{
$this->maxTime = $this->burnTime = $ev->getBurnTime(); $this->maxTime = $this->burnTime = $ev->getBurnTime();
if($this->getBlock()->getId() === Block::FURNACE){ if($this->getBlock()->getId() === Block::FURNACE){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::BURNING_FURNACE, $this->getBlock()->getDamage()), true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::BURNING_FURNACE, $this->getBlock()->getDamage()), true);
} }
if($this->burnTime > 0 and $ev->isBurning()){ if($this->burnTime > 0 and $ev->isBurning()){
@ -211,7 +211,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{
$ret = true; $ret = true;
}else{ }else{
if($this->getBlock()->getId() === Block::BURNING_FURNACE){ if($this->getBlock()->getId() === Block::BURNING_FURNACE){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FURNACE, $this->getBlock()->getDamage()), true); $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::FURNACE, $this->getBlock()->getDamage()), true);
} }
$this->burnTime = $this->cookTime = $this->maxTime = 0; $this->burnTime = $this->cookTime = $this->maxTime = 0;
} }

View File

@ -168,7 +168,7 @@ abstract class Tile extends Position{
parent::__construct($nbt->getInt(self::TAG_X), $nbt->getInt(self::TAG_Y), $nbt->getInt(self::TAG_Z), $level); parent::__construct($nbt->getInt(self::TAG_X), $nbt->getInt(self::TAG_Y), $nbt->getInt(self::TAG_Z), $level);
$this->readSaveData($nbt); $this->readSaveData($nbt);
$this->getLevel()->addTile($this); $this->getLevelNonNull()->addTile($this);
} }
public function getId() : int{ public function getId() : int{

View File

@ -0,0 +1,33 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\utils;
/**
* This exception should be thrown in places where something is assumed to be true, but the type system does not provide
* a guarantee. This makes static analysers happy and makes sure that the server will crash properly if any assumption
* does not hold.
*/
final class AssumptionFailedError extends \Error{
}