Added /stop, plugin disable / unload, remaining TaskCanceller classes

This commit is contained in:
Shoghi Cervantes 2014-03-27 18:49:43 +01:00
parent 2385b94ba3
commit 3bc3db0740
19 changed files with 463 additions and 24 deletions

View File

@ -77,7 +77,7 @@ class CommandReader extends \Thread{
}else{ }else{
$this->readline = false; $this->readline = false;
$this->fp = fopen($this->stream, "r"); $this->fp = fopen($this->stream, "r");
stream_set_blocking($this->fp, 0); //Won't work on Windows :P stream_set_blocking($this->fp, 1); //Non-blocking STDIN won't work on Windows
} }
$lastLine = microtime(true); $lastLine = microtime(true);

View File

@ -394,7 +394,7 @@ namespace PocketMine {
$server = new Server(\PocketMine\PATH, \PocketMine\DATA, \PocketMine\PLUGIN_PATH); $server = new Server(\PocketMine\PATH, \PocketMine\DATA, \PocketMine\PLUGIN_PATH);
$server->start(); $server->start();
kill(getmypid()); //Fix for ConsoleAPI being blocked kill(getmypid());
exit(0); exit(0);
} }

View File

@ -61,6 +61,11 @@ class Server{
*/ */
private static $instance = null; private static $instance = null;
/**
* @var bool
*/
private $isRunning = true;
/** /**
* @var PluginManager * @var PluginManager
*/ */
@ -132,6 +137,13 @@ class Server{
return "PocketMine-MP"; return "PocketMine-MP";
} }
/**
* @return bool
*/
public function isRunning(){
return $this->isRunning === true;
}
/** /**
* @return string * @return string
*/ */
@ -251,6 +263,41 @@ class Server{
return $this->getConfigBoolean("white-list", false); return $this->getConfigBoolean("white-list", false);
} }
/**
* @return int
*/
public function getSpawnRadius(){
return $this->getConfigInt("spawn-protection", 16);
}
/**
* @return bool
*/
public function getAllowFlight(){
return $this->getConfigBoolean("allow-flight", false);
}
/**
* @return bool
*/
public function isHardcore(){
return $this->getConfigBoolean("hardcore", false);
}
/**
* @return int
*/
public function getDefaultGamemode(){
return $this->getConfigInt("gamemode", 0) & 0b11;
}
/**
* @return string
*/
public function getMotd(){
return $this->getConfigString("motd", "");
}
/** /**
* @return PluginManager * @return PluginManager
*/ */
@ -421,7 +468,6 @@ class Server{
"server-name" => "Minecraft: PE Server", "server-name" => "Minecraft: PE Server",
"motd" => "Welcome @player to this server!", "motd" => "Welcome @player to this server!",
"server-port" => 19132, "server-port" => 19132,
"server-type" => "normal",
"memory-limit" => "128M", "memory-limit" => "128M",
"white-list" => false, "white-list" => false,
"announce-player-achievements" => true, "announce-player-achievements" => true,
@ -484,6 +530,7 @@ class Server{
$this->consoleSender = new ConsoleCommandSender(); $this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this); $this->commandMap = new SimpleCommandMap($this);
$this->pluginManager = new PluginManager($this, $this->commandMap); $this->pluginManager = new PluginManager($this, $this->commandMap);
$this->pluginManager->subscribeToPermission(Player::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
$this->pluginManager->registerInterface("PocketMine\\Plugin\\FolderPluginLoader"); $this->pluginManager->registerInterface("PocketMine\\Plugin\\FolderPluginLoader");
$this->pluginManager->loadPlugins($this->pluginPath); $this->pluginManager->loadPlugins($this->pluginPath);
@ -576,6 +623,10 @@ class Server{
return false; return false;
} }
public function shutdown(){
$this->isRunning = false;
}
/** /**
* Starts the PocketMine-MP server and starts processing ticks and packets * Starts the PocketMine-MP server and starts processing ticks and packets
*/ */
@ -608,11 +659,24 @@ class Server{
}else{ }else{
$this->tickProcessor(); $this->tickProcessor();
} }
foreach(Player::getAll() as $player){
$player->kick("server stop");
}
foreach(Level::getAll() as $level){
$level->unload(true);
}
$this->pluginManager->disablePlugins();
$this->console->kill();
//TODO: kill scheduler
} }
private function tickProcessorWindows(){ private function tickProcessorWindows(){
$lastLoop = 0; $lastLoop = 0;
while(true){ while($this->isRunning){
if(($packet = $this->interface->readPacket()) instanceof Packet){ if(($packet = $this->interface->readPacket()) instanceof Packet){
if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){ if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){
$this->handlePacket($packet); $this->handlePacket($packet);
@ -632,7 +696,7 @@ class Server{
private function tickProcessor(){ private function tickProcessor(){
$lastLoop = 0; $lastLoop = 0;
while(true){ while($this->isRunning){
if(($packet = $this->interface->readPacket()) instanceof Packet){ if(($packet = $this->interface->readPacket()) instanceof Packet){
if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){ if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){
$this->handlePacket($packet); $this->handlePacket($packet);

View File

@ -24,6 +24,8 @@
*/ */
namespace PocketMine\Command; namespace PocketMine\Command;
use PocketMine\Player;
use PocketMine\Server;
use PocketMine\Utils\TextFormat; use PocketMine\Utils\TextFormat;
abstract class Command{ abstract class Command{
@ -290,6 +292,24 @@ abstract class Command{
* @param bool $sendToSource * @param bool $sendToSource
*/ */
public static function broadcastCommandMessage(CommandSender $source, $message, $sendToSource = true){ public static function broadcastCommandMessage(CommandSender $source, $message, $sendToSource = true){
$result = $source->getName() .": " . $message;
//Command minecarts or command blocks are not implemented
$users = Server::getInstance()->getPluginManager()->getPermissionSubscriptions(Player::BROADCAST_CHANNEL_ADMINISTRATIVE);
$colored = TextFormat::GRAY . TextFormat::ITALIC . "[$result".TextFormat::GRAY . TextFormat::ITALIC."]";
if($sendToSource === true and !($source instanceof ConsoleCommandSender)){
$source->sendMessage($message);
}
foreach($users as $user){
if($user instanceof CommandSender){
if($user instanceof ConsoleCommandSender){
$user->sendMessage($result);
}elseif($user !== $source){
$user->sendMessage($colored);
}
}
}
} }
} }

View File

@ -23,6 +23,7 @@ namespace PocketMine\Command;
use PocketMine\Permission\PermissibleBase; use PocketMine\Permission\PermissibleBase;
use PocketMine\Permission\PermissionAttachment; use PocketMine\Permission\PermissionAttachment;
use PocketMine\Player;
use PocketMine\Plugin\Plugin; use PocketMine\Plugin\Plugin;
use PocketMine\Server; use PocketMine\Server;

View File

@ -22,6 +22,7 @@
namespace PocketMine\Command; namespace PocketMine\Command;
use PocketMine\Command\Defaults\PluginsCommand; use PocketMine\Command\Defaults\PluginsCommand;
use PocketMine\Command\Defaults\StopCommand;
use PocketMine\Command\Defaults\VanillaCommand; use PocketMine\Command\Defaults\VanillaCommand;
use PocketMine\Command\Defaults\VersionCommand; use PocketMine\Command\Defaults\VersionCommand;
use PocketMine\Command\Defaults\SeedCommand; use PocketMine\Command\Defaults\SeedCommand;
@ -51,6 +52,7 @@ class SimpleCommandMap implements CommandMap{
$this->register("pocketmine", new PluginsCommand("plugins")); $this->register("pocketmine", new PluginsCommand("plugins"));
$this->register("pocketmine", new SeedCommand("seed")); $this->register("pocketmine", new SeedCommand("seed"));
$this->register("pocketmine", new HelpCommand("help")); $this->register("pocketmine", new HelpCommand("help"));
$this->register("pocketmine", new StopCommand("stop"));
} }

View File

@ -0,0 +1,58 @@
<?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\Command;
use PocketMine\Command\CommandSender;
use PocketMine\Server;
use PocketMine\Player;
class StopCommand extends VanillaCommand{
public function __construct($name){
parent::__construct(
$name,
"Stops the server, with optional reason",
"/stop [reason]"
);
$this->setPermission("pocketmine.command.stop");
}
public function execute(CommandSender $sender, $currentAlias, array $args){
if(!$this->testPermission($sender)){
return true;
}
Command::broadcastCommandMessage($sender, "Stopping the server...");
$reason = implode(" ", $args);
if($reason !== ""){
foreach(Player::getAll() as $player){
$player->kick($reason);
}
}
Server::getInstance()->shutdown();
return true;
}
}

View File

@ -117,12 +117,13 @@ class ThreadedHandler extends \Thread{
public function run(){ public function run(){
$this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($this->socket, SOL_SOCKET, SO_BROADCAST, 1); //Allow sending broadcast messages socket_set_option($this->socket, SOL_SOCKET, SO_BROADCAST, 1); //Allow sending broadcast messages
if(socket_bind($this->socket, $this->serverip, $this->port) === true){ if(@socket_bind($this->socket, $this->serverip, $this->port) === true){
socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 0); socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 0);
@socket_set_option($this->socket, SOL_SOCKET, SO_SNDBUF, 1024 * 1024 * 2); //2MB @socket_set_option($this->socket, SOL_SOCKET, SO_SNDBUF, 1024 * 1024 * 2); //2MB
@socket_set_option($this->socket, SOL_SOCKET, SO_RCVBUF, 1024 * 1024); //1MB @socket_set_option($this->socket, SOL_SOCKET, SO_RCVBUF, 1024 * 1024); //1MB
}else{ }else{
console("[SEVERE] Couldn't bind to $this->serverip:" . $this->port, true, true, 0); console("[SEVERE] **** FAILED TO BIND TO ".$this->serverip.":" . $this->port."!", true, true, 0);
console("[SEVERE] Perhaps a server is already running on that port?", true, true, 0);
exit(1); exit(1);
} }
socket_set_nonblock($this->socket); socket_set_nonblock($this->socket);

View File

@ -197,7 +197,7 @@ class PermissibleBase implements Permissible{
* @param bool $invert * @param bool $invert
* @param PermissionAttachment $attachment * @param PermissionAttachment $attachment
*/ */
public function calculateChildPermissions(array $children, $invert, PermissionAttachment $attachment){ public function calculateChildPermissions(array $children, $invert, $attachment){
foreach(array_keys($children) as $name){ foreach(array_keys($children) as $name){
$perm = Server::getInstance()->getPluginManager()->getPermission($name); $perm = Server::getInstance()->getPluginManager()->getPermission($name);
$value = $invert === true ? !$children[$name] : $children[$name]; $value = $invert === true ? !$children[$name] : $children[$name];

View File

@ -49,10 +49,7 @@ class PermissionAttachment{
* @param Permissible $permissible * @param Permissible $permissible
*/ */
public function __construct(Plugin $plugin, Permissible $permissible){ public function __construct(Plugin $plugin, Permissible $permissible){
if($plugin === null){ if(!$plugin->isEnabled()){
trigger_error("Plugin cannot be null", E_USER_WARNING);
return;
}elseif(!$plugin->isEnabled()){
trigger_error("Plugin ".$plugin->getDescription()->getName()." is disabled", E_USER_WARNING); trigger_error("Plugin ".$plugin->getDescription()->getName()." is disabled", E_USER_WARNING);
return; return;
} }

View File

@ -49,11 +49,8 @@ class PermissionAttachmentInfo{
* @param PermissionAttachment $attachment * @param PermissionAttachment $attachment
* @param bool $value * @param bool $value
*/ */
public function __construct(Permissible $permissible, $permission, PermissionAttachment $attachment, $value){ public function __construct(Permissible $permissible, $permission, $attachment, $value){
if($permissible === null){ if($permission === null){
trigger_error("Permissible may not be null", E_USER_WARNING);
return;
}elseif($permission === null){
trigger_error("Permission may not be null", E_USER_WARNING); trigger_error("Permission may not be null", E_USER_WARNING);
return; return;
} }

View File

@ -0,0 +1,81 @@
<?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
*
*
*/
namespace PocketMine\Scheduler;
class ServerAllTaskCanceller extends \Threaded{
/**
* @var ServerTask[]
*/
protected $temp;
/**
* @var ServerTask[]
*/
protected $pending;
/**
* @var ServerTask[]
*/
protected $runners;
public function __construct($temp, $pending, $runners){
$this->temp = $temp;
$this->pending = $pending;
$this->runners = $runners;
}
public function run(){
foreach($this->runners as $index => $task){
$task->cancel0();
if($task->isSync()){
unset($this->runners[$index]);
}
}
while($this->temp->count() > 0){
$this->temp->pop();
}
while($this->pending->count() > 0){
$this->pending->pop();
}
}
/**
* @param ServerTask[] $collection
*
* @return bool
*/
private function check($collection){
foreach($collection as $index => $task){
if($task->getTaskId() === $this->taskId){
$task->cancel0();
unset($collection[$index]);
if($task->isSync()){
unset($this->runners[$this->taskId]);
}
return true;
}
}
return false;
}
}

View File

@ -53,7 +53,7 @@ class ServerAsyncTask extends ServerTask{
return; return;
} }
$workers[] = new ServerWorker($asyncTask, $thread); $workers[] = new ServerWorker($asyncTask, $thread);
}, $this->workers, $thread, $this); }, $thread, $this);
parent::run(); parent::run();

View File

@ -0,0 +1,79 @@
<?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
*
*
*/
namespace PocketMine\Scheduler;
use PocketMine\Plugin\Plugin;
class ServerPluginTaskCanceller extends \Threaded{
/**
* @var Plugin
*/
protected $plugin;
/**
* @var ServerTask[]
*/
protected $temp;
/**
* @var ServerTask[]
*/
protected $pending;
/**
* @var ServerTask[]
*/
protected $runners;
public function __construct(Plugin $plugin, $temp, $pending, $runners){
$this->plugin = $plugin;
$this->temp = $temp;
$this->pending = $pending;
$this->runners = $runners;
}
public function run(){
$this->check($this->temp);
$this->check($this->pending);
}
/**
* @param ServerTask[] $collection
*
* @return bool
*/
private function check($collection){
foreach($collection as $index => $task){
if($task->getOwner() === $this->plugin){
$task->cancel0();
unset($collection[$index]);
if($task->isSync()){
unset($this->runners[$task->getTaskId()]);
}
return true;
}
}
return false;
}
}

View File

@ -53,7 +53,7 @@ class ServerScheduler{
private $temp = array(); private $temp = array();
/** /**
* @var \Threaded<ServerTask> * @var ServerTask[]
*/ */
private $runners; private $runners;
@ -77,14 +77,14 @@ class ServerScheduler{
/** /**
* @param int $workers * @param int $workers
*/ */
public function __construct($workers = 2){ public function __construct($workers = 8){
self::$instance = $this; self::$instance = $this;
$this->head = new ServerTask(); $this->head = new ServerTask();
$this->tail = new ServerTask(); $this->tail = new ServerTask();
$this->pending = new \SplPriorityQueue(); $this->pending = new \SplPriorityQueue();
$this->temp = array(); $this->temp = array();
$this->runners = new \Threaded(); $this->runners = new \Threaded();
//TODO: $this->executor = new \Pool($workers); $this->executor = new TaskPool($workers);
} }
@ -256,7 +256,7 @@ class ServerScheduler{
} }
//TODO //TODO
$task = new ServerTask(null, new ServerTaskCanceller($taskId)); $task = new ServerTask(null, new ServerTaskCanceller($taskId, $this->temp, $this->pending, $this->runners));
$this->handle($task, 0); $this->handle($task, 0);
for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){ for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){
if($taskPending === $task){ if($taskPending === $task){
@ -277,7 +277,7 @@ class ServerScheduler{
} }
//TODO //TODO
$task = new ServerTask(null, new ServerPluginTaskCanceller($plugin)); $task = new ServerTask(null, new ServerPluginTaskCanceller($plugin, $this->temp, $this->pending, $this->runners));
$this->handle($task, 0); $this->handle($task, 0);
for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){ for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){
if($taskPending === $task){ if($taskPending === $task){
@ -300,7 +300,7 @@ class ServerScheduler{
*/ */
public function cancelAllTasks(){ public function cancelAllTasks(){
//TODO //TODO
$task = new ServerTask(null, new ServerAllTaskCanceller()); $task = new ServerTask(null, new ServerAllTaskCanceller($this->temp, $this->pending, $this->runners));
$this->handle($task, 0); $this->handle($task, 0);
for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){ for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){
if($taskPending === $task){ if($taskPending === $task){

View File

@ -0,0 +1,73 @@
<?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
*
*
*/
namespace PocketMine\Scheduler;
class ServerTaskCanceller extends \Threaded{
protected $taskId;
/**
* @var ServerTask[]
*/
protected $temp;
/**
* @var ServerTask[]
*/
protected $pending;
/**
* @var ServerTask[]
*/
protected $runners;
public function __construct($taskId, $temp, $pending, $runners){
$this->taskId = $taskId;
$this->temp = $temp;
$this->pending = $pending;
$this->runners = $runners;
}
public function run(){
if(!$this->check($this->temp)){
$this->check($this->pending);
}
}
/**
* @param ServerTask[] $collection
*
* @return bool
*/
private function check($collection){
foreach($collection as $index => $task){
if($task->getTaskId() === $this->taskId){
$task->cancel0();
unset($collection[$index]);
if($task->isSync()){
unset($this->runners[$this->taskId]);
}
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,34 @@
<?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\Scheduler;
class TaskPool extends \Pool{
public function __construct($workers){
parent::__construct((int) $workers, "PocketMine\\Scheduler\\TaskWorker");
}
public function shutdown(){
foreach($this->workers as $worker){
$worker->shutdown();
}
}
}

View File

@ -0,0 +1,31 @@
<?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\Scheduler;
class TaskWorker extends \Worker{
protected $shutdown;
public function run(){
}
}

View File

@ -637,6 +637,7 @@ $HAVE_READLINE \
--without-pear \ --without-pear \
--without-iconv \ --without-iconv \
--without-pdo-sqlite \ --without-pdo-sqlite \
--with-pic \
--enable-phar \ --enable-phar \
--enable-ctype \ --enable-ctype \
--enable-sockets \ --enable-sockets \