From d6e343c2cf076a8bce946374f3d5682d5f98cb58 Mon Sep 17 00:00:00 2001 From: SOF3 Date: Wed, 24 Aug 2016 17:15:22 +0800 Subject: [PATCH 01/14] Premature optimization again --- src/pocketmine/math/Vector3.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pocketmine/math/Vector3.php b/src/pocketmine/math/Vector3.php index 32a92ebda..c8c9463c5 100644 --- a/src/pocketmine/math/Vector3.php +++ b/src/pocketmine/math/Vector3.php @@ -253,7 +253,7 @@ class Vector3{ if($f < 0 or $f > 1){ return null; }else{ - return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $this->z + $zDiff * $f); + return new Vector3($x, $this->y + $yDiff * $f, $this->z + $zDiff * $f); } } @@ -280,7 +280,7 @@ class Vector3{ if($f < 0 or $f > 1){ return null; }else{ - return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $this->z + $zDiff * $f); + return new Vector3($this->x + $xDiff * $f, $y, $this->z + $zDiff * $f); } } @@ -307,7 +307,7 @@ class Vector3{ if($f < 0 or $f > 1){ return null; }else{ - return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $this->z + $zDiff * $f); + return new Vector3($this->x + $xDiff * $f, $this->y + $yDiff * $f, $z); } } From 6ba4a8fe5c5e719fc8236050fde8874b6ef7e5bc Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 20 Mar 2017 10:20:54 +0000 Subject: [PATCH 02/14] Moved batch packet handling into BatchPacket->handle(), fixed data packet receive timings to include MCPE packet decode time --- src/pocketmine/Player.php | 9 ++-- src/pocketmine/network/Network.php | 52 ++----------------- .../network/mcpe/NetworkSession.php | 12 +++-- .../network/mcpe/RakLibInterface.php | 6 +-- .../network/mcpe/protocol/BatchPacket.php | 27 +++++++++- 5 files changed, 42 insertions(+), 64 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index b93234287..1e6c9474f 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -112,7 +112,6 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; -use pocketmine\network\mcpe\protocol\BatchPacket; use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; @@ -1959,11 +1958,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade return false; } - public function handleBatch(BatchPacket $packet) : bool{ - $this->server->getNetwork()->processBatch($packet, $this); - return true; - } - public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool{ return false; } @@ -3303,6 +3297,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $timings = Timings::getReceiveDataPacketTimings($packet); $timings->startTiming(); + $packet->decode(); + assert($packet->feof(), "Still " . strlen(substr($packet->buffer, $packet->offset)) . " bytes unread in " . get_class($packet)); + $this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet)); if(!$ev->isCancelled() and !$packet->handle($this)){ $this->server->getLogger()->debug("Unhandled " . get_class($packet) . " received from " . $this->getName()); diff --git a/src/pocketmine/network/Network.php b/src/pocketmine/network/Network.php index d7dfc7a3a..1a16800a3 100644 --- a/src/pocketmine/network/Network.php +++ b/src/pocketmine/network/Network.php @@ -55,16 +55,15 @@ use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\ExplodePacket; use pocketmine\network\mcpe\protocol\FullChunkDataPacket; use pocketmine\network\mcpe\protocol\HurtArmorPacket; -use pocketmine\network\mcpe\protocol\MapInfoRequestPacket; -use pocketmine\network\mcpe\protocol\ProtocolInfo; use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InventoryActionPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LoginPacket; -use pocketmine\network\mcpe\protocol\MobEquipmentPacket; +use pocketmine\network\mcpe\protocol\MapInfoRequestPacket; use pocketmine\network\mcpe\protocol\MobArmorEquipmentPacket; +use pocketmine\network\mcpe\protocol\MobEquipmentPacket; use pocketmine\network\mcpe\protocol\MoveEntityPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\PlayerActionPacket; @@ -72,6 +71,7 @@ use pocketmine\network\mcpe\protocol\PlayerFallPacket; use pocketmine\network\mcpe\protocol\PlayerInputPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayStatusPacket; +use pocketmine\network\mcpe\protocol\ProtocolInfo; use pocketmine\network\mcpe\protocol\RemoveBlockPacket; use pocketmine\network\mcpe\protocol\RemoveEntityPacket; use pocketmine\network\mcpe\protocol\ReplaceItemInSlotPacket; @@ -103,9 +103,7 @@ use pocketmine\network\mcpe\protocol\UnknownPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateTradePacket; use pocketmine\network\mcpe\protocol\UseItemPacket; -use pocketmine\Player; use pocketmine\Server; -use pocketmine\utils\BinaryStream; class Network{ @@ -232,50 +230,6 @@ class Network{ return $this->server; } - /** - * Decodes a batch packet and does handling for it. - * - * TODO: Move this out of here - * - * @param BatchPacket $packet - * @param Player $player - * - * @throws \InvalidArgumentException|\InvalidStateException - */ - public function processBatch(BatchPacket $packet, Player $p){ - $rawLen = strlen($packet->payload); - if($rawLen === 0){ - throw new \InvalidArgumentException("BatchPacket payload is empty or packet decode error"); - }elseif($rawLen < 3){ - throw new \InvalidArgumentException("Not enough bytes, expected zlib header"); - } - - $str = zlib_decode($packet->payload, 1024 * 1024 * 64); //Max 64MB - $len = strlen($str); - - if($len === 0){ - throw new \InvalidStateException("Decoded BatchPacket payload is empty"); - } - - $stream = new BinaryStream($str); - - while($stream->offset < $len){ - $buf = $stream->getString(); - - if(($pk = $this->getPacket(ord($buf{0}))) !== null){ - if(!$pk->canBeBatched()){ - throw new \InvalidStateException("Received invalid " . get_class($pk) . " inside BatchPacket"); - } - - $pk->setBuffer($buf, 1); - - $pk->decode(); - assert($pk->feof(), "Still " . strlen(substr($pk->buffer, $pk->offset)) . " bytes unread in " . get_class($pk)); - $p->handleDataPacket($pk); - } - } - } - /** * @param $id * diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index ae790ae9e..66d19d063 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -32,7 +32,6 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; -use pocketmine\network\mcpe\protocol\BatchPacket; use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; @@ -47,6 +46,7 @@ use pocketmine\network\mcpe\protocol\ContainerSetDataPacket; use pocketmine\network\mcpe\protocol\ContainerSetSlotPacket; use pocketmine\network\mcpe\protocol\CraftingDataPacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket; +use pocketmine\network\mcpe\protocol\DataPacket; use pocketmine\network\mcpe\protocol\DisconnectPacket; use pocketmine\network\mcpe\protocol\DropItemPacket; use pocketmine\network\mcpe\protocol\EntityEventPacket; @@ -103,9 +103,17 @@ use pocketmine\network\mcpe\protocol\UpdateAttributesPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateTradePacket; use pocketmine\network\mcpe\protocol\UseItemPacket; +use pocketmine\Server; interface NetworkSession{ + /** + * @return Server + */ + public function getServer(); + + public function handleDataPacket(DataPacket $pk); + public function handleLogin(LoginPacket $packet) : bool; public function handlePlayStatus(PlayStatusPacket $packet) : bool; @@ -116,8 +124,6 @@ interface NetworkSession{ public function handleDisconnect(DisconnectPacket $packet) : bool; - public function handleBatch(BatchPacket $packet) : bool; - public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool; public function handleResourcePackStack(ResourcePackStackPacket $packet) : bool; diff --git a/src/pocketmine/network/mcpe/RakLibInterface.php b/src/pocketmine/network/mcpe/RakLibInterface.php index 9a5b12275..a613d8a41 100644 --- a/src/pocketmine/network/mcpe/RakLibInterface.php +++ b/src/pocketmine/network/mcpe/RakLibInterface.php @@ -132,11 +132,7 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{ try{ if($packet->buffer !== ""){ $pk = $this->getPacket($packet->buffer); - if($pk !== null){ - $pk->decode(); - assert($pk->feof(), "Still " . strlen(substr($pk->buffer, $pk->offset)) . " bytes unread!"); - $this->players[$identifier]->handleDataPacket($pk); - } + $this->players[$identifier]->handleDataPacket($pk); } }catch(\Throwable $e){ if(\pocketmine\DEBUG > 1 and isset($pk)){ diff --git a/src/pocketmine/network/mcpe/protocol/BatchPacket.php b/src/pocketmine/network/mcpe/protocol/BatchPacket.php index 4f952548e..2257655a0 100644 --- a/src/pocketmine/network/mcpe/protocol/BatchPacket.php +++ b/src/pocketmine/network/mcpe/protocol/BatchPacket.php @@ -45,7 +45,32 @@ class BatchPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleBatch($this); + if(strlen($this->payload) < 2){ + throw new \InvalidStateException("Not enough bytes in payload, expected zlib header"); + } + + $str = zlib_decode($this->payload, 1024 * 1024 * 64); //Max 64MB + $len = strlen($str); + + if($len === 0){ + throw new \InvalidStateException("Decoded BatchPacket payload is empty"); + } + + $this->setBuffer($str, 0); + + $network = $session->getServer()->getNetwork(); + while(!$this->feof()){ + $buf = $this->getString(); + $pk = $network->getPacket(ord($buf{0})); + if(!$pk->canBeBatched()){ + throw new \InvalidArgumentException("Received invalid " . get_class($pk) . " inside BatchPacket"); + } + + $pk->setBuffer($buf, 1); + $session->handleDataPacket($pk); + } + + return true; } } \ No newline at end of file From 284c18d40102e91c35108d28473f30256be3b8c2 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 20 Mar 2017 10:58:43 +0000 Subject: [PATCH 03/14] Added debug for mismatched item equipment tool damage packets sent in the wrong order? This could be bad for performance since the entire inventory is resent every time this issue crops up. --- src/pocketmine/Player.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 1e6c9474f..b0c448d95 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2237,6 +2237,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $item = $this->inventory->getItem($packet->inventorySlot); if(!$item->equals($packet->item)){ + $this->server->getLogger()->debug("Tried to equip " . $packet->item . " but have " . $item . " in target slot"); $this->inventory->sendContents($this); return false; } From 0e64d4bbc222fedf28109affb3b50a5b1ca0854f Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 20 Mar 2017 12:21:02 +0000 Subject: [PATCH 04/14] Given Player->iusername a use, added Player->getLowerCaseName() Micro optimizations by not repeatedly lowercasing names when searching --- src/pocketmine/Player.php | 7 +++++++ src/pocketmine/Server.php | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index b0c448d95..324404d0f 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -3571,6 +3571,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade return $this->username; } + /** + * @return string + */ + public function getLowerCaseName() : string{ + return $this->iusername; + } + public function kill(){ if(!$this->spawned){ return; diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 3bf61a76f..1ab35324c 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -817,7 +817,7 @@ class Server{ public function getPlayerExact($name){ $name = strtolower($name); foreach($this->getOnlinePlayers() as $player){ - if(strtolower($player->getName()) === $name){ + if($player->getLowerCaseName() === $name){ return $player; } } @@ -834,7 +834,7 @@ class Server{ $partialName = strtolower($partialName); $matchedPlayers = []; foreach($this->getOnlinePlayers() as $player){ - if(strtolower($player->getName()) === $partialName){ + if($player->getLowerCaseName() === $partialName){ $matchedPlayers = [$player]; break; }elseif(stripos($player->getName(), $partialName) !== false){ From 6a03f8d434b04d200115c504cf6338f30f87385c Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 20 Mar 2017 13:20:34 +0000 Subject: [PATCH 05/14] Fixed server creating resource packs directory inside itself when running from a phar Once again, epic facepalm @dktapps --- src/pocketmine/Server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 1ab35324c..9f0db3dbc 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -1546,7 +1546,7 @@ class Server{ Attribute::init(); $this->craftingManager = new CraftingManager(); - $this->resourceManager = new ResourcePackManager($this, \pocketmine\PATH . "resource_packs" . DIRECTORY_SEPARATOR); + $this->resourceManager = new ResourcePackManager($this, $this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR); $this->pluginManager = new PluginManager($this, $this->commandMap); $this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender); From 47f7af6739537af7a4d356a08aa00eb7feefd1ed Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 20 Mar 2017 21:26:20 +0000 Subject: [PATCH 06/14] Fixed usage reporting cannot be disabled --- src/pocketmine/Server.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index ac6076821..12f8d9eb5 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -2251,7 +2251,9 @@ class Server{ } public function sendUsage($type = SendUsageTask::TYPE_STATUS){ - $this->scheduler->scheduleAsyncTask(new SendUsageTask($this, $type, $this->uniquePlayers)); + if($this->getProperty("anonymous-statistics.enabled", true)){ + $this->scheduler->scheduleAsyncTask(new SendUsageTask($this, $type, $this->uniquePlayers)); + } $this->uniquePlayers = []; } From c040579e090e3461829e42b62db50d0085b81e5b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 21 Mar 2017 15:11:48 +0000 Subject: [PATCH 07/14] Fixed a mistake in spaced command handling Nothing drastic, just a self-defeating line of code. --- src/pocketmine/command/SimpleCommandMap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pocketmine/command/SimpleCommandMap.php b/src/pocketmine/command/SimpleCommandMap.php index 48e30d1ac..566e4d0a1 100644 --- a/src/pocketmine/command/SimpleCommandMap.php +++ b/src/pocketmine/command/SimpleCommandMap.php @@ -188,7 +188,7 @@ class SimpleCommandMap implements CommandMap{ * @return Command|null */ public function matchCommand(string &$commandName, array &$args){ - $count = max(count($args), 255); + $count = min(count($args), 255); for($i = 0; $i < $count; ++$i){ $commandName .= array_shift($args); From 96801be3d3ea8876c503f8cacbad3ff15b284e68 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 23 Mar 2017 11:40:33 +0000 Subject: [PATCH 08/14] Fixed #453 multiple refs to the same cached NBT object tree --- src/pocketmine/item/Item.php | 16 +++++++++++++++- src/pocketmine/item/ItemBlock.php | 4 ---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/pocketmine/item/Item.php b/src/pocketmine/item/Item.php index c5ef917a8..356466d68 100644 --- a/src/pocketmine/item/Item.php +++ b/src/pocketmine/item/Item.php @@ -65,13 +65,19 @@ class Item implements ItemIds, \JsonSerializable{ /** @var \SplFixedArray */ public static $list = null; + /** @var Block|null */ protected $block; + /** @var int */ protected $id; + /** @var int */ protected $meta; + /** @var string */ private $tags = ""; + /** @var CompoundTag|null */ private $cachedNBT = null; + /** @var int */ public $count; - protected $durability = 0; + /** @var string */ protected $name; public function canBeActivated(){ @@ -1007,4 +1013,12 @@ class Item implements ItemIds, \JsonSerializable{ return $item; } + public function __clone(){ + if($this->block !== null){ + $this->block = clone $this->block; + } + + $this->cachedNBT = null; + } + } diff --git a/src/pocketmine/item/ItemBlock.php b/src/pocketmine/item/ItemBlock.php index 4bcac3f9d..8a61b31aa 100644 --- a/src/pocketmine/item/ItemBlock.php +++ b/src/pocketmine/item/ItemBlock.php @@ -37,10 +37,6 @@ class ItemBlock extends Item{ $this->block->setDamage($this->meta !== -1 ? $this->meta : 0); } - public function __clone(){ - $this->block = clone $this->block; - } - public function getBlock() : Block{ return $this->block; } From 0750b3ab592434ba4a210ee0b78847bd11838d87 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 24 Mar 2017 16:03:10 +0000 Subject: [PATCH 09/14] Added pocketmine.yml option to disable the title ticker (#447) This gets really spammy on some consoles when you stick it in the background, but I don't want to lose colour for the sake of that. --- src/pocketmine/Server.php | 13 ++++++++----- src/pocketmine/resources/pocketmine.yml | 5 +++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 12f8d9eb5..ce3cf2569 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -157,6 +157,9 @@ class Server{ private $currentTPS = 20; private $currentUse = 0; + /** @var bool */ + private $doTitleTick = true; + private $sendUsageTicker = 0; private $dispatchSignals = false; @@ -1455,6 +1458,8 @@ class Server{ $this->alwaysTickPlayers = (int) $this->getProperty("level-settings.always-tick-players", false); $this->baseTickRate = (int) $this->getProperty("level-settings.base-tick-rate", 1); + $this->doTitleTick = (bool) $this->getProperty("console.title-tick", true); + $this->scheduler = new ServerScheduler(); if($this->getConfigBoolean("enable-rcon", false) === true){ @@ -2287,10 +2292,6 @@ class Server{ } private function titleTick(){ - if(!Terminal::hasFormattingCodes()){ - return; - } - $d = Utils::getRealMemoryUsage(); $u = Utils::getMemoryUsage(true); @@ -2366,7 +2367,9 @@ class Server{ } if(($this->tickCounter & 0b1111) === 0){ - $this->titleTick(); + if($this->doTitleTick and Terminal::hasFormattingCodes()){ + $this->titleTick(); + } $this->currentTPS = 20; $this->currentUse = 0; diff --git a/src/pocketmine/resources/pocketmine.yml b/src/pocketmine/resources/pocketmine.yml index 9b8df9222..132890293 100644 --- a/src/pocketmine/resources/pocketmine.yml +++ b/src/pocketmine/resources/pocketmine.yml @@ -185,6 +185,11 @@ timings: #Choose the host to use for viewing your timings results. host: mcpetimings.com +console: + #Choose whether to enable server stats reporting on the console title. + #NOTE: The title ticker will be disabled regardless if console colours are not enabled. + title-tick: true + aliases: #Examples: #showtheversion: version From 5926bab32389bde976a3d2c151777c2e90f3c4a0 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 24 Mar 2017 17:56:26 +0000 Subject: [PATCH 10/14] Block light bug fixes (#454) * Fixed an age-old light calculation bug causing solid blocks to filter their own light, fixed #375, probably fixed #288 Light spread reduction should be done based on the _target's_ light filter level, not the source. * Revert "Fix Glowing Obsidian lighting" This hack is no longer necessary. This reverts commit 35c33ba980887e9680d62bbcb65f8537bb063f2c. * Fixed wrong light levels for torch and redstone torch * Take adjacent light levels and opacity changes into account, block light will now spread when an obstruction is removed, close #455 * Added timings for Level->setBlock() and lighting updates --- src/pocketmine/block/GlowingObsidian.php | 2 +- src/pocketmine/block/RedstoneTorch.php | 4 +++ src/pocketmine/block/Torch.php | 2 +- src/pocketmine/event/LevelTimings.php | 11 +++++++ src/pocketmine/level/Level.php | 38 ++++++++++++++++++++++-- 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/pocketmine/block/GlowingObsidian.php b/src/pocketmine/block/GlowingObsidian.php index e3ee02ba8..26b55cfd2 100644 --- a/src/pocketmine/block/GlowingObsidian.php +++ b/src/pocketmine/block/GlowingObsidian.php @@ -22,7 +22,7 @@ namespace pocketmine\block; -class GlowingObsidian extends Transparent{ +class GlowingObsidian extends Solid{ protected $id = self::GLOWING_OBSIDIAN; diff --git a/src/pocketmine/block/RedstoneTorch.php b/src/pocketmine/block/RedstoneTorch.php index ca7f7f352..32e4bb77a 100644 --- a/src/pocketmine/block/RedstoneTorch.php +++ b/src/pocketmine/block/RedstoneTorch.php @@ -32,4 +32,8 @@ class RedstoneTorch extends Torch{ public function getName(){ return "Redstone Torch"; } + + public function getLightLevel(){ + return 7; + } } diff --git a/src/pocketmine/block/Torch.php b/src/pocketmine/block/Torch.php index c71bd957a..78cf35e82 100644 --- a/src/pocketmine/block/Torch.php +++ b/src/pocketmine/block/Torch.php @@ -34,7 +34,7 @@ class Torch extends Flowable{ } public function getLightLevel(){ - return 15; + return 14; } public function getName(){ diff --git a/src/pocketmine/event/LevelTimings.php b/src/pocketmine/event/LevelTimings.php index ef78dcbd2..52a0ce6fb 100644 --- a/src/pocketmine/event/LevelTimings.php +++ b/src/pocketmine/event/LevelTimings.php @@ -25,6 +25,13 @@ use pocketmine\level\Level; class LevelTimings{ + /** @var TimingsHandler */ + public $setBlock; + /** @var TimingsHandler */ + public $doBlockLightUpdates; + /** @var TimingsHandler */ + public $doBlockSkyLightUpdates; + /** @var TimingsHandler */ public $mobSpawn; /** @var TimingsHandler */ @@ -79,6 +86,10 @@ class LevelTimings{ public function __construct(Level $level){ $name = $level->getFolderName() . " - "; + $this->setBlock = new TimingsHandler("** " . $name . "setBlock"); + $this->doBlockLightUpdates = new TimingsHandler("** " . $name . "doBlockLightUpdates"); + $this->doBlockSkyLightUpdates = new TimingsHandler("** " . $name . "doBlockSkyLightUpdates"); + $this->mobSpawn = new TimingsHandler("** " . $name . "mobSpawn"); $this->doChunkUnload = new TimingsHandler("** " . $name . "doChunkUnload"); $this->doTickPending = new TimingsHandler("** " . $name . "doTickPending"); diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 8641622b4..a5178d3e6 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -1286,17 +1286,42 @@ class Level implements ChunkManager, Metadatable{ } public function updateBlockSkyLight(int $x, int $y, int $z){ + $this->timings->doBlockSkyLightUpdates->startTiming(); //TODO + $this->timings->doBlockSkyLightUpdates->stopTiming(); + } + + /** + * Returns the highest light level available in the positions adjacent to the specified block coordinates. + * + * @param int $x + * @param int $y + * @param int $z + * + * @return int + */ + public function getHighestAdjacentBlockLight(int $x, int $y, int $z) : int{ + return max([ + $this->getBlockLightAt($x + 1, $y, $z), + $this->getBlockLightAt($x - 1, $y, $z), + $this->getBlockLightAt($x, $y + 1, $z), + $this->getBlockLightAt($x, $y - 1, $z), + $this->getBlockLightAt($x, $y, $z + 1), + $this->getBlockLightAt($x, $y, $z - 1) + ]); } public function updateBlockLight(int $x, int $y, int $z){ + $this->timings->doBlockLightUpdates->startTiming(); + $lightPropagationQueue = new \SplQueue(); $lightRemovalQueue = new \SplQueue(); $visited = []; $removalVisited = []; + $id = $this->getBlockIdAt($x, $y, $z); $oldLevel = $this->getBlockLightAt($x, $y, $z); - $newLevel = (int) Block::$light[$this->getBlockIdAt($x, $y, $z)]; + $newLevel = max(Block::$light[$id], $this->getHighestAdjacentBlockLight($x, $y, $z) - Block::$lightFilter[$id]); if($oldLevel !== $newLevel){ $this->setBlockLightAt($x, $y, $z, $newLevel); @@ -1328,7 +1353,7 @@ class Level implements ChunkManager, Metadatable{ /** @var Vector3 $node */ $node = $lightPropagationQueue->dequeue(); - $lightLevel = $this->getBlockLightAt($node->x, $node->y, $node->z) - (int) Block::$lightFilter[$this->getBlockIdAt($node->x, $node->y, $node->z)]; + $lightLevel = $this->getBlockLightAt($node->x, $node->y, $node->z); if($lightLevel >= 1){ $this->computeSpreadBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited); @@ -1339,6 +1364,8 @@ class Level implements ChunkManager, Metadatable{ $this->computeSpreadBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightPropagationQueue, $visited); } } + + $this->timings->doBlockLightUpdates->stopTiming(); } private function computeRemoveBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, \SplQueue $spreadQueue, array &$visited, array &$spreadVisited){ @@ -1365,6 +1392,7 @@ class Level implements ChunkManager, Metadatable{ private function computeSpreadBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, array &$visited){ if($y < 0) return; $current = $this->getBlockLightAt($x, $y, $z); + $currentLight -= Block::$lightFilter[$this->getBlockIdAt($x, $y, $z)]; if($current < $currentLight){ $this->setBlockLightAt($x, $y, $z, $currentLight); @@ -1402,6 +1430,8 @@ class Level implements ChunkManager, Metadatable{ return false; } + $this->timings->setBlock->startTiming(); + if($this->getChunk($pos->x >> 4, $pos->z >> 4, true)->setBlock($pos->x & 0x0f, $pos->y & Level::Y_MASK, $pos->z & 0x0f, $block->getId(), $block->getDamage())){ if(!($pos instanceof Position)){ $pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z); @@ -1441,9 +1471,13 @@ class Level implements ChunkManager, Metadatable{ $this->updateAround($pos); } + $this->timings->setBlock->stopTiming(); + return true; } + $this->timings->setBlock->stopTiming(); + return false; } From 5332887a0abc4099a54467c47c21be8924b1b945 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 25 Mar 2017 10:26:06 +0000 Subject: [PATCH 11/14] Fixed command name case sensitivity issue noted in #462 --- src/pocketmine/command/SimpleCommandMap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pocketmine/command/SimpleCommandMap.php b/src/pocketmine/command/SimpleCommandMap.php index 566e4d0a1..ae959c8ad 100644 --- a/src/pocketmine/command/SimpleCommandMap.php +++ b/src/pocketmine/command/SimpleCommandMap.php @@ -136,7 +136,7 @@ class SimpleCommandMap implements CommandMap{ if($label === null){ $label = $command->getName(); } - $label = strtolower(trim($label)); + $label = trim($label); $fallbackPrefix = strtolower(trim($fallbackPrefix)); $registered = $this->registerAlias($command, false, $fallbackPrefix, $label); From c9cf3d5aa4b4721e98854b6e4b3bc9604d5a9715 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 25 Mar 2017 10:33:05 +0000 Subject: [PATCH 12/14] Throw an exception when something attempts to serialize Server (#459) --- src/pocketmine/Server.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index ce3cf2569..3290ab0c9 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -2434,4 +2434,13 @@ class Server{ return true; } + + /** + * Called when something attempts to serialize the server instance. + * + * @throws \BadMethodCallException because Server instances cannot be serialized + */ + public function __sleep(){ + throw new \BadMethodCallException("Cannot serialize Server instance"); + } } From 34f833fa79e048bcac4c52a0b8c9e936577f1490 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 25 Mar 2017 12:02:09 +0000 Subject: [PATCH 13/14] Do not save empty inventory slots --- src/pocketmine/entity/Human.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index d9a26d1ee..e5c86b4b7 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -443,7 +443,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize(); for($slot = $this->inventory->getHotbarSize(); $slot < $slotCount; ++$slot){ $item = $this->inventory->getItem($slot - 9); - $this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot); + if($item->getId() !== ItemItem::AIR){ + $this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot); + } } //Armor From b9dfc7551a2b021a2892594d13294334d17d1e20 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 25 Mar 2017 16:34:42 -0400 Subject: [PATCH 14/14] Added Permission to bypass spawn protection, close #440 (#451) --- src/pocketmine/level/Level.php | 6 +++--- src/pocketmine/permission/DefaultPermissions.php | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index a5178d3e6..d68896812 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -1542,7 +1542,7 @@ class Level implements ChunkManager, Metadatable{ if(($player->isSurvival() and $item instanceof Item and !$target->isBreakable($item)) or $player->isSpectator()){ $ev->setCancelled(); - }elseif(!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1){ + }elseif(!$player->hasPermission("pocketmine.spawnprotect.bypass") and ($distance = $this->server->getSpawnRadius()) > -1){ $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if(count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance){ //set it to cancelled so plugins can bypass this @@ -1679,7 +1679,7 @@ class Level implements ChunkManager, Metadatable{ if($player !== null){ $ev = new PlayerInteractEvent($player, $item, $target, $face, $target->getId() === 0 ? PlayerInteractEvent::RIGHT_CLICK_AIR : PlayerInteractEvent::RIGHT_CLICK_BLOCK); - if(!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1){ + if(!$player->hasPermission("pocketmine.spawnprotect.bypass") and ($distance = $this->server->getSpawnRadius()) > -1){ $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if(count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance){ //set it to cancelled so plugins can bypass this @@ -1769,7 +1769,7 @@ class Level implements ChunkManager, Metadatable{ if($player !== null){ $ev = new BlockPlaceEvent($player, $hand, $block, $target, $item); - if(!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1){ + if(!$player->hasPermission("pocketmine.spawnprotect.bypass") and ($distance = $this->server->getSpawnRadius()) > -1){ $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if(count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance){ //set it to cancelled so plugins can bypass this diff --git a/src/pocketmine/permission/DefaultPermissions.php b/src/pocketmine/permission/DefaultPermissions.php index b1aa2f682..079db04ff 100644 --- a/src/pocketmine/permission/DefaultPermissions.php +++ b/src/pocketmine/permission/DefaultPermissions.php @@ -47,12 +47,13 @@ abstract class DefaultPermissions{ $parent = self::registerPermission(new Permission(self::ROOT, "Allows using all PocketMine commands and utilities")); $broadcasts = self::registerPermission(new Permission(self::ROOT . ".broadcast", "Allows the user to receive all broadcast messages"), $parent); - self::registerPermission(new Permission(self::ROOT . ".broadcast.admin", "Allows the user to receive administrative broadcasts", Permission::DEFAULT_OP), $broadcasts); self::registerPermission(new Permission(self::ROOT . ".broadcast.user", "Allows the user to receive user broadcasts", Permission::DEFAULT_TRUE), $broadcasts); - $broadcasts->recalculatePermissibles(); + $spawnprotect = self::registerPermission(new Permission(self::ROOT . ".spawnprotect.bypass", "Allows the user to edit blocks within the protected spawn radius", Permission::DEFAULT_OP), $parent); + $spawnprotect->recalculatePermissibles(); + $commands = self::registerPermission(new Permission(self::ROOT . ".command", "Allows using all PocketMine commands"), $parent); $whitelist = self::registerPermission(new Permission(self::ROOT . ".command.whitelist", "Allows the user to modify the server whitelist", Permission::DEFAULT_OP), $commands);