Merge branch 'api3/network' into api3/network_mcpe-1.0.5

This commit is contained in:
Dylan K. Taylor 2017-03-25 21:31:48 +00:00
commit bb79684480
18 changed files with 161 additions and 94 deletions

View File

@ -112,7 +112,6 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket; use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
@ -1955,11 +1954,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false; return false;
} }
public function handleBatch(BatchPacket $packet) : bool{
$this->server->getNetwork()->processBatch($packet, $this);
return true;
}
public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool{ public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool{
return false; return false;
} }
@ -2237,6 +2231,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$item = $this->inventory->getItem($packet->inventorySlot); $item = $this->inventory->getItem($packet->inventorySlot);
if(!$item->equals($packet->item)){ if(!$item->equals($packet->item)){
$this->server->getLogger()->debug("Tried to equip " . $packet->item . " but have " . $item . " in target slot");
$this->inventory->sendContents($this); $this->inventory->sendContents($this);
return false; return false;
} }
@ -3317,6 +3312,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$timings = Timings::getReceiveDataPacketTimings($packet); $timings = Timings::getReceiveDataPacketTimings($packet);
$timings->startTiming(); $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)); $this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet));
if(!$ev->isCancelled() and !$packet->handle($this)){ if(!$ev->isCancelled() and !$packet->handle($this)){
$this->server->getLogger()->debug("Unhandled " . get_class($packet) . " received from " . $this->getName()); $this->server->getLogger()->debug("Unhandled " . get_class($packet) . " received from " . $this->getName());
@ -3580,6 +3578,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->username; return $this->username;
} }
/**
* @return string
*/
public function getLowerCaseName() : string{
return $this->iusername;
}
public function kill(){ public function kill(){
if(!$this->spawned){ if(!$this->spawned){
return; return;

View File

@ -158,6 +158,9 @@ class Server{
private $currentTPS = 20; private $currentTPS = 20;
private $currentUse = 0; private $currentUse = 0;
/** @var bool */
private $doTitleTick = true;
private $sendUsageTicker = 0; private $sendUsageTicker = 0;
private $dispatchSignals = false; private $dispatchSignals = false;
@ -817,7 +820,7 @@ class Server{
public function getPlayerExact($name){ public function getPlayerExact($name){
$name = strtolower($name); $name = strtolower($name);
foreach($this->getOnlinePlayers() as $player){ foreach($this->getOnlinePlayers() as $player){
if(strtolower($player->getName()) === $name){ if($player->getLowerCaseName() === $name){
return $player; return $player;
} }
} }
@ -834,7 +837,7 @@ class Server{
$partialName = strtolower($partialName); $partialName = strtolower($partialName);
$matchedPlayers = []; $matchedPlayers = [];
foreach($this->getOnlinePlayers() as $player){ foreach($this->getOnlinePlayers() as $player){
if(strtolower($player->getName()) === $partialName){ if($player->getLowerCaseName() === $partialName){
$matchedPlayers = [$player]; $matchedPlayers = [$player];
break; break;
}elseif(stripos($player->getName(), $partialName) !== false){ }elseif(stripos($player->getName(), $partialName) !== false){
@ -1466,6 +1469,8 @@ class Server{
$this->alwaysTickPlayers = (int) $this->getProperty("level-settings.always-tick-players", false); $this->alwaysTickPlayers = (int) $this->getProperty("level-settings.always-tick-players", false);
$this->baseTickRate = (int) $this->getProperty("level-settings.base-tick-rate", 1); $this->baseTickRate = (int) $this->getProperty("level-settings.base-tick-rate", 1);
$this->doTitleTick = (bool) $this->getProperty("console.title-tick", true);
$this->scheduler = new ServerScheduler(); $this->scheduler = new ServerScheduler();
if($this->getConfigBoolean("enable-rcon", false) === true){ if($this->getConfigBoolean("enable-rcon", false) === true){
@ -1546,7 +1551,7 @@ class Server{
Attribute::init(); Attribute::init();
$this->craftingManager = new CraftingManager(); $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 = new PluginManager($this, $this->commandMap);
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender); $this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
@ -2262,7 +2267,9 @@ class Server{
} }
public function sendUsage($type = SendUsageTask::TYPE_STATUS){ public function sendUsage($type = SendUsageTask::TYPE_STATUS){
if($this->getProperty("anonymous-statistics.enabled", true)){
$this->scheduler->scheduleAsyncTask(new SendUsageTask($this, $type, $this->uniquePlayers)); $this->scheduler->scheduleAsyncTask(new SendUsageTask($this, $type, $this->uniquePlayers));
}
$this->uniquePlayers = []; $this->uniquePlayers = [];
} }
@ -2296,10 +2303,6 @@ class Server{
} }
private function titleTick(){ private function titleTick(){
if(!Terminal::hasFormattingCodes()){
return;
}
$d = Utils::getRealMemoryUsage(); $d = Utils::getRealMemoryUsage();
$u = Utils::getMemoryUsage(true); $u = Utils::getMemoryUsage(true);
@ -2375,7 +2378,9 @@ class Server{
} }
if(($this->tickCounter & 0b1111) === 0){ if(($this->tickCounter & 0b1111) === 0){
if($this->doTitleTick and Terminal::hasFormattingCodes()){
$this->titleTick(); $this->titleTick();
}
$this->currentTPS = 20; $this->currentTPS = 20;
$this->currentUse = 0; $this->currentUse = 0;
@ -2440,4 +2445,13 @@ class Server{
return true; 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");
}
} }

View File

@ -22,7 +22,7 @@
namespace pocketmine\block; namespace pocketmine\block;
class GlowingObsidian extends Transparent{ class GlowingObsidian extends Solid{
protected $id = self::GLOWING_OBSIDIAN; protected $id = self::GLOWING_OBSIDIAN;

View File

@ -32,4 +32,8 @@ class RedstoneTorch extends Torch{
public function getName(){ public function getName(){
return "Redstone Torch"; return "Redstone Torch";
} }
public function getLightLevel(){
return 7;
}
} }

View File

@ -34,7 +34,7 @@ class Torch extends Flowable{
} }
public function getLightLevel(){ public function getLightLevel(){
return 15; return 14;
} }
public function getName(){ public function getName(){

View File

@ -136,7 +136,7 @@ class SimpleCommandMap implements CommandMap{
if($label === null){ if($label === null){
$label = $command->getName(); $label = $command->getName();
} }
$label = strtolower(trim($label)); $label = trim($label);
$fallbackPrefix = strtolower(trim($fallbackPrefix)); $fallbackPrefix = strtolower(trim($fallbackPrefix));
$registered = $this->registerAlias($command, false, $fallbackPrefix, $label); $registered = $this->registerAlias($command, false, $fallbackPrefix, $label);
@ -188,7 +188,7 @@ class SimpleCommandMap implements CommandMap{
* @return Command|null * @return Command|null
*/ */
public function matchCommand(string &$commandName, array &$args){ public function matchCommand(string &$commandName, array &$args){
$count = max(count($args), 255); $count = min(count($args), 255);
for($i = 0; $i < $count; ++$i){ for($i = 0; $i < $count; ++$i){
$commandName .= array_shift($args); $commandName .= array_shift($args);

View File

@ -443,8 +443,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize(); $slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize();
for($slot = $this->inventory->getHotbarSize(); $slot < $slotCount; ++$slot){ for($slot = $this->inventory->getHotbarSize(); $slot < $slotCount; ++$slot){
$item = $this->inventory->getItem($slot - 9); $item = $this->inventory->getItem($slot - 9);
if($item->getId() !== ItemItem::AIR){
$this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot); $this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot);
} }
}
//Armor //Armor
for($slot = 100; $slot < 104; ++$slot){ for($slot = 100; $slot < 104; ++$slot){

View File

@ -25,6 +25,13 @@ use pocketmine\level\Level;
class LevelTimings{ class LevelTimings{
/** @var TimingsHandler */
public $setBlock;
/** @var TimingsHandler */
public $doBlockLightUpdates;
/** @var TimingsHandler */
public $doBlockSkyLightUpdates;
/** @var TimingsHandler */ /** @var TimingsHandler */
public $mobSpawn; public $mobSpawn;
/** @var TimingsHandler */ /** @var TimingsHandler */
@ -79,6 +86,10 @@ class LevelTimings{
public function __construct(Level $level){ public function __construct(Level $level){
$name = $level->getFolderName() . " - "; $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->mobSpawn = new TimingsHandler("** " . $name . "mobSpawn");
$this->doChunkUnload = new TimingsHandler("** " . $name . "doChunkUnload"); $this->doChunkUnload = new TimingsHandler("** " . $name . "doChunkUnload");
$this->doTickPending = new TimingsHandler("** " . $name . "doTickPending"); $this->doTickPending = new TimingsHandler("** " . $name . "doTickPending");

View File

@ -65,13 +65,19 @@ class Item implements ItemIds, \JsonSerializable{
/** @var \SplFixedArray */ /** @var \SplFixedArray */
public static $list = null; public static $list = null;
/** @var Block|null */
protected $block; protected $block;
/** @var int */
protected $id; protected $id;
/** @var int */
protected $meta; protected $meta;
/** @var string */
private $tags = ""; private $tags = "";
/** @var CompoundTag|null */
private $cachedNBT = null; private $cachedNBT = null;
/** @var int */
public $count; public $count;
protected $durability = 0; /** @var string */
protected $name; protected $name;
public function canBeActivated(){ public function canBeActivated(){
@ -1007,4 +1013,12 @@ class Item implements ItemIds, \JsonSerializable{
return $item; return $item;
} }
public function __clone(){
if($this->block !== null){
$this->block = clone $this->block;
}
$this->cachedNBT = null;
}
} }

View File

@ -37,10 +37,6 @@ class ItemBlock extends Item{
$this->block->setDamage($this->meta !== -1 ? $this->meta : 0); $this->block->setDamage($this->meta !== -1 ? $this->meta : 0);
} }
public function __clone(){
$this->block = clone $this->block;
}
public function getBlock() : Block{ public function getBlock() : Block{
return $this->block; return $this->block;
} }

View File

@ -1254,17 +1254,42 @@ class Level implements ChunkManager, Metadatable{
} }
public function updateBlockSkyLight(int $x, int $y, int $z){ public function updateBlockSkyLight(int $x, int $y, int $z){
$this->timings->doBlockSkyLightUpdates->startTiming();
//TODO //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){ public function updateBlockLight(int $x, int $y, int $z){
$this->timings->doBlockLightUpdates->startTiming();
$lightPropagationQueue = new \SplQueue(); $lightPropagationQueue = new \SplQueue();
$lightRemovalQueue = new \SplQueue(); $lightRemovalQueue = new \SplQueue();
$visited = []; $visited = [];
$removalVisited = []; $removalVisited = [];
$id = $this->getBlockIdAt($x, $y, $z);
$oldLevel = $this->getBlockLightAt($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){ if($oldLevel !== $newLevel){
$this->setBlockLightAt($x, $y, $z, $newLevel); $this->setBlockLightAt($x, $y, $z, $newLevel);
@ -1296,7 +1321,7 @@ class Level implements ChunkManager, Metadatable{
/** @var Vector3 $node */ /** @var Vector3 $node */
$node = $lightPropagationQueue->dequeue(); $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){ if($lightLevel >= 1){
$this->computeSpreadBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited); $this->computeSpreadBlockLight($node->x - 1, $node->y, $node->z, $lightLevel, $lightPropagationQueue, $visited);
@ -1307,6 +1332,8 @@ class Level implements ChunkManager, Metadatable{
$this->computeSpreadBlockLight($node->x, $node->y, $node->z + 1, $lightLevel, $lightPropagationQueue, $visited); $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){ private function computeRemoveBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, \SplQueue $spreadQueue, array &$visited, array &$spreadVisited){
@ -1333,6 +1360,7 @@ class Level implements ChunkManager, Metadatable{
private function computeSpreadBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, array &$visited){ private function computeSpreadBlockLight(int $x, int $y, int $z, int $currentLight, \SplQueue $queue, array &$visited){
if($y < 0) return; if($y < 0) return;
$current = $this->getBlockLightAt($x, $y, $z); $current = $this->getBlockLightAt($x, $y, $z);
$currentLight -= Block::$lightFilter[$this->getBlockIdAt($x, $y, $z)];
if($current < $currentLight){ if($current < $currentLight){
$this->setBlockLightAt($x, $y, $z, $currentLight); $this->setBlockLightAt($x, $y, $z, $currentLight);
@ -1370,6 +1398,8 @@ class Level implements ChunkManager, Metadatable{
return false; 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($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)){ if(!($pos instanceof Position)){
$pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z); $pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z);
@ -1409,9 +1439,13 @@ class Level implements ChunkManager, Metadatable{
$this->updateAround($pos); $this->updateAround($pos);
} }
$this->timings->setBlock->stopTiming();
return true; return true;
} }
$this->timings->setBlock->stopTiming();
return false; return false;
} }
@ -1476,7 +1510,7 @@ class Level implements ChunkManager, Metadatable{
if(($player->isSurvival() and $item instanceof Item and !$target->isBreakable($item)) or $player->isSpectator()){ if(($player->isSurvival() and $item instanceof Item and !$target->isBreakable($item)) or $player->isSpectator()){
$ev->setCancelled(); $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); $t = new Vector2($target->x, $target->z);
$s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->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 if(count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance){ //set it to cancelled so plugins can bypass this
@ -1613,7 +1647,7 @@ class Level implements ChunkManager, Metadatable{
if($player !== null){ if($player !== null){
$ev = new PlayerInteractEvent($player, $item, $target, $face, $target->getId() === 0 ? PlayerInteractEvent::RIGHT_CLICK_AIR : PlayerInteractEvent::RIGHT_CLICK_BLOCK); $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); $t = new Vector2($target->x, $target->z);
$s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->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 if(count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance){ //set it to cancelled so plugins can bypass this
@ -1703,7 +1737,7 @@ class Level implements ChunkManager, Metadatable{
if($player !== null){ if($player !== null){
$ev = new BlockPlaceEvent($player, $hand, $block, $target, $item); $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); $t = new Vector2($target->x, $target->z);
$s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->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 if(count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance){ //set it to cancelled so plugins can bypass this

View File

@ -250,7 +250,7 @@ class Vector3{
if($f < 0 or $f > 1){ if($f < 0 or $f > 1){
return null; return null;
}else{ }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);
} }
} }
@ -277,7 +277,7 @@ class Vector3{
if($f < 0 or $f > 1){ if($f < 0 or $f > 1){
return null; return null;
}else{ }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);
} }
} }
@ -304,7 +304,7 @@ class Vector3{
if($f < 0 or $f > 1){ if($f < 0 or $f > 1){
return null; return null;
}else{ }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);
} }
} }

View File

@ -57,24 +57,24 @@ use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ExplodePacket; use pocketmine\network\mcpe\protocol\ExplodePacket;
use pocketmine\network\mcpe\protocol\FullChunkDataPacket; use pocketmine\network\mcpe\protocol\FullChunkDataPacket;
use pocketmine\network\mcpe\protocol\HurtArmorPacket; use pocketmine\network\mcpe\protocol\HurtArmorPacket;
use pocketmine\network\mcpe\protocol\MapInfoRequestPacket;
use pocketmine\network\mcpe\protocol\PlaySoundPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryActionPacket; use pocketmine\network\mcpe\protocol\InventoryActionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\LoginPacket; 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\MobArmorEquipmentPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\MoveEntityPacket; use pocketmine\network\mcpe\protocol\MoveEntityPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\PlayerActionPacket; use pocketmine\network\mcpe\protocol\PlayerActionPacket;
use pocketmine\network\mcpe\protocol\PlayerFallPacket; use pocketmine\network\mcpe\protocol\PlayerFallPacket;
use pocketmine\network\mcpe\protocol\PlayerInputPacket; use pocketmine\network\mcpe\protocol\PlayerInputPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\PlaySoundPacket;
use pocketmine\network\mcpe\protocol\PlayStatusPacket; use pocketmine\network\mcpe\protocol\PlayStatusPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\RemoveBlockPacket; use pocketmine\network\mcpe\protocol\RemoveBlockPacket;
use pocketmine\network\mcpe\protocol\RemoveEntityPacket; use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
use pocketmine\network\mcpe\protocol\ReplaceItemInSlotPacket; use pocketmine\network\mcpe\protocol\ReplaceItemInSlotPacket;
@ -108,9 +108,7 @@ use pocketmine\network\mcpe\protocol\UnknownPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket; use pocketmine\network\mcpe\protocol\UpdateTradePacket;
use pocketmine\network\mcpe\protocol\UseItemPacket; use pocketmine\network\mcpe\protocol\UseItemPacket;
use pocketmine\Player;
use pocketmine\Server; use pocketmine\Server;
use pocketmine\utils\BinaryStream;
class Network{ class Network{
@ -237,50 +235,6 @@ class Network{
return $this->server; 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 * @param $id
* *

View File

@ -32,7 +32,6 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket; use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
@ -49,6 +48,7 @@ use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
use pocketmine\network\mcpe\protocol\ContainerSetSlotPacket; use pocketmine\network\mcpe\protocol\ContainerSetSlotPacket;
use pocketmine\network\mcpe\protocol\CraftingDataPacket; use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket; use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\DropItemPacket; use pocketmine\network\mcpe\protocol\DropItemPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\EntityEventPacket;
@ -108,9 +108,17 @@ use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket; use pocketmine\network\mcpe\protocol\UpdateTradePacket;
use pocketmine\network\mcpe\protocol\UseItemPacket; use pocketmine\network\mcpe\protocol\UseItemPacket;
use pocketmine\Server;
interface NetworkSession{ interface NetworkSession{
/**
* @return Server
*/
public function getServer();
public function handleDataPacket(DataPacket $pk);
public function handleLogin(LoginPacket $packet) : bool; public function handleLogin(LoginPacket $packet) : bool;
public function handlePlayStatus(PlayStatusPacket $packet) : bool; public function handlePlayStatus(PlayStatusPacket $packet) : bool;
@ -121,8 +129,6 @@ interface NetworkSession{
public function handleDisconnect(DisconnectPacket $packet) : bool; public function handleDisconnect(DisconnectPacket $packet) : bool;
public function handleBatch(BatchPacket $packet) : bool;
public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool; public function handleResourcePacksInfo(ResourcePacksInfoPacket $packet) : bool;
public function handleResourcePackStack(ResourcePackStackPacket $packet) : bool; public function handleResourcePackStack(ResourcePackStackPacket $packet) : bool;

View File

@ -132,12 +132,8 @@ class RakLibInterface implements ServerInstance, AdvancedSourceInterface{
try{ try{
if($packet->buffer !== ""){ if($packet->buffer !== ""){
$pk = $this->getPacket($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){ }catch(\Throwable $e){
if(\pocketmine\DEBUG > 1 and isset($pk)){ if(\pocketmine\DEBUG > 1 and isset($pk)){
$logger = $this->server->getLogger(); $logger = $this->server->getLogger();

View File

@ -45,7 +45,32 @@ class BatchPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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;
} }
} }

View File

@ -47,12 +47,13 @@ abstract class DefaultPermissions{
$parent = self::registerPermission(new Permission(self::ROOT, "Allows using all PocketMine commands and utilities")); $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); $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.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); self::registerPermission(new Permission(self::ROOT . ".broadcast.user", "Allows the user to receive user broadcasts", Permission::DEFAULT_TRUE), $broadcasts);
$broadcasts->recalculatePermissibles(); $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); $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); $whitelist = self::registerPermission(new Permission(self::ROOT . ".command.whitelist", "Allows the user to modify the server whitelist", Permission::DEFAULT_OP), $commands);

View File

@ -185,6 +185,11 @@ timings:
#Choose the host to use for viewing your timings results. #Choose the host to use for viewing your timings results.
host: mcpetimings.com 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: aliases:
#Examples: #Examples:
#showtheversion: version #showtheversion: version