Branch merge

This commit is contained in:
Dylan K. Taylor 2017-08-20 21:07:19 +01:00
commit 1f70a7830e
112 changed files with 931 additions and 800 deletions

View File

@ -26,6 +26,7 @@ namespace pocketmine;
use pocketmine\block\Air;
use pocketmine\block\Bed;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\entity\Arrow;
@ -1626,6 +1627,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
protected function tryChangeMovement(){
}
public function sendAttributes(bool $sendAll = false){
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
if(count($entries) > 0){
@ -1670,7 +1675,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->processMovement($tickDiff);
$this->entityBaseTick($tickDiff);
if(!$this->isSpectator()){
if(!$this->isSpectator() and $this->isAlive()){
$this->checkNearEntities($tickDiff);
if($this->speed !== null){
@ -2215,7 +2220,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()){
}elseif($this->isCreative()){
$item = $this->inventory->getItemInHand();
if($this->level->useItemOn($blockVector, $item, $face, $packet->transactionData->clickPos->x, $packet->transactionData->clickPos->y, $packet->transactionData->clickPos->z, $this, true) === true){
if($this->level->useItemOn($blockVector, $item, $face, $packet->transactionData->clickPos, $this, true) === true){
return true;
}
}elseif(!$this->inventory->getItemInHand()->equals($packet->transactionData->itemInHand)){
@ -2223,7 +2228,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}else{
$item = $this->inventory->getItemInHand();
$oldItem = clone $item;
if($this->level->useItemOn($blockVector, $item, $face, $packet->transactionData->clickPos->x, $packet->transactionData->clickPos->y, $packet->transactionData->clickPos->z, $this, true)){
if($this->level->useItemOn($blockVector, $item, $face, $packet->transactionData->clickPos, $this, true)){
if(!$item->equals($oldItem) or $item->getCount() !== $oldItem->getCount()){
$this->inventory->setItemInHand($item);
$this->inventory->sendHeldItem($this->hasSpawned);
@ -2587,7 +2592,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
$block = $target->getSide($packet->face);
if($block->getId() === Block::FIRE){
$this->level->setBlock($block, Block::get(Block::AIR));
$this->level->setBlock($block, BlockFactory::get(Block::AIR));
break;
}

View File

@ -27,7 +27,7 @@ declare(strict_types=1);
*/
namespace pocketmine;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\command\CommandReader;
use pocketmine\command\CommandSender;
use pocketmine\command\ConsoleCommandSender;
@ -80,8 +80,8 @@ use pocketmine\nbt\tag\StringTag;
use pocketmine\network\CompressBatchedTask;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
use pocketmine\network\mcpe\RakLibInterface;
use pocketmine\network\Network;
@ -1439,6 +1439,18 @@ class Server{
}
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
define('pocketmine\DEBUG', (int) $this->getProperty("debug.level", 1));
if(((int) ini_get('zend.assertions')) > 0 and ((bool) $this->getProperty("debug.assertions.warn-if-enabled", true)) !== false){
$this->logger->warning("Debugging assertions are enabled, this may impact on performance. To disable them, set `zend.assertions = -1` in php.ini.");
}
ini_set('assert.exception', '1');
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
}
$this->logger->info("Loading server properties...");
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
"motd" => "Minecraft: PE Server",
@ -1540,18 +1552,6 @@ class Server{
$this->setConfigInt("difficulty", 3);
}
define('pocketmine\DEBUG', (int) $this->getProperty("debug.level", 1));
if(((int) ini_get('zend.assertions')) > 0 and ((bool) $this->getProperty("debug.assertions.warn-if-enabled", true)) !== false){
$this->logger->warning("Debugging assertions are enabled, this may impact on performance. To disable them, set `zend.assertions = -1` in php.ini.");
}
ini_set('assert.exception', '1');
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
}
if(\pocketmine\DEBUG >= 0){
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
}
@ -1582,7 +1582,7 @@ class Server{
Entity::init();
Tile::init();
Block::init();
BlockFactory::init();
Enchantment::init();
Item::init();
Biome::init();

View File

@ -54,7 +54,7 @@ class Air extends Transparent{
return true;
}
public function canBeReplaced() : bool{
public function canBeReplaced(Block $with = null) : bool{
return true;
}
@ -74,7 +74,7 @@ class Air extends Transparent{
return -1;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 0;
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\inventory\AnvilInventory;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Anvil extends Fallable{
@ -48,7 +49,7 @@ class Anvil extends Fallable{
return 5;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 6000;
}
@ -73,7 +74,7 @@ class Anvil extends Fallable{
return true;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
$this->meta = ($this->meta & 0x0c) | $direction;
return $this->getLevel()->setBlock($block, $this, true, true);

View File

@ -174,14 +174,14 @@ class Bed extends Transparent{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if(!$down->isTransparent()){
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
$next = $this->getSide(self::getOtherHalfSide($meta));
if($next->canBeReplaced() === true and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, true);
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
$this->getLevel()->setBlock($block, BlockFactory::get($this->id, $meta), true, true);
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
$nbt = new CompoundTag("", [
new StringTag("id", Tile::BED),
@ -206,7 +206,7 @@ class Bed extends Transparent{
}
public function onBreak(Item $item) : bool{
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true, true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
if(($other = $this->getOtherHalf()) !== null){
$this->getLevel()->useBreakOn($other); //make sure tiles get removed
}

View File

@ -41,7 +41,7 @@ class Bedrock extends Solid{
return -1;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 18000000;
}

View File

@ -41,356 +41,17 @@ use pocketmine\plugin\Plugin;
class Block extends Position implements BlockIds, Metadatable{
/** @var \SplFixedArray<Block> */
public static $list = null;
/** @var \SplFixedArray<Block> */
public static $fullList = null;
/** @var \SplFixedArray<int> */
public static $light = null;
/** @var \SplFixedArray<int> */
public static $lightFilter = null;
/** @var \SplFixedArray<bool> */
public static $solid = null;
/** @var \SplFixedArray<float> */
public static $hardness = null;
/** @var \SplFixedArray<bool> */
public static $transparent = null;
/** @var \SplFixedArray<bool> */
public static $diffusesSkyLight = null;
/**
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
* this if you need to reset the block factory back to its original defaults for whatever reason.
* @deprecated This functionality has moved to {@link BlockFactory#get}
*
* @param bool $force
*/
public static function init(bool $force = false){
if(self::$list === null or $force){
self::$list = new \SplFixedArray(256);
self::$fullList = new \SplFixedArray(4096);
self::$light = new \SplFixedArray(256);
self::$lightFilter = new \SplFixedArray(256);
self::$solid = new \SplFixedArray(256);
self::$hardness = new \SplFixedArray(256);
self::$transparent = new \SplFixedArray(256);
self::$diffusesSkyLight = new \SplFixedArray(256);
self::registerBlock(new Air());
self::registerBlock(new Stone());
self::registerBlock(new Grass());
self::registerBlock(new Dirt());
self::registerBlock(new Cobblestone());
self::registerBlock(new Planks());
self::registerBlock(new Sapling());
self::registerBlock(new Bedrock());
self::registerBlock(new Water());
self::registerBlock(new StillWater());
self::registerBlock(new Lava());
self::registerBlock(new StillLava());
self::registerBlock(new Sand());
self::registerBlock(new Gravel());
self::registerBlock(new GoldOre());
self::registerBlock(new IronOre());
self::registerBlock(new CoalOre());
self::registerBlock(new Wood());
self::registerBlock(new Leaves());
self::registerBlock(new Sponge());
self::registerBlock(new Glass());
self::registerBlock(new LapisOre());
self::registerBlock(new Lapis());
//TODO: DISPENSER
self::registerBlock(new Sandstone());
self::registerBlock(new NoteBlock());
self::registerBlock(new Bed());
self::registerBlock(new PoweredRail());
self::registerBlock(new DetectorRail());
//TODO: STICKY_PISTON
self::registerBlock(new Cobweb());
self::registerBlock(new TallGrass());
self::registerBlock(new DeadBush());
//TODO: PISTON
//TODO: PISTONARMCOLLISION
self::registerBlock(new Wool());
self::registerBlock(new Dandelion());
self::registerBlock(new Flower());
self::registerBlock(new BrownMushroom());
self::registerBlock(new RedMushroom());
self::registerBlock(new Gold());
self::registerBlock(new Iron());
self::registerBlock(new DoubleStoneSlab());
self::registerBlock(new StoneSlab());
self::registerBlock(new Bricks());
self::registerBlock(new TNT());
self::registerBlock(new Bookshelf());
self::registerBlock(new MossyCobblestone());
self::registerBlock(new Obsidian());
self::registerBlock(new Torch());
self::registerBlock(new Fire());
self::registerBlock(new MonsterSpawner());
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
self::registerBlock(new Chest());
//TODO: REDSTONE_WIRE
self::registerBlock(new DiamondOre());
self::registerBlock(new Diamond());
self::registerBlock(new CraftingTable());
self::registerBlock(new Wheat());
self::registerBlock(new Farmland());
self::registerBlock(new Furnace());
self::registerBlock(new BurningFurnace());
self::registerBlock(new SignPost());
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door Block", Item::OAK_DOOR));
self::registerBlock(new Ladder());
self::registerBlock(new Rail());
self::registerBlock(new CobblestoneStairs());
self::registerBlock(new WallSign());
self::registerBlock(new Lever());
self::registerBlock(new StonePressurePlate());
self::registerBlock(new IronDoor());
self::registerBlock(new WoodenPressurePlate());
self::registerBlock(new RedstoneOre());
self::registerBlock(new GlowingRedstoneOre());
self::registerBlock(new RedstoneTorchUnlit());
self::registerBlock(new RedstoneTorch());
self::registerBlock(new StoneButton());
self::registerBlock(new SnowLayer());
self::registerBlock(new Ice());
self::registerBlock(new Snow());
self::registerBlock(new Cactus());
self::registerBlock(new Clay());
self::registerBlock(new Sugarcane());
self::registerBlock(new Fence());
self::registerBlock(new Pumpkin());
self::registerBlock(new Netherrack());
self::registerBlock(new SoulSand());
self::registerBlock(new Glowstone());
//TODO: PORTAL
self::registerBlock(new LitPumpkin());
self::registerBlock(new Cake());
//TODO: REPEATER_BLOCK
//TODO: POWERED_REPEATER
//TODO: INVISIBLEBEDROCK
self::registerBlock(new Trapdoor());
//TODO: MONSTER_EGG
self::registerBlock(new StoneBricks());
//TODO: BROWN_MUSHROOM_BLOCK
//TODO: RED_MUSHROOM_BLOCK
self::registerBlock(new IronBars());
self::registerBlock(new GlassPane());
self::registerBlock(new Melon());
self::registerBlock(new PumpkinStem());
self::registerBlock(new MelonStem());
self::registerBlock(new Vine());
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
self::registerBlock(new BrickStairs());
self::registerBlock(new StoneBrickStairs());
self::registerBlock(new Mycelium());
self::registerBlock(new WaterLily());
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
self::registerBlock(new NetherBrickFence());
self::registerBlock(new NetherBrickStairs());
self::registerBlock(new NetherWartPlant());
self::registerBlock(new EnchantingTable());
self::registerBlock(new BrewingStand());
//TODO: CAULDRON_BLOCK
//TODO: END_PORTAL
self::registerBlock(new EndPortalFrame());
self::registerBlock(new EndStone());
//TODO: DRAGON_EGG
self::registerBlock(new RedstoneLamp());
self::registerBlock(new LitRedstoneLamp());
//TODO: DROPPER
self::registerBlock(new ActivatorRail());
self::registerBlock(new CocoaBlock());
self::registerBlock(new SandstoneStairs());
self::registerBlock(new EmeraldOre());
//TODO: ENDER_CHEST
self::registerBlock(new TripwireHook());
self::registerBlock(new Tripwire());
self::registerBlock(new Emerald());
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
self::registerBlock(new WoodenStairs(Block::BIRCH_STAIRS, 0, "Birch Stairs"));
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
//TODO: COMMAND_BLOCK
//TODO: BEACON
self::registerBlock(new CobblestoneWall());
self::registerBlock(new FlowerPot());
self::registerBlock(new Carrot());
self::registerBlock(new Potato());
self::registerBlock(new WoodenButton());
self::registerBlock(new Skull());
self::registerBlock(new Anvil());
self::registerBlock(new TrappedChest());
self::registerBlock(new WeightedPressurePlateLight());
self::registerBlock(new WeightedPressurePlateHeavy());
//TODO: COMPARATOR_BLOCK
//TODO: POWERED_COMPARATOR
self::registerBlock(new DaylightSensor());
self::registerBlock(new Redstone());
self::registerBlock(new NetherQuartzOre());
//TODO: HOPPER_BLOCK
self::registerBlock(new Quartz());
self::registerBlock(new QuartzStairs());
self::registerBlock(new DoubleWoodenSlab());
self::registerBlock(new WoodenSlab());
self::registerBlock(new StainedClay());
self::registerBlock(new StainedGlassPane());
self::registerBlock(new Leaves2());
self::registerBlock(new Wood2());
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
//TODO: SLIME
self::registerBlock(new IronTrapdoor());
self::registerBlock(new Prismarine());
self::registerBlock(new SeaLantern());
self::registerBlock(new HayBale());
self::registerBlock(new Carpet());
self::registerBlock(new HardenedClay());
self::registerBlock(new Coal());
self::registerBlock(new PackedIce());
self::registerBlock(new DoublePlant());
//TODO: DAYLIGHT_DETECTOR_INVERTED
//TODO: RED_SANDSTONE
//TODO: RED_SANDSTONE_STAIRS
//TODO: DOUBLE_STONE_SLAB2
//TODO: STONE_SLAB2
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
self::registerBlock(new FenceGate(Block::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
//TODO: REPEATING_COMMAND_BLOCK
//TODO: CHAIN_COMMAND_BLOCK
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door Block", Item::SPRUCE_DOOR));
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door Block", Item::BIRCH_DOOR));
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door Block", Item::JUNGLE_DOOR));
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door Block", Item::ACACIA_DOOR));
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door Block", Item::DARK_OAK_DOOR));
self::registerBlock(new GrassPath());
self::registerBlock(new ItemFrame());
//TODO: CHORUS_FLOWER
//TODO: PURPUR_BLOCK
//TODO: PURPUR_STAIRS
//TODO: END_BRICKS
//TODO: FROSTED_ICE
self::registerBlock(new EndRod());
//TODO: END_GATEWAY
self::registerBlock(new Magma());
self::registerBlock(new NetherWartBlock());
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
//TODO: BONE_BLOCK
//TODO: SHULKER_BOX
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::MAGENTA_GLAZED_TERRACOTTA, 0, "Magenta Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::LIGHT_BLUE_GLAZED_TERRACOTTA, 0, "Light Blue Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::SILVER_GLAZED_TERRACOTTA, 0, "Light Grey Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
//TODO: CONCRETE
//TODO: CONCRETEPOWDER
//TODO: CHORUS_PLANT
self::registerBlock(new StainedGlass());
self::registerBlock(new Podzol());
self::registerBlock(new Beetroot());
self::registerBlock(new Stonecutter());
self::registerBlock(new GlowingObsidian());
self::registerBlock(new NetherReactor());
//TODO: INFO_UPDATE
//TODO: INFO_UPDATE2
//TODO: MOVINGBLOCK
//TODO: OBSERVER
//TODO: RESERVED6
foreach(self::$list as $id => $block){
if($block === null){
self::registerBlock(new UnknownBlock($id));
}
}
}
}
/**
* Registers a block type into the index. Plugins may use this method to register new block types or override
* existing ones.
*
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
* will not automatically appear there.
*
* @param Block $block
* @param bool $override Whether to override existing registrations
*
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
* $override parameter.
*/
public static function registerBlock(Block $block, bool $override = false){
$id = $block->getId();
if(self::$list[$id] !== null and !(self::$list[$id] instanceof UnknownBlock) and !$override){
throw new \RuntimeException("Trying to overwrite an already registered block");
}
self::$list[$id] = clone $block;
for($meta = 0; $meta < 16; ++$meta){
$variant = clone $block;
$variant->setDamage($meta);
self::$fullList[($id << 4) | $meta] = $variant;
}
self::$solid[$id] = $block->isSolid();
self::$transparent[$id] = $block->isTransparent();
self::$hardness[$id] = $block->getHardness();
self::$light[$id] = $block->getLightLevel();
self::$lightFilter[$id] = $block->getLightFilter() + 1; //opacity plus 1 standard light filter
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
}
/**
* @param int $id
* @param int $meta
* @param Position $pos
* @param int $id
* @param int $meta
* @param Position|null $pos
*
* @return Block
*/
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
try{
$block = clone self::$fullList[($id << 4) | $meta];
}catch(\RuntimeException $e){
//TODO: this probably should return null (out of bounds IDs may cause unexpected behaviour)
$block = new UnknownBlock($id, $meta);
}
if($pos !== null){
$block->x = $pos->x;
$block->y = $pos->y;
$block->z = $pos->z;
$block->level = $pos->level;
}
return $block;
return BlockFactory::get($id, $meta, $pos);
}
/** @var int */
@ -476,14 +137,12 @@ class Block extends Position implements BlockIds, Metadatable{
* @param Block $block
* @param Block $target
* @param int $face
* @param float $fx
* @param float $fy
* @param float $fz
* @param Vector3 $facePos
* @param Player|null $player
*
* @return bool
*/
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, $this, true, true);
}
@ -506,7 +165,7 @@ class Block extends Position implements BlockIds, Metadatable{
* @return bool
*/
public function onBreak(Item $item) : bool{
return $this->getLevel()->setBlock($this, Block::get(Block::AIR), true, true);
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
}
/**
@ -533,6 +192,7 @@ class Block extends Position implements BlockIds, Metadatable{
}
/**
* Returns a base value used to compute block break times.
* @return float
*/
public function getHardness() : float{
@ -540,9 +200,18 @@ class Block extends Position implements BlockIds, Metadatable{
}
/**
* @deprecated
* @return float
*/
public function getResistance() : float{
return $this->getBlastResistance();
}
/**
* Returns the block's resistance to explosions. Usually 5x hardness.
* @return float
*/
public function getBlastResistance() : float{
return $this->getHardness() * 5;
}
@ -599,9 +268,11 @@ class Block extends Position implements BlockIds, Metadatable{
}
/**
* @param Block|null $with
*
* @return bool
*/
public function canBeReplaced() : bool{
public function canBeReplaced(Block $with = null) : bool{
return false;
}
@ -742,7 +413,7 @@ class Block extends Position implements BlockIds, Metadatable{
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
}
return Block::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));
return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));
}
/**

View File

@ -0,0 +1,391 @@
<?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\block;
use pocketmine\item\Item;
use pocketmine\level\Position;
/**
* Manages block registration and instance creation
*/
class BlockFactory{
/** @var \SplFixedArray<Block> */
public static $list = null;
/** @var \SplFixedArray<Block> */
public static $fullList = null;
/** @var \SplFixedArray<bool> */
public static $solid = null;
/** @var \SplFixedArray<bool> */
public static $transparent = null;
/** @var \SplFixedArray<float> */
public static $hardness = null;
/** @var \SplFixedArray<int> */
public static $light = null;
/** @var \SplFixedArray<int> */
public static $lightFilter = null;
/** @var \SplFixedArray<bool> */
public static $diffusesSkyLight = null;
/** @var \SplFixedArray<float> */
public static $blastResistance = null;
/**
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
* this if you need to reset the block factory back to its original defaults for whatever reason.
*
* @param bool $force
*/
public static function init(bool $force = false){
if(self::$list === null or $force){
self::$list = new \SplFixedArray(256);
self::$fullList = new \SplFixedArray(4096);
self::$light = new \SplFixedArray(256);
self::$lightFilter = new \SplFixedArray(256);
self::$solid = new \SplFixedArray(256);
self::$hardness = new \SplFixedArray(256);
self::$transparent = new \SplFixedArray(256);
self::$diffusesSkyLight = new \SplFixedArray(256);
self::registerBlock(new Air());
self::registerBlock(new Stone());
self::registerBlock(new Grass());
self::registerBlock(new Dirt());
self::registerBlock(new Cobblestone());
self::registerBlock(new Planks());
self::registerBlock(new Sapling());
self::registerBlock(new Bedrock());
self::registerBlock(new Water());
self::registerBlock(new StillWater());
self::registerBlock(new Lava());
self::registerBlock(new StillLava());
self::registerBlock(new Sand());
self::registerBlock(new Gravel());
self::registerBlock(new GoldOre());
self::registerBlock(new IronOre());
self::registerBlock(new CoalOre());
self::registerBlock(new Wood());
self::registerBlock(new Leaves());
self::registerBlock(new Sponge());
self::registerBlock(new Glass());
self::registerBlock(new LapisOre());
self::registerBlock(new Lapis());
//TODO: DISPENSER
self::registerBlock(new Sandstone());
self::registerBlock(new NoteBlock());
self::registerBlock(new Bed());
self::registerBlock(new PoweredRail());
self::registerBlock(new DetectorRail());
//TODO: STICKY_PISTON
self::registerBlock(new Cobweb());
self::registerBlock(new TallGrass());
self::registerBlock(new DeadBush());
//TODO: PISTON
//TODO: PISTONARMCOLLISION
self::registerBlock(new Wool());
self::registerBlock(new Dandelion());
self::registerBlock(new Flower());
self::registerBlock(new BrownMushroom());
self::registerBlock(new RedMushroom());
self::registerBlock(new Gold());
self::registerBlock(new Iron());
self::registerBlock(new DoubleStoneSlab());
self::registerBlock(new StoneSlab());
self::registerBlock(new Bricks());
self::registerBlock(new TNT());
self::registerBlock(new Bookshelf());
self::registerBlock(new MossyCobblestone());
self::registerBlock(new Obsidian());
self::registerBlock(new Torch());
self::registerBlock(new Fire());
self::registerBlock(new MonsterSpawner());
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
self::registerBlock(new Chest());
//TODO: REDSTONE_WIRE
self::registerBlock(new DiamondOre());
self::registerBlock(new Diamond());
self::registerBlock(new CraftingTable());
self::registerBlock(new Wheat());
self::registerBlock(new Farmland());
self::registerBlock(new Furnace());
self::registerBlock(new BurningFurnace());
self::registerBlock(new SignPost());
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door Block", Item::OAK_DOOR));
self::registerBlock(new Ladder());
self::registerBlock(new Rail());
self::registerBlock(new CobblestoneStairs());
self::registerBlock(new WallSign());
self::registerBlock(new Lever());
self::registerBlock(new StonePressurePlate());
self::registerBlock(new IronDoor());
self::registerBlock(new WoodenPressurePlate());
self::registerBlock(new RedstoneOre());
self::registerBlock(new GlowingRedstoneOre());
self::registerBlock(new RedstoneTorchUnlit());
self::registerBlock(new RedstoneTorch());
self::registerBlock(new StoneButton());
self::registerBlock(new SnowLayer());
self::registerBlock(new Ice());
self::registerBlock(new Snow());
self::registerBlock(new Cactus());
self::registerBlock(new Clay());
self::registerBlock(new Sugarcane());
self::registerBlock(new Fence());
self::registerBlock(new Pumpkin());
self::registerBlock(new Netherrack());
self::registerBlock(new SoulSand());
self::registerBlock(new Glowstone());
//TODO: PORTAL
self::registerBlock(new LitPumpkin());
self::registerBlock(new Cake());
//TODO: REPEATER_BLOCK
//TODO: POWERED_REPEATER
//TODO: INVISIBLEBEDROCK
self::registerBlock(new Trapdoor());
//TODO: MONSTER_EGG
self::registerBlock(new StoneBricks());
//TODO: BROWN_MUSHROOM_BLOCK
//TODO: RED_MUSHROOM_BLOCK
self::registerBlock(new IronBars());
self::registerBlock(new GlassPane());
self::registerBlock(new Melon());
self::registerBlock(new PumpkinStem());
self::registerBlock(new MelonStem());
self::registerBlock(new Vine());
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
self::registerBlock(new BrickStairs());
self::registerBlock(new StoneBrickStairs());
self::registerBlock(new Mycelium());
self::registerBlock(new WaterLily());
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
self::registerBlock(new NetherBrickFence());
self::registerBlock(new NetherBrickStairs());
self::registerBlock(new NetherWartPlant());
self::registerBlock(new EnchantingTable());
self::registerBlock(new BrewingStand());
//TODO: CAULDRON_BLOCK
//TODO: END_PORTAL
self::registerBlock(new EndPortalFrame());
self::registerBlock(new EndStone());
//TODO: DRAGON_EGG
self::registerBlock(new RedstoneLamp());
self::registerBlock(new LitRedstoneLamp());
//TODO: DROPPER
self::registerBlock(new ActivatorRail());
self::registerBlock(new CocoaBlock());
self::registerBlock(new SandstoneStairs());
self::registerBlock(new EmeraldOre());
//TODO: ENDER_CHEST
self::registerBlock(new TripwireHook());
self::registerBlock(new Tripwire());
self::registerBlock(new Emerald());
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
self::registerBlock(new WoodenStairs(Block::BIRCH_STAIRS, 0, "Birch Stairs"));
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
//TODO: COMMAND_BLOCK
//TODO: BEACON
self::registerBlock(new CobblestoneWall());
self::registerBlock(new FlowerPot());
self::registerBlock(new Carrot());
self::registerBlock(new Potato());
self::registerBlock(new WoodenButton());
self::registerBlock(new Skull());
self::registerBlock(new Anvil());
self::registerBlock(new TrappedChest());
self::registerBlock(new WeightedPressurePlateLight());
self::registerBlock(new WeightedPressurePlateHeavy());
//TODO: COMPARATOR_BLOCK
//TODO: POWERED_COMPARATOR
self::registerBlock(new DaylightSensor());
self::registerBlock(new Redstone());
self::registerBlock(new NetherQuartzOre());
//TODO: HOPPER_BLOCK
self::registerBlock(new Quartz());
self::registerBlock(new QuartzStairs());
self::registerBlock(new DoubleWoodenSlab());
self::registerBlock(new WoodenSlab());
self::registerBlock(new StainedClay());
self::registerBlock(new StainedGlassPane());
self::registerBlock(new Leaves2());
self::registerBlock(new Wood2());
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
//TODO: SLIME
self::registerBlock(new IronTrapdoor());
self::registerBlock(new Prismarine());
self::registerBlock(new SeaLantern());
self::registerBlock(new HayBale());
self::registerBlock(new Carpet());
self::registerBlock(new HardenedClay());
self::registerBlock(new Coal());
self::registerBlock(new PackedIce());
self::registerBlock(new DoublePlant());
//TODO: DAYLIGHT_DETECTOR_INVERTED
//TODO: RED_SANDSTONE
//TODO: RED_SANDSTONE_STAIRS
//TODO: DOUBLE_STONE_SLAB2
//TODO: STONE_SLAB2
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
self::registerBlock(new FenceGate(Block::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
//TODO: REPEATING_COMMAND_BLOCK
//TODO: CHAIN_COMMAND_BLOCK
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door Block", Item::SPRUCE_DOOR));
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door Block", Item::BIRCH_DOOR));
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door Block", Item::JUNGLE_DOOR));
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door Block", Item::ACACIA_DOOR));
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door Block", Item::DARK_OAK_DOOR));
self::registerBlock(new GrassPath());
self::registerBlock(new ItemFrame());
//TODO: CHORUS_FLOWER
//TODO: PURPUR_BLOCK
//TODO: PURPUR_STAIRS
//TODO: END_BRICKS
//TODO: FROSTED_ICE
self::registerBlock(new EndRod());
//TODO: END_GATEWAY
self::registerBlock(new Magma());
self::registerBlock(new NetherWartBlock());
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
//TODO: BONE_BLOCK
//TODO: SHULKER_BOX
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::MAGENTA_GLAZED_TERRACOTTA, 0, "Magenta Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::LIGHT_BLUE_GLAZED_TERRACOTTA, 0, "Light Blue Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::SILVER_GLAZED_TERRACOTTA, 0, "Light Grey Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
//TODO: CONCRETE
//TODO: CONCRETEPOWDER
//TODO: CHORUS_PLANT
self::registerBlock(new StainedGlass());
self::registerBlock(new Podzol());
self::registerBlock(new Beetroot());
self::registerBlock(new Stonecutter());
self::registerBlock(new GlowingObsidian());
self::registerBlock(new NetherReactor());
//TODO: INFO_UPDATE
//TODO: INFO_UPDATE2
//TODO: MOVINGBLOCK
//TODO: OBSERVER
//TODO: RESERVED6
foreach(self::$list as $id => $block){
if($block === null){
self::registerBlock(new UnknownBlock($id));
}
}
}
}
/**
* Registers a block type into the index. Plugins may use this method to register new block types or override
* existing ones.
*
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
* will not automatically appear there.
*
* @param Block $block
* @param bool $override Whether to override existing registrations
*
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
* $override parameter.
*/
public static function registerBlock(Block $block, bool $override = false){
$id = $block->getId();
if(self::$list[$id] !== null and !(self::$list[$id] instanceof UnknownBlock) and !$override){
throw new \RuntimeException("Trying to overwrite an already registered block");
}
self::$list[$id] = clone $block;
for($meta = 0; $meta < 16; ++$meta){
$variant = clone $block;
$variant->setDamage($meta);
self::$fullList[($id << 4) | $meta] = $variant;
}
self::$solid[$id] = $block->isSolid();
self::$transparent[$id] = $block->isTransparent();
self::$hardness[$id] = $block->getHardness();
self::$light[$id] = $block->getLightLevel();
self::$lightFilter[$id] = $block->getLightFilter() + 1; //opacity plus 1 standard light filter
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
self::$blastResistance[$id] = $block->getBlastResistance();
}
/**
* @param int $id
* @param int $meta
* @param Position $pos
*
* @return Block
*/
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
try{
$block = self::$fullList[($id << 4) | $meta];
if($block !== null){
$block = clone $block;
}else{
$block = new UnknownBlock($id, $meta);
}
}catch(\RuntimeException $e){
//TODO: this probably should return null (out of bounds IDs may cause unexpected behaviour)
$block = new UnknownBlock($id, $meta);
}
if($pos !== null){
$block->x = $pos->x;
$block->y = $pos->y;
$block->z = $pos->z;
$block->level = $pos->level;
}
return $block;
}
}

View File

@ -37,7 +37,7 @@ class BrickStairs extends Stair{
return 2;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 30;
}

View File

@ -38,7 +38,7 @@ class Bricks extends Solid{
return 2;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 30;
}

View File

@ -56,7 +56,7 @@ class BrownMushroom extends Flowable{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->isTransparent() === false){
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\Vector3;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
@ -58,7 +59,7 @@ class BurningFurnace extends Solid{
return 13;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$faces = [
0 => 4,
1 => 2,

View File

@ -90,7 +90,7 @@ class Cactus extends Transparent{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, Block::get(Block::CACTUS)));
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}
@ -108,7 +108,7 @@ class Cactus extends Transparent{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::SAND or $down->getId() === self::CACTUS){
$block0 = $this->getSide(Vector3::SIDE_NORTH);

View File

@ -62,7 +62,7 @@ class Cake extends Transparent implements FoodSource{
);
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($block, $this, true, true);
@ -76,7 +76,7 @@ class Cake extends Transparent implements FoodSource{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
return Level::BLOCK_UPDATE_NORMAL;
}
@ -114,7 +114,7 @@ class Cake extends Transparent implements FoodSource{
$clone = clone $this;
$clone->meta++;
if($clone->meta >= 0x06){
$clone = Block::get(Block::AIR);
$clone = BlockFactory::get(Block::AIR);
}
return $clone;
}

View File

@ -62,7 +62,7 @@ class Carpet extends Flowable{
);
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -67,7 +67,7 @@ class Chest extends Transparent{
);
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$faces = [
0 => 4,
1 => 2,
@ -129,7 +129,7 @@ class Chest extends Transparent{
if($t instanceof TileChest){
$t->unpair();
}
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true, true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
return true;
}

View File

@ -32,7 +32,7 @@ use pocketmine\Server;
abstract class Crops extends Flowable{
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($block->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -41,7 +41,7 @@ class Dandelion extends Flowable{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === 2 or $down->getId() === 3 or $down->getId() === 60){
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -50,7 +50,7 @@ class Dirt extends Solid{
public function onActivate(Item $item, Player $player = null) : bool{
if($item->isHoe()){
$item->useOn($this);
$this->getLevel()->setBlock($this, Block::get(Block::FARMLAND, 0), true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND, 0), true);
return true;
}

View File

@ -204,9 +204,9 @@ abstract class Door extends Transparent{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, Block::get(Block::AIR), false);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), Block::get(Block::AIR), false);
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
}
return Level::BLOCK_UPDATE_NORMAL;
@ -216,22 +216,22 @@ abstract class Door extends Transparent{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
if($face === 1){
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($face === Vector3::SIDE_UP){
$blockUp = $this->getSide(Vector3::SIDE_UP);
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
if($blockUp->canBeReplaced() === false or $blockDown->isTransparent() === true){
return false;
}
$direction = $player instanceof Player ? $player->getDirection() : 0;
$face = [
$faces = [
0 => 3,
1 => 4,
2 => 2,
3 => 5,
];
$next = $this->getSide($face[($direction + 2) % 4]);
$next2 = $this->getSide($face[$direction]);
$next = $this->getSide($faces[($direction + 2) % 4]);
$next2 = $this->getSide($faces[$direction]);
$metaUp = 0x08;
if($next->getId() === $this->getId() or ($next2->isTransparent() === false and $next->isTransparent() === true)){ //Door hinge
$metaUp |= 0x01;
@ -239,7 +239,7 @@ abstract class Door extends Transparent{
$this->setDamage($player->getDirection() & 0x03);
$this->getLevel()->setBlock($block, $this, true, true); //Bottom
$this->getLevel()->setBlock($blockUp, $b = Block::get($this->getId(), $metaUp), true); //Top
$this->getLevel()->setBlock($blockUp, $b = BlockFactory::get($this->getId(), $metaUp), true); //Top
return true;
}
@ -250,15 +250,15 @@ abstract class Door extends Transparent{
if(($this->getDamage() & 0x08) === 0x08){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === $this->getId()){
$this->getLevel()->setBlock($down, Block::get(Block::AIR), true);
$this->getLevel()->setBlock($down, BlockFactory::get(Block::AIR), true);
}
}else{
$up = $this->getSide(Vector3::SIDE_UP);
if($up->getId() === $this->getId()){
$this->getLevel()->setBlock($up, Block::get(Block::AIR), true);
$this->getLevel()->setBlock($up, BlockFactory::get(Block::AIR), true);
}
}
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
return true;
}
@ -268,7 +268,7 @@ abstract class Door extends Transparent{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === $this->getId()){
$meta = $down->getDamage() ^ 0x04;
$this->level->setBlock($down, Block::get($this->getId(), $meta), true);
$this->level->setBlock($down, BlockFactory::get($this->getId(), $meta), true);
$this->level->addSound(new DoorSound($this));
return true;
}

View File

@ -37,7 +37,7 @@ class DoublePlant extends Flowable{
$this->meta = $meta;
}
public function canBeReplaced() : bool{
public function canBeReplaced(Block $with = null) : bool{
return $this->meta === 2 or $this->meta === 3; //grass or fern
}
@ -53,11 +53,11 @@ class DoublePlant extends Flowable{
return $names[$this->meta & 0x07] ?? "";
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$id = $block->getSide(Vector3::SIDE_DOWN)->getId();
if(($id === Block::GRASS or $id === Block::DIRT) and $block->getSide(Vector3::SIDE_UP)->canBeReplaced()){
$this->getLevel()->setBlock($block, $this, false, false);
$this->getLevel()->setBlock($block->getSide(Vector3::SIDE_UP), Block::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
$this->getLevel()->setBlock($block->getSide(Vector3::SIDE_UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
return true;
}
@ -98,7 +98,7 @@ class DoublePlant extends Flowable{
public function onBreak(Item $item) : bool{
if(parent::onBreak($item) and $this->isValidHalfPlant()){
return $this->getLevel()->setBlock($this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP), Block::get(Block::AIR));
return $this->getLevel()->setBlock($this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP), BlockFactory::get(Block::AIR));
}
return false;

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\inventory\EnchantInventory;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
@ -40,7 +41,7 @@ class EnchantingTable extends Transparent{
$this->meta = $meta;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$this->getLevel()->setBlock($block, $this, true, true);
$nbt = new CompoundTag("", [
new StringTag("id", Tile::ENCHANT_TABLE),
@ -68,7 +69,7 @@ class EnchantingTable extends Transparent{
return 5;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 6000;
}

View File

@ -46,7 +46,7 @@ class EndPortalFrame extends Solid{
return -1;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 18000000;
}

View File

@ -40,7 +40,7 @@ class EndRod extends Flowable{
return "End Rod";
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($face === Vector3::SIDE_UP or $face === Vector3::SIDE_DOWN){
$this->meta = $face;
}else{

View File

@ -39,7 +39,7 @@ abstract class Fallable extends Solid{
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::AIR or ($down instanceof Liquid)){
$this->level->setBlock($this, Block::get(Block::AIR), true, true);
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
$fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [
new ListTag("Pos", [
new DoubleTag("", $this->x + 0.5),

View File

@ -27,6 +27,7 @@ use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\sound\DoorSound;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
class FenceGate extends Transparent{
@ -68,7 +69,7 @@ class FenceGate extends Transparent{
}
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$this->meta = ($player instanceof Player ? ($player->getDirection() - 1) & 0x03 : 0);
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -57,7 +57,7 @@ class Fire extends Flowable{
return false;
}
public function canBeReplaced() : bool{
public function canBeReplaced(Block $with = null) : bool{
return true;
}
@ -87,14 +87,14 @@ class Fire extends Flowable{
return false;
}
}
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
return Level::BLOCK_UPDATE_NORMAL;
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::NETHERRACK){
if(mt_rand(0, 2) === 0){
if($this->meta === 0x0F){
$this->level->setBlock($this, Block::get(Block::AIR));
$this->level->setBlock($this, BlockFactory::get(Block::AIR));
}else{
$this->meta++;
$this->level->setBlock($this, $this);

View File

@ -33,7 +33,7 @@ abstract class Flowable extends Transparent{
return 0;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 0;
}

View File

@ -60,7 +60,7 @@ class Flower extends Flowable{
return $names[$this->meta] ?? "Unknown";
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($block, $this, true);

View File

@ -62,7 +62,7 @@ class FlowerPot extends Flowable{
);
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
return false;
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\Vector3;
use pocketmine\Player;
class GlazedTerracotta extends Solid{
@ -38,7 +39,7 @@ class GlazedTerracotta extends Solid{
return Tool::TYPE_PICKAXE;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($player !== null){
$faces = [
0 => 4,

View File

@ -39,7 +39,7 @@ class GlowingRedstoneOre extends RedstoneOre{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_SCHEDULED or $type === Level::BLOCK_UPDATE_RANDOM){
$this->getLevel()->setBlock($this, Block::get(Block::REDSTONE_ORE, $this->meta), false, false);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
return Level::BLOCK_UPDATE_WEAK;
}

View File

@ -61,9 +61,9 @@ class Grass extends Solid{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_RANDOM){
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
if($lightAbove < 4 and Block::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
//grass dies
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, Block::get(Block::DIRT)));
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT)));
if(!$ev->isCancelled()){
$this->level->setBlock($this, $ev->getNewState(), false, false);
}
@ -79,12 +79,12 @@ class Grass extends Solid{
if(
$this->level->getBlockIdAt($vector->x, $vector->y, $vector->z) !== Block::DIRT or
$this->level->getFullLightAt($vector->x, $vector->y + 1, $vector->z) < 4 or
Block::$lightFilter[$this->level->getBlockIdAt($vector->x, $vector->y + 1, $vector->z)] >= 3
BlockFactory::$lightFilter[$this->level->getBlockIdAt($vector->x, $vector->y + 1, $vector->z)] >= 3
){
continue;
}
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this->level->getBlock($vector), $this, Block::get(Block::GRASS)));
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this->level->getBlock($vector), $this, BlockFactory::get(Block::GRASS)));
if(!$ev->isCancelled()){
$this->level->setBlock($vector, $ev->getNewState(), false, false);
}
@ -105,12 +105,12 @@ class Grass extends Solid{
return true;
}elseif($item->isHoe()){
$item->useOn($this);
$this->getLevel()->setBlock($this, Block::get(Block::FARMLAND));
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
return true;
}elseif($item->isShovel() and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
$item->useOn($this);
$this->getLevel()->setBlock($this, Block::get(Block::GRASS_PATH));
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
return true;
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
class HayBale extends Solid{
@ -42,7 +43,7 @@ class HayBale extends Solid{
return 0.5;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$faces = [
0 => 0,
1 => 0,

View File

@ -52,7 +52,7 @@ class Ice extends Transparent{
}
public function onBreak(Item $item) : bool{
$this->getLevel()->setBlock($this, Block::get(Block::WATER), true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
return true;
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\{
ByteTag, CompoundTag, FloatTag, IntTag, StringTag
};
@ -103,16 +104,16 @@ class ItemFrame extends Flowable{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
if($face === 0 or $face === 1){
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($face === Vector3::SIDE_DOWN or $face === Vector3::SIDE_UP){
return false;
}
$faces = [
2 => 3,
3 => 2,
4 => 1,
5 => 0
Vector3::SIDE_NORTH => 3,
Vector3::SIDE_SOUTH => 2,
Vector3::SIDE_WEST => 1,
Vector3::SIDE_EAST => 0
];
$this->meta = $faces[$face];

View File

@ -28,6 +28,7 @@ use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Ladder extends Transparent{
@ -109,7 +110,7 @@ class Ladder extends Transparent{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($target->isTransparent() === false){
$faces = [
2 => 2,

View File

@ -28,6 +28,7 @@ use pocketmine\event\entity\EntityCombustByBlockEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
@ -62,7 +63,7 @@ class Lava extends Liquid{
$entity->resetFallDistance();
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$ret = $this->getLevel()->setBlock($this, $this, true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($this, $this->tickRate());

View File

@ -159,7 +159,7 @@ class Leaves extends Transparent{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$this->meta |= 0x04;
return $this->getLevel()->setBlock($this, $this, true);
}

View File

@ -41,7 +41,7 @@ abstract class Liquid extends Transparent{
return false;
}
public function canBeReplaced() : bool{
public function canBeReplaced(Block $with = null) : bool{
return true;
}
@ -241,9 +241,9 @@ abstract class Liquid extends Transparent{
if($k !== $decay){
$decay = $k;
if($decay < 0){
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true, true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
}else{
$this->getLevel()->setBlock($this, Block::get($this->id, $decay), true, true);
$this->getLevel()->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
$this->getLevel()->scheduleDelayedBlockUpdate($this, $this->tickRate());
}
}elseif($flag){
@ -257,10 +257,10 @@ abstract class Liquid extends Transparent{
$bottomBlock = $this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y - 1, $this->z));
if($this instanceof Lava and $bottomBlock instanceof Water){
$this->getLevel()->setBlock($bottomBlock, Block::get(Block::STONE), true, true);
$this->getLevel()->setBlock($bottomBlock, BlockFactory::get(Block::STONE), true, true);
}elseif($bottomBlock->canBeFlowedInto() or ($bottomBlock instanceof Liquid and ($bottomBlock->getDamage() & 0x07) !== 0)){
$this->getLevel()->setBlock($bottomBlock, Block::get($this->id, $decay | 0x08), true, false);
$this->getLevel()->setBlock($bottomBlock, BlockFactory::get($this->id, $decay | 0x08), true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($bottomBlock, $this->tickRate());
}elseif($decay >= 0 and ($decay === 0 or !$bottomBlock->canBeFlowedInto())){
@ -305,7 +305,7 @@ abstract class Liquid extends Transparent{
$this->getLevel()->useBreakOn($block);
}
$this->getLevel()->setBlock($block, Block::get($this->getId(), $newFlowDecay), true, false);
$this->getLevel()->setBlock($block, BlockFactory::get($this->getId(), $newFlowDecay), true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($block, $this->tickRate());
}
}
@ -434,9 +434,9 @@ abstract class Liquid extends Transparent{
if($colliding){
if($this->getDamage() === 0){
$this->getLevel()->setBlock($this, Block::get(Block::OBSIDIAN), true, true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::OBSIDIAN), true, true);
}elseif($this->getDamage() <= 4){
$this->getLevel()->setBlock($this, Block::get(Block::COBBLESTONE), true, true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::COBBLESTONE), true, true);
}
}
}

View File

@ -68,7 +68,7 @@ class MelonStem extends Crops{
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, Block::get(Block::MELON_BLOCK)));
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}

View File

@ -65,7 +65,7 @@ class Mycelium extends Solid{
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
if($block->getId() === Block::DIRT){
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, Block::get(Block::MYCELIUM)));
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($block, $ev->getNewState());
}

View File

@ -39,7 +39,7 @@ class NetherWartPlant extends Flowable{
$this->meta = $meta;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::SOUL_SAND){
$this->getLevel()->setBlock($block, $this, false, true);

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Pumpkin extends Solid{
@ -47,7 +48,7 @@ class Pumpkin extends Solid{
return "Pumpkin";
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($player instanceof Player){
$this->meta = ((int) $player->getDirection() + 1) % 4;
}

View File

@ -68,7 +68,7 @@ class PumpkinStem extends Crops{
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, Block::get(Block::PUMPKIN)));
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::PUMPKIN)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}

View File

@ -55,7 +55,7 @@ class Rail extends Flowable{
return 0.7;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if(!$block->getSide(Vector3::SIDE_DOWN)->isTransparent()){
return $this->getLevel()->setBlock($block, $this, true, true);
}

View File

@ -53,7 +53,7 @@ class RedMushroom extends Flowable{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->isTransparent() === false){
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
class RedstoneOre extends Solid{
@ -44,13 +45,13 @@ class RedstoneOre extends Solid{
return 3;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, $this, true, false);
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL or $type === Level::BLOCK_UPDATE_TOUCH){
$this->getLevel()->setBlock($this, Block::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
return Level::BLOCK_UPDATE_WEAK;
}

View File

@ -57,7 +57,7 @@ class Sapling extends Flowable{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -60,8 +60,8 @@ class SignPost extends Transparent{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
if($face !== 0){
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($face !== Vector3::SIDE_DOWN){
$nbt = new CompoundTag("", [
new StringTag("id", Tile::SIGN),
new IntTag("x", $block->x),
@ -83,7 +83,7 @@ class SignPost extends Transparent{
}
}
if($face === 1){
if($face === Vector3::SIDE_UP){
$this->meta = floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0f;
$this->getLevel()->setBlock($block, $this, true);
}else{

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
@ -62,10 +63,10 @@ class Skull extends Flowable{
);
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
if($face !== 0){
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($face !== Vector3::SIDE_DOWN){
$this->meta = $face;
if($face === 1){
if($face === Vector3::SIDE_UP){
$rot = floor(($player->yaw * 16 / 360) + 0.5) & 0x0F;
}else{
$rot = $face;

View File

@ -41,7 +41,7 @@ class SnowLayer extends Flowable{
return "Snow Layer";
}
public function canBeReplaced() : bool{
public function canBeReplaced(Block $with = null) : bool{
return true;
}
@ -54,7 +54,7 @@ class SnowLayer extends Flowable{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($block->getSide(Vector3::SIDE_DOWN)->isSolid()){
//TODO: fix placement
$this->getLevel()->setBlock($block, $this, true);
@ -68,13 +68,13 @@ class SnowLayer extends Flowable{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid()){
$this->getLevel()->setBlock($this, Block::get(Block::AIR), false, false);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->level->getBlockLightAt($this->x, $this->y, $this->z) >= 12){
$this->getLevel()->setBlock($this, Block::get(Block::AIR), false, false);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
return Level::BLOCK_UPDATE_RANDOM;
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
abstract class Stair extends Transparent{
@ -129,7 +130,7 @@ abstract class Stair extends Transparent{
}
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$faces = [
0 => 0,
1 => 2,
@ -137,7 +138,7 @@ abstract class Stair extends Transparent{
3 => 3,
];
$this->meta = $faces[$player->getDirection()] & 0x03;
if(($fy > 0.5 and $face !== 1) or $face === 0){
if(($facePos->y > 0.5 and $face !== Vector3::SIDE_UP) or $face === Vector3::SIDE_DOWN){
$this->meta |= 0x04; //Upside-down stairs
}
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -50,7 +50,7 @@ class Sugarcane extends Flowable{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, Block::get(Block::SUGARCANE_BLOCK)));
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::SUGARCANE_BLOCK)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}
@ -84,7 +84,7 @@ class Sugarcane extends Flowable{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getId() === self::AIR){
$this->getLevel()->setBlock($b, Block::get(Block::SUGARCANE_BLOCK), true);
$this->getLevel()->setBlock($b, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
break;
}
}
@ -102,10 +102,10 @@ class Sugarcane extends Flowable{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::SUGARCANE_BLOCK){
$this->getLevel()->setBlock($block, Block::get(Block::SUGARCANE_BLOCK), true);
$this->getLevel()->setBlock($block, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
return true;
}elseif($down->getId() === self::GRASS or $down->getId() === self::DIRT or $down->getId() === self::SAND){
@ -114,7 +114,7 @@ class Sugarcane extends Flowable{
$block2 = $down->getSide(Vector3::SIDE_WEST);
$block3 = $down->getSide(Vector3::SIDE_EAST);
if(($block0 instanceof Water) or ($block1 instanceof Water) or ($block2 instanceof Water) or ($block3 instanceof Water)){
$this->getLevel()->setBlock($block, Block::get(Block::SUGARCANE_BLOCK), true);
$this->getLevel()->setBlock($block, BlockFactory::get(Block::SUGARCANE_BLOCK), true);
return true;
}

View File

@ -60,7 +60,7 @@ class TNT extends Solid{
}
public function ignite(int $fuse = 80){
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
$mot = (new Random())->nextSignedFloat() * M_PI * 2;
$tnt = Entity::createEntity("PrimedTNT", $this->getLevel(), new CompoundTag("", [

View File

@ -36,7 +36,7 @@ class TallGrass extends Flowable{
$this->meta = $meta;
}
public function canBeReplaced() : bool{
public function canBeReplaced(Block $with = null) : bool{
return true;
}
@ -49,7 +49,7 @@ class TallGrass extends Flowable{
return $names[$this->meta & 0x03] ?? "Unknown";
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::GRASS){
$this->getLevel()->setBlock($block, $this, true);
@ -64,7 +64,7 @@ class TallGrass extends Flowable{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){ //Replace with common break method
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true, true);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
return Level::BLOCK_UPDATE_NORMAL;
}

View File

@ -68,16 +68,16 @@ class Torch extends Flowable{
return false;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$below = $this->getSide(Vector3::SIDE_DOWN);
if($target->isTransparent() === false and $face !== 0){
if($target->isTransparent() === false and $face !== Vector3::SIDE_DOWN){
$faces = [
1 => 5,
2 => 4,
3 => 3,
4 => 2,
5 => 1,
Vector3::SIDE_UP => 5,
Vector3::SIDE_NORTH => 4,
Vector3::SIDE_SOUTH => 3,
Vector3::SIDE_WEST => 2,
Vector3::SIDE_EAST => 1,
];
$this->meta = $faces[$face];
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -27,6 +27,7 @@ use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\sound\DoorSound;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Trapdoor extends Transparent{
@ -123,7 +124,7 @@ class Trapdoor extends Transparent{
return $bb;
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$directions = [
0 => 1,
1 => 3,
@ -133,7 +134,7 @@ class Trapdoor extends Transparent{
if($player !== null){
$this->meta = $directions[$player->getDirection() & 0x03];
}
if(($fy > 0.5 and $face !== self::SIDE_UP) or $face === self::SIDE_DOWN){
if(($facePos->y > 0.5 and $face !== self::SIDE_UP) or $face === self::SIDE_DOWN){
$this->meta |= self::MASK_UPPER; //top half of block
}
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -132,7 +132,7 @@ class Vine extends Transparent{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
//TODO: multiple sides
if($target->isSolid()){
$faces = [

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Water extends Liquid{
@ -52,7 +53,7 @@ class Water extends Liquid{
$entity->resetFallDistance();
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$ret = $this->getLevel()->setBlock($this, $this, true, false);
$this->getLevel()->scheduleDelayedBlockUpdate($this, $this->tickRate());

View File

@ -57,7 +57,7 @@ class WaterLily extends Flowable{
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
if($target instanceof Water){
$up = $target->getSide(Vector3::SIDE_UP);
if($up->getId() === Block::AIR){

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Wood extends Solid{
@ -53,14 +54,14 @@ class Wood extends Solid{
return $names[$this->meta & 0x03];
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$faces = [
0 => 0,
1 => 0,
2 => 0b1000,
3 => 0b1000,
4 => 0b0100,
5 => 0b0100,
Vector3::SIDE_DOWN => 0,
Vector3::SIDE_UP => 0,
Vector3::SIDE_NORTH => 0b1000,
Vector3::SIDE_SOUTH => 0b1000,
Vector3::SIDE_WEST => 0b0100,
Vector3::SIDE_EAST => 0b0100,
];
$this->meta = ($this->meta & 0x03) | $faces[$face];

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
class WoodenSlab extends Transparent{
@ -77,41 +78,45 @@ class WoodenSlab extends Transparent{
}
}
public function place(Item $item, Block $block, Block $target, int $face, float $fx, float $fy, float $fz, Player $player = null) : bool{
public function canBeReplaced(Block $with = null) : bool{
return $with !== null and $with->getId() === $this->getId() and ($with->getDamage() & 0x07) === ($this->getDamage() & 0x07);
}
public function place(Item $item, Block $block, Block $target, int $face, Vector3 $facePos, Player $player = null) : bool{
$this->meta &= 0x07;
if($face === 0){
if($target->getId() === $this->id and ($target->getDamage() & 0x08) === 0x08 and ($target->getDamage() & 0x07) === ($this->meta)){
$this->getLevel()->setBlock($target, Block::get($this->doubleId, $this->meta), true);
if($face === Vector3::SIDE_DOWN){
if($target->getId() === $this->id and ($target->getDamage() & 0x08) === 0x08 and ($target->getDamage() & 0x07) === $this->meta){
$this->getLevel()->setBlock($target, BlockFactory::get($this->doubleId, $this->meta), true);
return true;
}elseif($block->getId() === $this->id and ($block->getDamage() & 0x07) === ($this->meta)){
$this->getLevel()->setBlock($block, Block::get($this->doubleId, $this->meta), true);
}elseif($block->getId() === $this->id and ($block->getDamage() & 0x07) === $this->meta){
$this->getLevel()->setBlock($block, BlockFactory::get($this->doubleId, $this->meta), true);
return true;
}else{
$this->meta |= 0x08;
}
}elseif($face === 1){
}elseif($face === Vector3::SIDE_UP){
if($target->getId() === $this->id and ($target->getDamage() & 0x08) === 0 and ($target->getDamage() & 0x07) === $this->meta){
$this->getLevel()->setBlock($target, Block::get($this->doubleId, $this->meta), true);
$this->getLevel()->setBlock($target, BlockFactory::get($this->doubleId, $this->meta), true);
return true;
}elseif($block->getId() === $this->id and ($block->getDamage() & 0x07) === $this->meta){
$this->getLevel()->setBlock($block, Block::get($this->doubleId, $this->meta), true);
$this->getLevel()->setBlock($block, BlockFactory::get($this->doubleId, $this->meta), true);
return true;
}
}else{ //TODO: collision
if($block->getId() === $this->id){
if(($block->getDamage() & 0x07) === $this->meta){
$this->getLevel()->setBlock($block, Block::get($this->doubleId, $this->meta), true);
$this->getLevel()->setBlock($block, BlockFactory::get($this->doubleId, $this->meta), true);
return true;
}
return false;
}else{
if($fy > 0.5){
if($facePos->y > 0.5){
$this->meta |= 0x08;
}
}

View File

@ -32,7 +32,7 @@ class WoodenStairs extends Stair{
return 2;
}
public function getResistance() : float{
public function getBlastResistance() : float{
return 15;
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\command\defaults;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\event\TranslationContainer;
@ -183,7 +183,7 @@ class ParticleCommand extends VanillaCommand{
break;
case "terrain":
if($data !== null and $data !== 0){
return new TerrainParticle($pos, Block::get($data));
return new TerrainParticle($pos, BlockFactory::get($data));
}
break;
case "heart":
@ -211,7 +211,7 @@ class ParticleCommand extends VanillaCommand{
}elseif(strpos($name, "blockcrack_") === 0){
$d = explode("_", $name);
if(count($d) === 2){
return new TerrainParticle($pos, Block::get($d[1] & 0xff, $d[1] >> 12));
return new TerrainParticle($pos, BlockFactory::get($d[1] & 0xff, $d[1] >> 12));
}
}elseif(strpos($name, "blockdust_") === 0){
$d = explode("_", $name);

View File

@ -62,14 +62,12 @@ class Arrow extends Projectile{
}
}
public function onUpdate(int $currentTick) : bool{
public function entityBaseTick(int $tickDiff = 1) : bool{
if($this->closed){
return false;
}
$this->timings->startTiming();
$hasUpdate = parent::onUpdate($currentTick);
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->onGround or $this->hadCollision){
$this->setCritical(false);
@ -80,8 +78,6 @@ class Arrow extends Projectile{
$hasUpdate = true;
}
$this->timings->stopTiming();
return $hasUpdate;
}

View File

@ -27,6 +27,7 @@ declare(strict_types=1);
namespace pocketmine\entity;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\Water;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDespawnEvent;
@ -64,6 +65,8 @@ use pocketmine\Server;
abstract class Entity extends Location implements Metadatable{
const MOTION_THRESHOLD = 0.00001;
const NETWORK_ID = -1;
const DATA_TYPE_BYTE = 0;
@ -273,6 +276,8 @@ abstract class Entity extends Location implements Metadatable{
public $lastMotionY;
/** @var float */
public $lastMotionZ;
/** @var bool */
protected $forceMovementUpdate = false;
/** @var float */
public $lastYaw;
@ -1018,13 +1023,13 @@ abstract class Entity extends Location implements Metadatable{
$diffY = $y - $j;
$diffZ = $z - $k;
if(Block::$solid[$this->level->getBlockIdAt($i, $j, $k)]){
$flag = !Block::$solid[$this->level->getBlockIdAt($i - 1, $j, $k)];
$flag1 = !Block::$solid[$this->level->getBlockIdAt($i + 1, $j, $k)];
$flag2 = !Block::$solid[$this->level->getBlockIdAt($i, $j - 1, $k)];
$flag3 = !Block::$solid[$this->level->getBlockIdAt($i, $j + 1, $k)];
$flag4 = !Block::$solid[$this->level->getBlockIdAt($i, $j, $k - 1)];
$flag5 = !Block::$solid[$this->level->getBlockIdAt($i, $j, $k + 1)];
if(BlockFactory::$solid[$this->level->getBlockIdAt($i, $j, $k)]){
$flag = !BlockFactory::$solid[$this->level->getBlockIdAt($i - 1, $j, $k)];
$flag1 = !BlockFactory::$solid[$this->level->getBlockIdAt($i + 1, $j, $k)];
$flag2 = !BlockFactory::$solid[$this->level->getBlockIdAt($i, $j - 1, $k)];
$flag3 = !BlockFactory::$solid[$this->level->getBlockIdAt($i, $j + 1, $k)];
$flag4 = !BlockFactory::$solid[$this->level->getBlockIdAt($i, $j, $k - 1)];
$flag5 = !BlockFactory::$solid[$this->level->getBlockIdAt($i, $j, $k + 1)];
$direction = -1;
$limit = 9999;
@ -1227,6 +1232,35 @@ abstract class Entity extends Location implements Metadatable{
$this->level->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $pk);
}
protected function applyDragBeforeGravity() : bool{
return false;
}
protected function applyGravity(){
$this->motionY -= $this->gravity;
}
protected function tryChangeMovement(){
$friction = 1 - $this->drag;
if(!$this->onGround){
if($this->applyDragBeforeGravity()){
$this->motionY *= $friction;
}
$this->applyGravity();
if(!$this->applyDragBeforeGravity()){
$this->motionY *= $friction;
}
}else{
$friction = $this->level->getBlock($this->floor()->subtract(0, 1, 0))->getFrictionFactor();
}
$this->motionX *= $friction;
$this->motionZ *= $friction;
}
/**
* @return Vector3
*/
@ -1269,16 +1303,34 @@ abstract class Entity extends Location implements Metadatable{
$this->timings->startTiming();
if($this->hasMovementUpdate()){
$this->tryChangeMovement();
$this->move($this->motionX, $this->motionY, $this->motionZ);
if(abs($this->motionX) <= self::MOTION_THRESHOLD){
$this->motionX = 0;
}
if(abs($this->motionY) <= self::MOTION_THRESHOLD){
$this->motionY = 0;
}
if(abs($this->motionZ) <= self::MOTION_THRESHOLD){
$this->motionZ = 0;
}
$this->updateMovement();
$this->forceMovementUpdate = false;
}
Timings::$timerEntityBaseTick->startTiming();
$hasUpdate = $this->entityBaseTick($tickDiff);
Timings::$timerEntityBaseTick->stopTiming();
$this->updateMovement();
$this->timings->stopTiming();
//if($this->isStatic())
return $hasUpdate;
return ($hasUpdate or $this->hasMovementUpdate());
//return !($this instanceof Player);
}
@ -1286,6 +1338,31 @@ abstract class Entity extends Location implements Metadatable{
$this->level->updateEntities[$this->id] = $this;
}
/**
* Flags the entity as needing a movement update on the next tick. Setting this forces a movement update even if the
* entity's motion is zero. Used to trigger movement updates when blocks change near entities.
*
* @param bool $value
*/
final public function setForceMovementUpdate(bool $value = true){
$this->forceMovementUpdate = $value;
$this->onGround = false;
}
/**
* Returns whether the entity needs a movement update on the next tick.
* @return bool
*/
final public function hasMovementUpdate() : bool{
return (
$this->forceMovementUpdate or
abs($this->motionX) > self::MOTION_THRESHOLD or
abs($this->motionY) > self::MOTION_THRESHOLD or
abs($this->motionZ) > self::MOTION_THRESHOLD or
!$this->onGround
);
}
public function isOnFire() : bool{
return $this->fireTicks > 0;
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\entity;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\event\entity\EntityBlockChangeEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item as ItemItem;
@ -80,34 +80,14 @@ class FallingSand extends Entity{
}
}
public function onUpdate(int $currentTick) : bool{
public function entityBaseTick(int $tickDiff = 1) : bool{
if($this->closed){
return false;
}
$this->timings->startTiming();
$tickDiff = $currentTick - $this->lastUpdate;
if($tickDiff <= 0 and !$this->justCreated){
return true;
}
$this->lastUpdate = $currentTick;
$hasUpdate = $this->entityBaseTick($tickDiff);
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->isAlive()){
$this->motionY -= $this->gravity;
$this->move($this->motionX, $this->motionY, $this->motionZ);
$friction = 1 - $this->drag;
$this->motionX *= $friction;
$this->motionY *= 1 - $this->drag;
$this->motionZ *= $friction;
$pos = (new Vector3($this->x - 0.5, $this->y, $this->z - 0.5))->floor();
if($this->onGround){
@ -117,18 +97,16 @@ class FallingSand extends Entity{
//FIXME: anvils are supposed to destroy torches
$this->getLevel()->dropItem($this, ItemItem::get($this->getBlock(), $this->getDamage(), 1));
}else{
$this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, Block::get($this->getBlock(), $this->getDamage())));
$this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, BlockFactory::get($this->getBlock(), $this->getDamage())));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($pos, $ev->getTo(), true);
}
}
$hasUpdate = true;
}
$this->updateMovement();
}
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
return $hasUpdate;
}
public function getBlock(){

View File

@ -98,24 +98,14 @@ class Item extends Entity{
}
}
public function onUpdate(int $currentTick) : bool{
public function entityBaseTick(int $tickDiff = 1) : bool{
if($this->closed){
return false;
}
$tickDiff = $currentTick - $this->lastUpdate;
if($tickDiff <= 0 and !$this->justCreated){
return true;
}
$this->lastUpdate = $currentTick;
$this->timings->startTiming();
$hasUpdate = $this->entityBaseTick($tickDiff);
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->isAlive()){
if($this->pickupDelay > 0 and $this->pickupDelay < 32767){ //Infinite delay
$this->pickupDelay -= $tickDiff;
if($this->pickupDelay < 0){
@ -123,30 +113,6 @@ class Item extends Entity{
}
}
$this->motionY -= $this->gravity;
if($this->checkObstruction($this->x, $this->y, $this->z)){
$hasUpdate = true;
}
$this->move($this->motionX, $this->motionY, $this->motionZ);
$friction = 1 - $this->drag;
if($this->onGround and (abs($this->motionX) > 0.00001 or abs($this->motionZ) > 0.00001)){
$friction = $this->getLevel()->getBlock($this->temporalVector->setComponents((int) floor($this->x), (int) floor($this->y - 1), (int) floor($this->z) - 1))->getFrictionFactor() * $friction;
}
$this->motionX *= $friction;
$this->motionY *= 1 - $this->drag;
$this->motionZ *= $friction;
if($this->onGround){
$this->motionY *= -0.5;
}
$this->updateMovement();
if($this->age > 6000){
$this->server->getPluginManager()->callEvent($ev = new ItemDespawnEvent($this));
if($ev->isCancelled()){
@ -159,9 +125,16 @@ class Item extends Entity{
}
$this->timings->stopTiming();
return $hasUpdate;
}
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
protected function tryChangeMovement(){
$this->checkObstruction($this->x, $this->y, $this->z);
parent::tryChangeMovement();
}
protected function applyDragBeforeGravity() : bool{
return true;
}
public function saveNBT(){

View File

@ -79,58 +79,27 @@ class PrimedTNT extends Entity implements Explosive{
$this->namedtag->Fuse = new ByteTag("Fuse", $this->fuse);
}
public function onUpdate(int $currentTick) : bool{
public function entityBaseTick(int $tickDiff = 1) : bool{
if($this->closed){
return false;
}
$this->timings->startTiming();
$tickDiff = $currentTick - $this->lastUpdate;
if($tickDiff <= 0 and !$this->justCreated){
return true;
}
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->fuse % 5 === 0){ //don't spam it every tick, it's not necessary
$this->setDataProperty(self::DATA_FUSE_LENGTH, self::DATA_TYPE_INT, $this->fuse);
}
$this->lastUpdate = $currentTick;
$hasUpdate = $this->entityBaseTick($tickDiff);
if($this->isAlive()){
$this->motionY -= $this->gravity;
$this->move($this->motionX, $this->motionY, $this->motionZ);
$friction = 1 - $this->drag;
$this->motionX *= $friction;
$this->motionY *= $friction;
$this->motionZ *= $friction;
$this->updateMovement();
if($this->onGround){
$this->motionY *= -0.5;
$this->motionX *= 0.7;
$this->motionZ *= 0.7;
}
$this->fuse -= $tickDiff;
if($this->fuse <= 0){
$this->kill();
$this->explode();
}
}
return $hasUpdate or $this->fuse >= 0 or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
return $hasUpdate or $this->fuse >= 0;
}
public function explode(){

View File

@ -108,28 +108,20 @@ abstract class Projectile extends Entity{
$this->namedtag->Age = new ShortTag("Age", $this->age);
}
public function onUpdate(int $currentTick) : bool{
protected function applyDragBeforeGravity() : bool{
return true;
}
public function entityBaseTick(int $tickDiff = 1) : bool{
if($this->closed){
return false;
}
$tickDiff = $currentTick - $this->lastUpdate;
if($tickDiff <= 0 and !$this->justCreated){
return true;
}
$this->lastUpdate = $currentTick;
$hasUpdate = $this->entityBaseTick($tickDiff);
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->isAlive()){
$movingObjectPosition = null;
if(!$this->isCollided){
$this->motionY -= $this->gravity;
}
$moveVector = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
$list = $this->getLevel()->getCollidingEntities($this->boundingBox->addCoord($this->motionX, $this->motionY, $this->motionZ)->expand(1, 1, 1), $this);
@ -170,8 +162,6 @@ abstract class Projectile extends Entity{
}
}
$this->move($this->motionX, $this->motionY, $this->motionZ);
if($this->isCollided and !$this->hadCollision){ //Collided with a block
$this->hadCollision = true;
@ -181,20 +171,16 @@ abstract class Projectile extends Entity{
$this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this));
return false;
}elseif(!$this->isCollided and $this->hadCollision){ //Collided with block, but block later removed
//This currently doesn't work because the arrow's motion is all zeros when it's hit a block, so move() doesn't do any collision checks.
//TODO: fix this
}elseif(!$this->isCollided and $this->hadCollision){ //Previously collided with block, but block later removed
$this->hadCollision = false;
}
if(!$this->hadCollision or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001){
if(!$this->hadCollision or abs($this->motionX) > self::MOTION_THRESHOLD or abs($this->motionY) > self::MOTION_THRESHOLD or abs($this->motionZ) > self::MOTION_THRESHOLD){
$f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2));
$this->yaw = (atan2($this->motionX, $this->motionZ) * 180 / M_PI);
$this->pitch = (atan2($this->motionY, $f) * 180 / M_PI);
$hasUpdate = true;
}
$this->updateMovement();
}
return $hasUpdate;

View File

@ -42,22 +42,18 @@ class Snowball extends Projectile{
parent::__construct($level, $nbt, $shootingEntity);
}
public function onUpdate(int $currentTick) : bool{
public function entityBaseTick(int $tickDiff = 1) : bool{
if($this->closed){
return false;
}
$this->timings->startTiming();
$hasUpdate = parent::onUpdate($currentTick);
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->age > 1200 or $this->isCollided){
$this->kill();
$hasUpdate = true;
}
$this->timings->stopTiming();
return $hasUpdate;
}

View File

@ -78,21 +78,19 @@ class Squid extends WaterAnimal{
}
public function onUpdate(int $currentTick) : bool{
public function entityBaseTick(int $tickDiff = 1) : bool{
if($this->closed !== false){
return false;
}
if(++$this->switchDirectionTicker === 100){
if(++$this->switchDirectionTicker === 100 or $this->isCollided){
$this->switchDirectionTicker = 0;
if(mt_rand(0, 100) < 50){
$this->swimDirection = null;
}
}
$this->timings->startTiming();
$hasUpdate = parent::onUpdate($currentTick);
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->isAlive()){
@ -102,7 +100,6 @@ class Squid extends WaterAnimal{
$inWater = $this->isInsideOfWater();
if(!$inWater){
$this->motionY -= $this->gravity;
$this->swimDirection = null;
}elseif($this->swimDirection !== null){
if($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2 <= $this->swimDirection->lengthSquared()){
@ -115,34 +112,18 @@ class Squid extends WaterAnimal{
$this->swimSpeed = mt_rand(50, 100) / 2000;
}
$expectedPos = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
$this->move($this->motionX, $this->motionY, $this->motionZ);
if($expectedPos->distanceSquared($this) > 0){
$this->swimDirection = $this->generateRandomDirection();
$this->swimSpeed = mt_rand(50, 100) / 2000;
}
$friction = 1 - $this->drag;
$this->motionX *= $friction;
$this->motionY *= 1 - $this->drag;
$this->motionZ *= $friction;
$f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2));
$this->yaw = (-atan2($this->motionX, $this->motionZ) * 180 / M_PI);
$this->pitch = (-atan2($f, $this->motionY) * 180 / M_PI);
if($this->onGround){
$this->motionY *= -0.5;
}
}
$this->timings->stopTiming();
return $hasUpdate;
}
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
protected function applyGravity(){
if(!$this->isInsideOfWater()){
parent::applyGravity();
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\event\player;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
use pocketmine\level\Position;
@ -63,7 +64,7 @@ class PlayerInteractEvent extends PlayerEvent implements Cancellable{
$this->touchVector = new Vector3(0, 0, 0);
}else{
$this->touchVector = $block;
$this->blockTouched = Block::get(0, 0, new Position(0, 0, 0, $player->level));
$this->blockTouched = BlockFactory::get(0, 0, new Position(0, 0, 0, $player->level));
}
$this->player = $player;
$this->item = $item;

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class Bed extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::BED_BLOCK);
$this->block = BlockFactory::get(Block::BED_BLOCK);
parent::__construct(self::BED, $meta, $count, "Bed");
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class BeetrootSeeds extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::BEETROOT_BLOCK);
$this->block = BlockFactory::get(Block::BEETROOT_BLOCK);
parent::__construct(self::BEETROOT_SEEDS, $meta, $count, "Beetroot Seeds");
}
}

View File

@ -25,9 +25,11 @@ namespace pocketmine\item;
use pocketmine\block\Air;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\Liquid;
use pocketmine\event\player\PlayerBucketFillEvent;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Bucket extends Item{
@ -47,8 +49,8 @@ class Bucket extends Item{
return 0;
}
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
$targetBlock = Block::get($this->meta);
public function onActivate(Level $level, Player $player, Block $block, Block $target, int $face, Vector3 $facePos) : bool{
$targetBlock = BlockFactory::get($this->meta);
if($targetBlock instanceof Air){
if($target instanceof Liquid and $target->getDamage() === 0){
@ -56,7 +58,7 @@ class Bucket extends Item{
$result->setDamage($target->getId());
$player->getServer()->getPluginManager()->callEvent($ev = new PlayerBucketFillEvent($player, $block, $face, $this, $result));
if(!$ev->isCancelled()){
$player->getLevel()->setBlock($target, Block::get(Block::AIR), true, true);
$player->getLevel()->setBlock($target, BlockFactory::get(Block::AIR), true, true);
if($player->isSurvival()){
$player->getInventory()->setItemInHand($ev->getItem());
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class Cake extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::CAKE_BLOCK);
$this->block = BlockFactory::get(Block::CAKE_BLOCK);
parent::__construct(self::CAKE, $meta, $count, "Cake");
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class Carrot extends Food{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::CARROT_BLOCK);
$this->block = BlockFactory::get(Block::CARROT_BLOCK);
parent::__construct(self::CARROT, $meta, $count, "Carrot");
}

View File

@ -24,9 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\Fire;
use pocketmine\block\Solid;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
class FlintSteel extends Tool{
@ -34,9 +36,9 @@ class FlintSteel extends Tool{
parent::__construct(self::FLINT_STEEL, $meta, $count, "Flint and Steel");
}
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
public function onActivate(Level $level, Player $player, Block $block, Block $target, int $face, Vector3 $facePos) : bool{
if($block->getId() === self::AIR and ($target instanceof Solid)){
$level->setBlock($block, Block::get(Block::FIRE), true);
$level->setBlock($block, BlockFactory::get(Block::FIRE), true);
if(($player->gamemode & 0x01) === 0 and $this->useOn($block)){
if($this->getDamage() >= $this->getMaxDurability()){
$player->getInventory()->setItemInHand(new Item(Item::AIR, 0, 0));

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class FlowerPot extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::FLOWER_POT_BLOCK);
$this->block = BlockFactory::get(Block::FLOWER_POT_BLOCK);
parent::__construct(self::FLOWER_POT, $meta, $count, "Flower Pot");
}
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class IronDoor extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::IRON_DOOR_BLOCK);
$this->block = BlockFactory::get(Block::IRON_DOOR_BLOCK);
parent::__construct(self::IRON_DOOR, $meta, $count, "Iron Door");
}

View File

@ -27,9 +27,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\entity\Entity;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
@ -327,7 +329,7 @@ class Item implements ItemIds, \JsonSerializable{
public static function get(int $id, int $meta = 0, int $count = 1, $tags = "") : Item{
try{
if($id < 256){
return (new ItemBlock(Block::get($id, $meta), $meta, $count))->setCompoundTag($tags);
return (new ItemBlock(BlockFactory::get($id, $meta), $meta, $count))->setCompoundTag($tags);
}else{
$class = self::$list[$id];
if($class === null){
@ -387,8 +389,8 @@ class Item implements ItemIds, \JsonSerializable{
$this->meta = $meta !== -1 ? $meta & 0xffff : -1;
$this->count = $count;
$this->name = $name;
if(!isset($this->block) and $this->id <= 0xff and isset(Block::$list[$this->id])){
$this->block = Block::get($this->id, $this->meta);
if(!isset($this->block) and $this->id <= 0xff and isset(BlockFactory::$list[$this->id])){
$this->block = BlockFactory::get($this->id, $this->meta);
$this->name = $this->block->getName();
}
}
@ -877,7 +879,7 @@ class Item implements ItemIds, \JsonSerializable{
if($this->block instanceof Block){
return clone $this->block;
}else{
return Block::get(self::AIR);
return BlockFactory::get(self::AIR);
}
}
@ -982,18 +984,16 @@ class Item implements ItemIds, \JsonSerializable{
/**
* Called when a player uses this item on a block.
*
* @param Level $level
* @param Player $player
* @param Block $block
* @param Block $target
* @param int $face
* @param float $fx
* @param float $fy
* @param float $fz
* @param Level $level
* @param Player $player
* @param Block $block
* @param Block $target
* @param int $face
* @param Vector3 $facePos
*
* @return bool
*/
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
public function onActivate(Level $level, Player $player, Block $block, Block $target, int $face, Vector3 $facePos) : bool{
return false;
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class ItemFrame extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::ITEM_FRAME_BLOCK);
$this->block = BlockFactory::get(Block::ITEM_FRAME_BLOCK);
parent::__construct(self::ITEM_FRAME, $meta, $count, "Item Frame");
}
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class MelonSeeds extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::MELON_STEM);
$this->block = BlockFactory::get(Block::MELON_STEM);
parent::__construct(self::MELON_SEEDS, $meta, $count, "Melon Seeds");
}
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class NetherWart extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::NETHER_WART_PLANT);
$this->block = BlockFactory::get(Block::NETHER_WART_PLANT);
parent::__construct(self::NETHER_WART, $meta, $count, "Nether Wart");
}
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Painting extends Item{
@ -32,7 +33,7 @@ class Painting extends Item{
parent::__construct(self::PAINTING, $meta, $count, "Painting");
}
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
public function onActivate(Level $level, Player $player, Block $block, Block $target, int $face, Vector3 $facePos) : bool{
if($target->isTransparent() === false and $face > 1 and $block->isSolid() === false){
$faces = [
2 => 1,

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class Potato extends Food{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::POTATO_BLOCK);
$this->block = BlockFactory::get(Block::POTATO_BLOCK);
parent::__construct(self::POTATO, $meta, $count, "Potato");
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class PumpkinSeeds extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::PUMPKIN_STEM);
$this->block = BlockFactory::get(Block::PUMPKIN_STEM);
parent::__construct(self::PUMPKIN_SEEDS, $meta, $count, "Pumpkin Seeds");
}
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class Sign extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::SIGN_POST);
$this->block = BlockFactory::get(Block::SIGN_POST);
parent::__construct(self::SIGN, $meta, $count, "Sign");
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class Skull extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::SKULL_BLOCK);
$this->block = BlockFactory::get(Block::SKULL_BLOCK);
parent::__construct(self::SKULL, $meta, $count, "Mob Head");
}
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\entity\Entity;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\FloatTag;
@ -38,7 +39,7 @@ class SpawnEgg extends Item{
parent::__construct(self::SPAWN_EGG, $meta, $count, "Spawn Egg");
}
public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
public function onActivate(Level $level, Player $player, Block $block, Block $target, int $face, Vector3 $facePos) : bool{
$nbt = new CompoundTag("", [
new ListTag("Pos", [
new DoubleTag("", $block->getX() + 0.5),

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class Sugarcane extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::SUGARCANE_BLOCK);
$this->block = BlockFactory::get(Block::SUGARCANE_BLOCK);
parent::__construct(self::SUGARCANE, $meta, $count, "Sugar Cane");
}
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class WheatSeeds extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::WHEAT_BLOCK);
$this->block = BlockFactory::get(Block::WHEAT_BLOCK);
parent::__construct(self::WHEAT_SEEDS, $meta, $count, "Wheat Seeds");
}
}

View File

@ -24,10 +24,11 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
class WoodenDoor extends Item{
public function __construct($meta = 0, $count = 1){
$this->block = Block::get(Block::WOODEN_DOOR_BLOCK);
$this->block = BlockFactory::get(Block::WOODEN_DOOR_BLOCK);
parent::__construct(self::WOODEN_DOOR, $meta, $count, "Wooden Door");
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\level;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\TNT;
use pocketmine\entity\Entity;
use pocketmine\event\block\BlockUpdateEvent;
@ -32,6 +33,7 @@ use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityExplodeEvent;
use pocketmine\item\Item;
use pocketmine\level\format\SubChunkInterface;
use pocketmine\level\particle\HugeExplodeSeedParticle;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Math;
@ -69,7 +71,14 @@ class Explosion{
}
$vector = new Vector3(0, 0, 0);
$vBlock = new Vector3(0, 0, 0);
$vBlock = new Position(0, 0, 0, $this->level);
$currentX = ((int) $this->source->x) >> 4;
$currentZ = ((int) $this->source->z) >> 4;
$currentChunk = $this->level->getChunk($currentX, $currentZ, true);
$currentSubY = ((int) $this->source->y) >> 4;
$currentSubChunk = $currentChunk->getSubChunk($currentSubY);
$mRays = (int) ($this->rays - 1);
for($i = 0; $i < $this->rays; ++$i){
@ -89,19 +98,37 @@ class Explosion{
$vBlock->x = $pointerX >= $x ? $x : $x - 1;
$vBlock->y = $pointerY >= $y ? $y : $y - 1;
$vBlock->z = $pointerZ >= $z ? $z : $z - 1;
if(!$this->level->isInWorld($vBlock->x, $vBlock->y, $vBlock->z)){
break;
}
$block = $this->level->getBlock($vBlock);
if($block->getId() !== 0){
$blastForce -= ($block->getResistance() / 5 + 0.3) * $this->stepLen;
if(($vBlock->x >> 4) !== $currentX or ($vBlock->z >> 4) !== $currentZ){
$currentX = $vBlock->x >> 4;
$currentZ = $vBlock->z >> 4;
$currentChunk = $this->level->getChunk($currentX, $currentZ);
if($currentChunk === null){
continue;
}
}
if(($vBlock->y >> 4) !== $currentSubY){
$currentSubY = $vBlock->y >> 4;
$currentSubChunk = $currentChunk->getSubChunk($currentSubY);
if($currentSubChunk === null){
continue;
}
}
$blockId = $currentSubChunk->getBlockId($vBlock->x & 0x0f, $vBlock->y & 0x0f, $vBlock->z & 0x0f);
if($blockId !== 0){
$blastForce -= (BlockFactory::$blastResistance[$blockId] / 5 + 0.3) * $this->stepLen;
if($blastForce > 0){
if(!isset($this->affectedBlocks[$index = Level::blockHash($block->x, $block->y, $block->z)])){
$this->affectedBlocks[$index] = $block;
if(!isset($this->affectedBlocks[$index = Level::blockHash($vBlock->x, $vBlock->y, $vBlock->z)])){
$this->affectedBlocks[$index] = BlockFactory::get($blockId, $currentSubChunk->getBlockData($vBlock->x & 0x0f, $vBlock->y & 0x0f, $vBlock->z & 0x0f), $vBlock);
}
}
}
$pointerX += $vector->x;
$pointerY += $vector->y;
$pointerZ += $vector->z;
@ -183,6 +210,9 @@ class Explosion{
for($side = 0; $side <= 5; $side++){
$sideBlock = $pos->getSide($side);
if(!$this->level->isInWorld($sideBlock->x, $sideBlock->y, $sideBlock->z)){
continue;
}
if(!isset($this->affectedBlocks[$index = Level::blockHash($sideBlock->x, $sideBlock->y, $sideBlock->z)]) and !isset($updateBlocks[$index])){
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->level->getBlock($sideBlock)));
if(!$ev->isCancelled()){

View File

@ -29,6 +29,7 @@ namespace pocketmine\level;
use pocketmine\block\Air;
use pocketmine\block\Beetroot;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\BrownMushroom;
use pocketmine\block\Cactus;
use pocketmine\block\Carrot;
@ -311,7 +312,7 @@ class Level implements ChunkManager, Metadatable{
* @throws \Exception
*/
public function __construct(Server $server, string $name, string $path, string $provider){
$this->blockStates = Block::$fullList;
$this->blockStates = BlockFactory::$fullList;
$this->levelId = static::$levelIdCounter++;
$this->blockMetadata = new BlockMetadataStore($this);
$this->server = $server;
@ -911,7 +912,7 @@ class Level implements ChunkManager, Metadatable{
}
public function addRandomTickedBlock(int $id){
$this->randomTickBlocks[$id] = get_class(Block::$list[$id]);
$this->randomTickBlocks[$id] = get_class(BlockFactory::$list[$id]);
}
public function removeRandomTickedBlock(int $id){
@ -1388,7 +1389,7 @@ class Level implements ChunkManager, Metadatable{
if($yPlusOne === $oldHeightMap){ //Block changed directly beneath the heightmap. Check if a block was removed or changed to a different light-filter.
$newHeightMap = $this->getChunk($x >> 4, $z >> 4)->recalculateHeightMapColumn($x & 0x0f, $z & 0x0f);
}elseif($yPlusOne > $oldHeightMap){ //Block changed above the heightmap.
if(Block::$lightFilter[$sourceId] > 1 or Block::$diffusesSkyLight[$sourceId]){
if(BlockFactory::$lightFilter[$sourceId] > 1 or BlockFactory::$diffusesSkyLight[$sourceId]){
$this->setHeightMap($x, $z, $yPlusOne);
$newHeightMap = $yPlusOne;
}else{ //Block changed which has no effect on direct sky light, for example placing or removing glass.
@ -1410,7 +1411,7 @@ class Level implements ChunkManager, Metadatable{
$update->setAndUpdateLight($x, $i, $z, 15);
}
}else{ //No heightmap change, block changed "underground"
$update->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentBlockSkyLight($x, $y, $z) - Block::$lightFilter[$sourceId]));
$update->setAndUpdateLight($x, $y, $z, max(0, $this->getHighestAdjacentBlockSkyLight($x, $y, $z) - BlockFactory::$lightFilter[$sourceId]));
}
$update->execute();
@ -1442,7 +1443,7 @@ class Level implements ChunkManager, Metadatable{
$this->timings->doBlockLightUpdates->startTiming();
$id = $this->getBlockIdAt($x, $y, $z);
$newLevel = max(Block::$light[$id], $this->getHighestAdjacentBlockLight($x, $y, $z) - Block::$lightFilter[$id]);
$newLevel = max(BlockFactory::$light[$id], $this->getHighestAdjacentBlockLight($x, $y, $z) - BlockFactory::$lightFilter[$id]);
$update = new BlockLightUpdate($this);
$update->setAndUpdateLight($x, $y, $z, $newLevel);
@ -1507,7 +1508,8 @@ class Level implements ChunkManager, Metadatable{
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block));
if(!$ev->isCancelled()){
foreach($this->getNearbyEntities(new AxisAlignedBB($block->x - 1, $block->y - 1, $block->z - 1, $block->x + 1, $block->y + 1, $block->z + 1)) as $entity){
foreach($this->getNearbyEntities(new AxisAlignedBB($block->x - 1, $block->y - 1, $block->z - 1, $block->x + 2, $block->y + 2, $block->z + 2)) as $entity){
$entity->setForceMovementUpdate();
$entity->scheduleUpdate();
}
$ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
@ -1652,7 +1654,7 @@ class Level implements ChunkManager, Metadatable{
$above = $this->getBlock(new Vector3($target->x, $target->y + 1, $target->z));
if($above !== null){
if($above->getId() === Item::FIRE){
$this->setBlock($above, Block::get(Block::AIR), true);
$this->setBlock($above, BlockFactory::get(Block::AIR), true);
}
}
@ -1698,21 +1700,23 @@ class Level implements ChunkManager, Metadatable{
/**
* Uses a item on a position and face, placing it or activating the block
*
* @param Vector3 $vector
* @param Item $item
* @param int $face
* @param float $fx default 0.0
* @param float $fy default 0.0
* @param float $fz default 0.0
* @param Player $player default null
* @param bool $playSound Whether to play a block-place sound if the block was placed successfully.
* @param Vector3 $vector
* @param Item $item
* @param int $face
* @param Vector3|null $facePos
* @param Player|null $player default null
* @param bool $playSound Whether to play a block-place sound if the block was placed successfully.
*
* @return bool
*/
public function useItemOn(Vector3 $vector, Item &$item, int $face, float $fx = 0.0, float $fy = 0.0, float $fz = 0.0, Player $player = null, bool $playSound = false) : bool{
public function useItemOn(Vector3 $vector, Item &$item, int $face, Vector3 $facePos = null, Player $player = null, bool $playSound = false) : bool{
$target = $this->getBlock($vector);
$block = $target->getSide($face);
if($facePos === null){
$facePos = new Vector3(0.0, 0.0, 0.0);
}
if($block->y >= $this->provider->getWorldHeight() or $block->y < 0){
//TODO: build height limit messages for custom world heights and mcregion cap
return false;
@ -1757,7 +1761,7 @@ class Level implements ChunkManager, Metadatable{
return true;
}
if(!$player->isSneaking() and $item->onActivate($this, $player, $block, $target, $face, $fx, $fy, $fz)){
if(!$player->isSneaking() and $item->onActivate($this, $player, $block, $target, $face, $facePos)){
if($item->getCount() <= 0){
$item = Item::get(Item::AIR, 0, 0);
@ -1771,23 +1775,20 @@ class Level implements ChunkManager, Metadatable{
return true;
}
if($item->canBePlaced()){
$hand = $item->getBlock();
$hand->position($block);
}else{
if(!$item->canBePlaced()){
return false;
}
if(!($block->canBeReplaced() === true or ($hand->getId() === Item::WOODEN_SLAB and $block->getId() === Item::WOODEN_SLAB) or ($hand->getId() === Item::STONE_SLAB and $block->getId() === Item::STONE_SLAB))){
return false;
}
$hand = $item->getBlock();
if($target->canBeReplaced() === true){
if($target->canBeReplaced($hand)){
$block = $target;
$hand->position($block);
//$face = -1;
}elseif(!$block->canBeReplaced($hand)){
return false;
}
$hand->position($block);
if($hand->isSolid() === true and $hand->getBoundingBox() !== null){
$entities = $this->getCollidingEntities($hand->getBoundingBox());
$realCount = 0;
@ -1828,7 +1829,7 @@ class Level implements ChunkManager, Metadatable{
}
}
if($hand->place($item, $block, $target, $face, $fx, $fy, $fz, $player) === false){
if(!$hand->place($item, $block, $target, $face, $facePos, $player)){
return false;
}
@ -2683,7 +2684,7 @@ class Level implements ChunkManager, Metadatable{
$wasAir = ($chunk->getBlockId($x, $y - 1, $z) === 0);
for(; $y > 0; --$y){
$b = $chunk->getFullBlock($x, $y, $z);
$block = Block::get($b >> 4, $b & 0x0f);
$block = BlockFactory::get($b >> 4, $b & 0x0f);
if($this->isFullBlock($block)){
if($wasAir){
$y++;
@ -2696,10 +2697,10 @@ class Level implements ChunkManager, Metadatable{
for(; $y >= 0 and $y < $max; ++$y){
$b = $chunk->getFullBlock($x, $y + 1, $z);
$block = Block::get($b >> 4, $b & 0x0f);
$block = BlockFactory::get($b >> 4, $b & 0x0f);
if(!$this->isFullBlock($block)){
$b = $chunk->getFullBlock($x, $y, $z);
$block = Block::get($b >> 4, $b & 0x0f);
$block = BlockFactory::get($b >> 4, $b & 0x0f);
if(!$this->isFullBlock($block)){
return new Position($spawn->x, $y === (int) $spawn->y ? $spawn->y : $y, $spawn->z, $this);
}

View File

@ -27,24 +27,30 @@ use pocketmine\entity\Entity;
use pocketmine\math\Vector3;
class MovingObjectPosition{
const TYPE_BLOCK_COLLISION = 0;
const TYPE_ENTITY_COLLISION = 1;
/** 0 = block, 1 = entity */
/** @var int */
public $typeOfHit;
/** @var int|null */
public $blockX;
/** @var int|null */
public $blockY;
/** @var int|null */
public $blockZ;
/**
* @var int|null
* Which side was hit. If its -1 then it went the full length of the ray trace.
* Bottom = 0, Top = 1, East = 2, West = 3, North = 4, South = 5.
* -1 or one of the Vector3::SIDE_* constants
*/
public $sideHit;
/** @var Vector3 */
public $hitVector;
/** @var Entity */
/** @var Entity|null */
public $entityHit = null;
protected function __construct(){
@ -62,10 +68,11 @@ class MovingObjectPosition{
*/
public static function fromBlock(int $x, int $y, int $z, int $side, Vector3 $hitVector) : MovingObjectPosition{
$ob = new MovingObjectPosition;
$ob->typeOfHit = 0;
$ob->typeOfHit = self::TYPE_BLOCK_COLLISION;
$ob->blockX = $x;
$ob->blockY = $y;
$ob->blockZ = $z;
$ob->sideHit = $side;
$ob->hitVector = new Vector3($hitVector->x, $hitVector->y, $hitVector->z);
return $ob;
}
@ -77,7 +84,7 @@ class MovingObjectPosition{
*/
public static function fromEntity(Entity $entity) : MovingObjectPosition{
$ob = new MovingObjectPosition;
$ob->typeOfHit = 1;
$ob->typeOfHit = self::TYPE_ENTITY_COLLISION;
$ob->entityHit = $entity;
$ob->hitVector = new Vector3($entity->x, $entity->y, $entity->z);
return $ob;

View File

@ -26,7 +26,7 @@ declare(strict_types=1);
namespace pocketmine\level\format;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\entity\Entity;
use pocketmine\level\Level;
use pocketmine\nbt\NBT;
@ -438,7 +438,7 @@ class Chunk{
public function recalculateHeightMapColumn(int $x, int $z) : int{
$max = $this->getHighestBlockAt($x, $z);
for($y = $max; $y >= 0; --$y){
if(Block::$lightFilter[$id = $this->getBlockId($x, $y, $z)] > 1 or Block::$diffusesSkyLight[$id]){
if(BlockFactory::$lightFilter[$id = $this->getBlockId($x, $y, $z)] > 1 or BlockFactory::$diffusesSkyLight[$id]){
break;
}
}
@ -470,7 +470,7 @@ class Chunk{
$light = 15;
for(; $y >= 0; --$y){
if($light > 0){
$light -= Block::$lightFilter[$this->getBlockId($x, $y, $z)];
$light -= BlockFactory::$lightFilter[$this->getBlockId($x, $y, $z)];
if($light <= 0){
break;
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\level\generator;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\level\generator\biome\Biome;
use pocketmine\level\Level;
use pocketmine\level\SimpleChunkManager;
@ -47,7 +47,7 @@ class GeneratorRegisterTask extends AsyncTask{
}
public function onRun(){
Block::init();
BlockFactory::init();
Biome::init();
$manager = new SimpleChunkManager($this->seed, $this->worldHeight);
$this->saveToThreadStore("generation.level{$this->levelId}.manager", $manager);

Some files were not shown because too many files have changed in this diff Show More