diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 87d71ec21..fc05e03a9 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -1185,6 +1185,10 @@ class Server{ "auto-save" => true, )); + if($this->getConfigBoolean("enable-rcon", false) === true){ + $this->rcon = new RCON($this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50)); + } + $this->maxPlayers = $this->getConfigInt("max-players", 20); if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "128M")))) !== false){ @@ -1215,7 +1219,7 @@ class Server{ console("[INFO] Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort()); define("BOOTUP_RANDOM", Utils::getRandomBytes(16)); - $this->serverID = Utils::readLong(substr(Utils::getUniqueID(true, $this->getIp() . $this->getPort()), 8)); + $this->serverID = Utils::readLong(substr(Utils::getUniqueID(true, $this->getIp() . $this->getPort()), 0, 8)); $this->interface = new ThreadedHandler("255.255.255.255", $this->getPort(), $this->getIp() === "" ? "0.0.0.0" : $this->getIp()); console("[INFO] This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . $this->getPocketMineVersion() . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0); @@ -1398,6 +1402,48 @@ class Server{ return false; } + public function reload(){ + console("[INFO] Saving levels..."); + + foreach($this->levels as $level){ + $level->save(); + } + + $this->pluginManager->disablePlugins(); + $this->pluginManager->clearPlugins(); + $this->commandMap->clearCommands(); + + console("[INFO] Reloading properties..."); + $this->properties->reload(); + $this->maxPlayers = $this->getConfigInt("max-players", 20); + + if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "128M")))) !== false){ + $value = array("M" => 1, "G" => 1024); + $real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)]; + if($real < 128){ + console("[WARNING] PocketMine-MP may not work right with less than 128MB of RAM", true, true, 0); + } + @ini_set("memory_limit", $memory); + }else{ + $this->setConfigString("memory-limit", "128M"); + } + + if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){ + $this->setConfigInt("difficulty", 3); + } + + $this->banByIP->load(); + $this->banByName->load(); + $this->reloadWhitelist(); + $this->operators->reload(); + + + $this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader"); + $this->pluginManager->loadPlugins($this->pluginPath); + $this->enablePlugins(PluginLoadOrder::STARTUP); + $this->enablePlugins(PluginLoadOrder::POSTWORLD); + } + /** * Shutdowns the server correctly */ @@ -1405,50 +1451,8 @@ class Server{ $this->isRunning = false; } - /** - * Starts the PocketMine-MP server and starts processing ticks and packets - */ - public function start(){ - - if($this->getConfigBoolean("enable-rcon", false) === true){ - $this->rcon = new RCON($this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50)); - } - - if($this->getConfigBoolean("enable-query", true) === true){ - $this->queryHandler = new QueryHandler(); - } - - - if($this->getConfigBoolean("send-usage", true) !== false){ - $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "sendUsage")), 6000, 6000); - $this->sendUsage(); - } - - - if($this->getConfigBoolean("upnp-forwarding", false) == true){ - console("[INFO] [UPnP] Trying to port forward..."); - UPnP::PortForward($this->getPort()); - } - - $this->tickCounter = 0; - - //register_shutdown_function(array($this, "dumpError")); - register_shutdown_function(array($this, "shutdown")); - if(function_exists("pcntl_signal")){ - pcntl_signal(SIGTERM, array($this, "shutdown")); - pcntl_signal(SIGINT, array($this, "shutdown")); - pcntl_signal(SIGHUP, array($this, "shutdown")); - } - - console("[INFO] Default game type: " . self::getGamemodeString($this->getGamemode())); //TODO: string name - - console('[INFO] Done (' . round(microtime(true) - \pocketmine\START_TIME, 3) . 's)! For help, type "help" or "?"'); - if(Utils::getOS() === "win"){ //Workaround less usleep() waste - $this->tickProcessorWindows(); - }else{ - $this->tickProcessor(); - } - + public function forceShutdown(){ + $this->shutdown(); if($this->rcon instanceof RCON){ $this->rcon->stop(); } @@ -1476,7 +1480,48 @@ class Server{ $this->tickScheduler->kill(); $this->console->kill(); + } + /** + * Starts the PocketMine-MP server and starts processing ticks and packets + */ + public function start(){ + + if($this->getConfigBoolean("enable-query", true) === true){ + $this->queryHandler = new QueryHandler(); + } + + + if($this->getConfigBoolean("send-usage", true) !== false){ + $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "sendUsage")), 6000, 6000); + $this->sendUsage(); + } + + + if($this->getConfigBoolean("upnp-forwarding", false) == true){ + console("[INFO] [UPnP] Trying to port forward..."); + UPnP::PortForward($this->getPort()); + } + + $this->tickCounter = 0; + + //register_shutdown_function(array($this, "dumpError")); + register_shutdown_function(array($this, "forceShutdown")); + if(function_exists("pcntl_signal")){ + pcntl_signal(SIGTERM, array($this, "shutdown")); + pcntl_signal(SIGINT, array($this, "shutdown")); + pcntl_signal(SIGHUP, array($this, "shutdown")); + } + + console("[INFO] Default game type: " . self::getGamemodeString($this->getGamemode())); //TODO: string name + + console('[INFO] Done (' . round(microtime(true) - \pocketmine\START_TIME, 3) . 's)! For help, type "help" or "?"'); + if(Utils::getOS() === "win"){ //Workaround less usleep() waste + $this->tickProcessorWindows(); + }else{ + $this->tickProcessor(); + } + $this->forceShutdown(); } private function tickProcessorWindows(){ diff --git a/src/pocketmine/command/SimpleCommandMap.php b/src/pocketmine/command/SimpleCommandMap.php index 1c5bf1433..2e96e3039 100644 --- a/src/pocketmine/command/SimpleCommandMap.php +++ b/src/pocketmine/command/SimpleCommandMap.php @@ -38,6 +38,7 @@ use pocketmine\command\defaults\OpCommand; use pocketmine\command\defaults\PardonCommand; use pocketmine\command\defaults\PardonIpCommand; use pocketmine\command\defaults\PluginsCommand; +use pocketmine\command\defaults\ReloadCommand; use pocketmine\command\defaults\SaveCommand; use pocketmine\command\defaults\SaveOffCommand; use pocketmine\command\defaults\SaveOnCommand; @@ -97,6 +98,7 @@ class SimpleCommandMap implements CommandMap{ $this->register("pocketmine", new KillCommand("kill")); $this->register("pocketmine", new SpawnpointCommand("spawnpoint")); $this->register("pocketmine", new TeleportCommand("tp")); + $this->register("pocketmine", new ReloadCommand("reload")); if($this->server->getConfigBoolean("debug.commands", false) === true){ $this->register("pocketmine", new StatusCommand("status")); diff --git a/src/pocketmine/command/defaults/ReloadCommand.php b/src/pocketmine/command/defaults/ReloadCommand.php new file mode 100644 index 000000000..652f165f4 --- /dev/null +++ b/src/pocketmine/command/defaults/ReloadCommand.php @@ -0,0 +1,53 @@ +setPermission("pocketmine.command.reload"); + } + + public function execute(CommandSender $sender, $currentAlias, array $args){ + if(!$this->testPermission($sender)){ + return true; + } + + Command::broadcastCommandMessage($sender, TextFormat::YELLOW . "Reloading server..."); + + Server::getInstance()->reload(); + Command::broadcastCommandMessage($sender, TextFormat::GOLD . "Reload complete."); + + return true; + } +} \ No newline at end of file diff --git a/src/pocketmine/network/ThreadedHandler.php b/src/pocketmine/network/ThreadedHandler.php index 1a5421f19..1d37c49c0 100644 --- a/src/pocketmine/network/ThreadedHandler.php +++ b/src/pocketmine/network/ThreadedHandler.php @@ -39,6 +39,7 @@ class ThreadedHandler extends \Thread{ protected $server; protected $port; protected $serverip; + public $path; function __construct($server, $port = 19132, $serverip = "0.0.0.0"){ $this->server = $server; @@ -56,8 +57,8 @@ class ThreadedHandler extends \Thread{ new Packet(0); new QueryPacket(); new RakNetPacket(0); - - $this->start(PTHREADS_INHERIT_ALL); + $this->path = \pocketmine\PATH; + $this->start(PTHREADS_INHERIT_ALL & ~PTHREADS_INHERIT_CLASSES); } public function close(){ @@ -105,9 +106,10 @@ class ThreadedHandler extends \Thread{ } public function run(){ + require($this->path . "src/spl/SplClassLoader.php"); $autoloader = new \SplClassLoader(); $autoloader->add("pocketmine", array( - \pocketmine\PATH . "src" + $this->path . "src" )); $autoloader->register(true); diff --git a/src/pocketmine/network/rcon/RCONInstance.php b/src/pocketmine/network/rcon/RCONInstance.php index 5be2c440d..4c0420830 100644 --- a/src/pocketmine/network/rcon/RCONInstance.php +++ b/src/pocketmine/network/rcon/RCONInstance.php @@ -31,6 +31,7 @@ class RCONInstance extends \Thread{ private $password; private $maxClients; + public function __construct($socket, $password, $maxClients = 50){ $this->stop = false; $this->cmd = ""; @@ -43,6 +44,7 @@ class RCONInstance extends \Thread{ $this->{"status" . $n} = 0; $this->{"timeout" . $n} = 0; } + $this->start(); } @@ -80,6 +82,7 @@ class RCONInstance extends \Thread{ } public function run(){ + while($this->stop !== true){ usleep(2000); $r = array($socket = $this->socket); diff --git a/src/pocketmine/plugin/PluginBase.php b/src/pocketmine/plugin/PluginBase.php index cbe4b4d0d..9a5d55f28 100644 --- a/src/pocketmine/plugin/PluginBase.php +++ b/src/pocketmine/plugin/PluginBase.php @@ -29,7 +29,7 @@ use pocketmine\command\PluginIdentifiableCommand; use pocketmine\Server; use pocketmine\utils\Config; -abstract class PluginBase implements Plugin, CommandExecutor{ +abstract class PluginBase implements Plugin{ /** @var PluginLoader */ private $loader; @@ -116,22 +116,18 @@ abstract class PluginBase implements Plugin, CommandExecutor{ } } + /** + * @return bool + */ public final function isInitialized(){ return $this->initialized; } /** - * @param CommandSender $sender - * @param Command $command - * @param string $label - * @param string[] $args + * @param string $name * - * @return bool + * @return PluginIdentifiableCommand */ - public function onCommand(CommandSender $sender, Command $command, $label, array $args){ - return false; - } - public function getCommand($name){ $command = $this->getServer()->getPluginCommand($name); if($command === null or $command->getPlugin() !== $this){ diff --git a/src/pocketmine/plugin/PluginManager.php b/src/pocketmine/plugin/PluginManager.php index f001d24e5..75bf2c375 100644 --- a/src/pocketmine/plugin/PluginManager.php +++ b/src/pocketmine/plugin/PluginManager.php @@ -172,6 +172,7 @@ class PluginManager{ * @return Plugin[] */ public function loadPlugins($directory, $newLoaders = null){ + if(is_dir($directory)){ $plugins = array(); $loadedPlugins = array(); diff --git a/src/pocketmine/scheduler/AsyncTask.php b/src/pocketmine/scheduler/AsyncTask.php index c9e45a6bd..0dabcb9ce 100644 --- a/src/pocketmine/scheduler/AsyncTask.php +++ b/src/pocketmine/scheduler/AsyncTask.php @@ -33,12 +33,12 @@ abstract class AsyncTask extends \Threaded{ private $result; public function run(){ - $this->synchronized(function(){ - $this->result = null; - $this->onRun(\Thread::getCurrentThread()); - $this->finished = true; - $this->complete = $this->result === null ? true : false; - }); + $this->lock(); + $this->result = null; + $this->onRun(); + $this->finished = true; + $this->complete = $this->result === null ? true : false; + $this->unlock(); } /** @@ -82,10 +82,8 @@ abstract class AsyncTask extends \Threaded{ /** * Actions to execute when run * - * @param \Thread $thread - * * @return void */ - public abstract function onRun(\Thread $thread); + public abstract function onRun(); } diff --git a/src/pocketmine/scheduler/AsyncWorker.php b/src/pocketmine/scheduler/AsyncWorker.php new file mode 100644 index 000000000..ecb9fbed5 --- /dev/null +++ b/src/pocketmine/scheduler/AsyncWorker.php @@ -0,0 +1,40 @@ +path = \pocketmine\PATH; + return parent::start($options & ~PTHREADS_INHERIT_CLASSES); + } + + public function run(){ + require($this->path . "src/spl/SplClassLoader.php"); + $autoloader = new \SplClassLoader(); + $autoloader->add("pocketmine", array( + $this->path . "src" + )); + $autoloader->register(true); + } +} \ No newline at end of file diff --git a/src/pocketmine/scheduler/SendUsageTask.php b/src/pocketmine/scheduler/SendUsageTask.php index add05293d..689b4ae4d 100644 --- a/src/pocketmine/scheduler/SendUsageTask.php +++ b/src/pocketmine/scheduler/SendUsageTask.php @@ -33,7 +33,7 @@ class SendUsageTask extends AsyncTask{ $this->data = serialize($data); } - public function onRun(\Thread $thread){ + public function onRun(){ Utils::postURL($this->endpoint, unserialize($this->data)); } diff --git a/src/pocketmine/scheduler/ServerScheduler.php b/src/pocketmine/scheduler/ServerScheduler.php index 9e620796b..97a1b3665 100644 --- a/src/pocketmine/scheduler/ServerScheduler.php +++ b/src/pocketmine/scheduler/ServerScheduler.php @@ -52,7 +52,7 @@ class ServerScheduler{ public function __construct(){ $this->queue = new ReversePriorityQueue(); - $this->asyncPool = new \Pool(self::$WORKERS, "Worker"); + $this->asyncPool = new \Pool(self::$WORKERS, "pocketmine\\scheduler\\AsyncWorker"); } /** diff --git a/src/spl/SplClassLoader.php b/src/spl/SplClassLoader.php index 63f42fa47..df47ee8cf 100644 --- a/src/spl/SplClassLoader.php +++ b/src/spl/SplClassLoader.php @@ -1,6 +1,6 @@