Merge branch 'master' into mcpe-1.1

This commit is contained in:
Dylan K. Taylor 2017-05-04 21:15:49 +01:00
commit 56306f6636
15 changed files with 201 additions and 39 deletions

View File

@ -24,6 +24,7 @@ namespace pocketmine;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\plugin\PluginBase;
use pocketmine\plugin\PluginLoadOrder;
use pocketmine\plugin\PluginManager;
use pocketmine\utils\Utils;
use pocketmine\utils\VersionString;
use raklib\RakLib;
@ -86,7 +87,7 @@ class CrashDump{
}
private function pluginsData(){
if(class_exists("pocketmine\\plugin\\PluginManager", false)){
if($this->server->getPluginManager() instanceof PluginManager){
$this->addLine();
$this->addLine("Loaded plugins:");
$this->data["plugins"] = [];
@ -224,6 +225,7 @@ class CrashDump{
private function generalData(){
$version = new VersionString();
$this->data["general"] = [];
$this->data["general"]["name"] = $this->server->getName();
$this->data["general"]["version"] = $version->get(false);
$this->data["general"]["build"] = $version->getBuild();
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
@ -235,7 +237,7 @@ class CrashDump{
$this->data["general"]["zend"] = zend_version();
$this->data["general"]["php_os"] = PHP_OS;
$this->data["general"]["os"] = Utils::getOS();
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
$this->addLine($this->server->getName() . " version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
$this->addLine("Git commit: " . GIT_COMMIT);
$this->addLine("uname -a: " . php_uname("a"));
$this->addLine("PHP Version: " . phpversion());

View File

@ -214,6 +214,8 @@ class MemoryManager{
}
public function dumpServerMemory($outputFolder, $maxNesting, $maxStringSize){
$hardLimit = ini_get('memory_limit');
ini_set('memory_limit', -1);
gc_disable();
if(!file_exists($outputFolder)){
@ -232,6 +234,32 @@ class MemoryManager{
$refCounts = [];
$instanceCounts = [];
$staticCount = 0;
foreach($this->server->getLoader()->getClasses() as $className){
$reflection = new \ReflectionClass($className);
$staticProperties[$className] = [];
foreach($reflection->getProperties() as $property){
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
continue;
}
if(!$property->isPublic()){
$property->setAccessible(true);
}
$staticCount++;
$this->continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
if(count($staticProperties[$className]) === 0){
unset($staticProperties[$className]);
}
}
echo "[Dump] Wrote $staticCount static properties\n";
$this->continueDump($this->server, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
do{
@ -243,6 +271,11 @@ class MemoryManager{
$continue = true;
$className = get_class($object);
if(!isset($instanceCounts[$className])){
$instanceCounts[$className] = 1;
}else{
$instanceCounts[$className]++;
}
$objects[$hash] = true;
@ -273,33 +306,23 @@ class MemoryManager{
}
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
if(!isset($objects["staticProperties"][$className])){
$staticProperties[$className] = [];
foreach($reflection->getProperties() as $property){
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
continue;
}
if(!$property->isPublic()){
$property->setAccessible(true);
}
$this->continueDump($property->getValue($object), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
}
}
echo "[Dump] Wrote " . count($objects) . " objects\n";
}while($continue);
fclose($obData);
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
arsort($instanceCounts, SORT_NUMERIC);
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
echo "[Dump] Finished!\n";
ini_set('memory_limit', $hardLimit);
gc_enable();
}

View File

@ -184,7 +184,6 @@ use pocketmine\network\mcpe\protocol\StopSoundPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\TextPacket;
use pocketmine\network\mcpe\protocol\TransferPacket;
use pocketmine\network\mcpe\protocol\UnknownPacket;
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket;
@ -3464,11 +3463,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
public function addTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1){
$this->setTitleDuration($fadeIn, $stay, $fadeOut);
if($subtitle !== ""){
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
$this->addSubTitle($subtitle);
}
$this->sendTitleText($title, SetTitlePacket::TYPE_SET_TITLE);
}
/**
* Sets the subtitle message, without sending a title.
*
* @param string $subtitle
*/
public function addSubTitle(string $subtitle){
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
}
/**
* Adds small text to the user's screen.
*
@ -3487,6 +3495,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->dataPacket($pk);
}
/**
* Resets the title duration settings.
*/
public function resetTitles(){
$pk = new SetTitlePacket();
$pk->type = SetTitlePacket::TYPE_RESET_TITLE;
$this->dataPacket($pk);
}
/**
* Sets the title duration.
*

View File

@ -1940,8 +1940,10 @@ class Server{
UPnP::RemovePortForward($this->getPort());
}
$this->getLogger()->debug("Disabling all plugins");
$this->pluginManager->disablePlugins();
if($this->pluginManager instanceof PluginManager){
$this->getLogger()->debug("Disabling all plugins");
$this->pluginManager->disablePlugins();
}
foreach($this->players as $player){
$player->close($player->getLeaveMessage(), $this->getProperty("settings.shutdown-message", "Server closed"));
@ -2084,7 +2086,8 @@ class Server{
try{
$dump = new CrashDump($this);
}catch(\Throwable $e){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.crash.error", $e->getMessage()));
$this->logger->logException($e);
$this->logger->critical($this->getLanguage()->translateString("pocketmine.crash.error", [$e->getMessage()]));
return;
}
@ -2199,9 +2202,6 @@ class Server{
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_ADD;
foreach($this->playerList as $player){
if($p === $player){
continue; //fixes duplicates
}
$pk->entries[] = [$player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkinId(), $player->getSkinData()];
}

View File

@ -46,11 +46,6 @@ abstract class Command{
/** @var string */
private $label;
/**
* @var string[]
*/
private $aliases = [];
/**
* @var string[]
*/
@ -79,11 +74,11 @@ abstract class Command{
*/
public function __construct($name, $description = "", $usageMessage = null, array $aliases = []){
$this->commandData = self::generateDefaultData();
$this->name = $this->nextLabel = $this->label = $name;
$this->name = $name;
$this->setLabel($name);
$this->setDescription($description);
$this->usageMessage = $usageMessage === null ? "/" . $name : $usageMessage;
$this->setAliases($aliases);
$this->timings = new TimingsHandler("** Command: " . $name);
}
/**
@ -208,6 +203,9 @@ abstract class Command{
public function setLabel($name){
$this->nextLabel = $name;
if(!$this->isRegistered()){
if($this->timings instanceof TimingsHandler){
$this->timings->remove();
}
$this->timings = new TimingsHandler("** Command: " . $name);
$this->label = $name;

View File

@ -57,6 +57,7 @@ use pocketmine\command\defaults\TeleportCommand;
use pocketmine\command\defaults\TellCommand;
use pocketmine\command\defaults\TimeCommand;
use pocketmine\command\defaults\TimingsCommand;
use pocketmine\command\defaults\TitleCommand;
use pocketmine\command\defaults\TransferServerCommand;
use pocketmine\command\defaults\VanillaCommand;
use pocketmine\command\defaults\VersionCommand;
@ -115,6 +116,7 @@ class SimpleCommandMap implements CommandMap{
$this->register("pocketmine", new TeleportCommand("tp"));
$this->register("pocketmine", new TimeCommand("time"));
$this->register("pocketmine", new TimingsCommand("timings"));
$this->register("pocketmine", new TitleCommand("title"));
$this->register("pocketmine", new ReloadCommand("reload"));
$this->register("pocketmine", new TransferServerCommand("transferserver"));
@ -302,4 +304,4 @@ class SimpleCommandMap implements CommandMap{
}
}
}

View File

@ -75,7 +75,6 @@ class EffectCommand extends VanillaCommand{
return true;
}
$duration = 300;
$amplification = 0;
if(count($args) >= 3){

View File

@ -0,0 +1,102 @@
<?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/
*
*
*/
namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\event\TranslationContainer;
class TitleCommand extends VanillaCommand{
public function __construct($name){
parent::__construct(
$name,
"%pocketmine.command.title.description",
"%commands.title.usage"
);
$this->setPermission("pocketmine.command.title");
}
public function execute(CommandSender $sender, $currentAlias, array $args){
if(!$this->testPermission($sender)){
return true;
}
if(count($args) < 2){
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return true;
}
$player = $sender->getServer()->getPlayer($args[0]);
if($player === null){
$sender->sendMessage(new TranslationContainer("commands.generic.player.notFound"));
return true;
}
switch($args[1]){
case "clear":
$player->removeTitles();
break;
case "reset":
$player->resetTitles();
break;
case "title":
if(count($args) < 3){
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return false;
}
$player->addTitle(implode(" ", array_slice($args, 2)));
break;
case "subtitle":
if(count($args) < 3){
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return false;
}
$player->addSubTitle(implode(" ", array_slice($args, 2)));
break;
case "actionbar":
if(count($args) < 3){
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return false;
}
$player->addActionBarMessage(implode(" ", array_slice($args, 2)));
break;
case "times":
if(count($args) < 4){
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return false;
}
$player->setTitleDuration($this->getInteger($sender, $args[2]), $this->getInteger($sender, $args[3]), $this->getInteger($sender, $args[4]));
break;
default:
$sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
return false;
}
$sender->sendMessage(new TranslationContainer("commands.title.success"));
return true;
}
}

View File

@ -30,7 +30,6 @@ use pocketmine\level\format\io\ChunkUtils;
use pocketmine\level\format\SubChunk;
use pocketmine\level\generator\Generator;
use pocketmine\level\Level;
use pocketmine\level\LevelException;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\{
ByteArrayTag, ByteTag, CompoundTag, IntArrayTag, IntTag, ListTag, LongTag, StringTag

View File

@ -25,7 +25,6 @@ namespace pocketmine\level\format\io\region;
use pocketmine\level\format\Chunk;
use pocketmine\level\format\io\ChunkException;
use pocketmine\level\LevelException;
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;

View File

@ -103,7 +103,6 @@ use pocketmine\network\mcpe\protocol\StopSoundPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\TextPacket;
use pocketmine\network\mcpe\protocol\TransferPacket;
use pocketmine\network\mcpe\protocol\UnknownPacket;
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket;

View File

@ -24,12 +24,14 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\item\Item;
use pocketmine\network\mcpe\NetworkSession;
class DropItemPacket extends DataPacket{
const NETWORK_ID = ProtocolInfo::DROP_ITEM_PACKET;
public $type;
/** @var Item */
public $item;
public function decode(){

View File

@ -124,6 +124,7 @@ abstract class DefaultPermissions{
self::registerPermission(new Permission(self::ROOT . ".command.spawnpoint", "Allows the user to change player's spawnpoint", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.setworldspawn", "Allows the user to change the world spawn", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.transferserver", "Allows the user to transfer self to another server", Permission::DEFAULT_OP), $commands);
self::registerPermission(new Permission(self::ROOT . ".command.title", "Allows the user to send a title to the specified player", Permission::DEFAULT_OP), $commands);
$commands->recalculatePermissibles();

View File

@ -177,11 +177,19 @@ class BinaryStream extends \stdClass{
}
public function getUUID(){
return UUID::fromBinary($this->get(16));
//This is actually two little-endian longs: UUID Most followed by UUID Least
$part1 = $this->getLInt();
$part0 = $this->getLInt();
$part3 = $this->getLInt();
$part2 = $this->getLInt();
return new UUID($part0, $part1, $part2, $part3);
}
public function putUUID(UUID $uuid){
$this->put($uuid->toBinary());
$this->putLInt($uuid->getPart(1));
$this->putLInt($uuid->getPart(0));
$this->putLInt($uuid->getPart(3));
$this->putLInt($uuid->getPart(2));
}
public function getSlot(){

View File

@ -102,4 +102,15 @@ class UUID{
public function __toString(){
return $this->toString();
}
public function getPart(int $partNumber){
if($partNumber < 0 or $partNumber > 3){
throw new \InvalidArgumentException("Invalid UUID part index $partNumber");
}
return $this->parts[$partNumber];
}
public function getParts() : array{
return $this->parts;
}
}