mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-15 18:29:46 +00:00
Merge branch 'master' into mcpe-1.1
This commit is contained in:
commit
56306f6636
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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()];
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,6 @@ class EffectCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$duration = 300;
|
||||
$amplification = 0;
|
||||
|
||||
if(count($args) >= 3){
|
||||
|
102
src/pocketmine/command/defaults/TitleCommand.php
Normal file
102
src/pocketmine/command/defaults/TitleCommand.php
Normal 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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(){
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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(){
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user