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{
$this->readline = false;
$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);

View File

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

View File

@ -61,6 +61,11 @@ class Server{
*/
private static $instance = null;
/**
* @var bool
*/
private $isRunning = true;
/**
* @var PluginManager
*/
@ -132,6 +137,13 @@ class Server{
return "PocketMine-MP";
}
/**
* @return bool
*/
public function isRunning(){
return $this->isRunning === true;
}
/**
* @return string
*/
@ -251,6 +263,41 @@ class Server{
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
*/
@ -421,7 +468,6 @@ class Server{
"server-name" => "Minecraft: PE Server",
"motd" => "Welcome @player to this server!",
"server-port" => 19132,
"server-type" => "normal",
"memory-limit" => "128M",
"white-list" => false,
"announce-player-achievements" => true,
@ -484,6 +530,7 @@ class Server{
$this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this);
$this->pluginManager = new PluginManager($this, $this->commandMap);
$this->pluginManager->subscribeToPermission(Player::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
$this->pluginManager->registerInterface("PocketMine\\Plugin\\FolderPluginLoader");
$this->pluginManager->loadPlugins($this->pluginPath);
@ -576,6 +623,10 @@ class Server{
return false;
}
public function shutdown(){
$this->isRunning = false;
}
/**
* Starts the PocketMine-MP server and starts processing ticks and packets
*/
@ -608,11 +659,24 @@ class Server{
}else{
$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(){
$lastLoop = 0;
while(true){
while($this->isRunning){
if(($packet = $this->interface->readPacket()) instanceof Packet){
if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){
$this->handlePacket($packet);
@ -632,7 +696,7 @@ class Server{
private function tickProcessor(){
$lastLoop = 0;
while(true){
while($this->isRunning){
if(($packet = $this->interface->readPacket()) instanceof Packet){
if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){
$this->handlePacket($packet);

View File

@ -24,6 +24,8 @@
*/
namespace PocketMine\Command;
use PocketMine\Player;
use PocketMine\Server;
use PocketMine\Utils\TextFormat;
abstract class Command{
@ -290,6 +292,24 @@ abstract class Command{
* @param bool $sendToSource
*/
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\PermissionAttachment;
use PocketMine\Player;
use PocketMine\Plugin\Plugin;
use PocketMine\Server;

View File

@ -22,6 +22,7 @@
namespace PocketMine\Command;
use PocketMine\Command\Defaults\PluginsCommand;
use PocketMine\Command\Defaults\StopCommand;
use PocketMine\Command\Defaults\VanillaCommand;
use PocketMine\Command\Defaults\VersionCommand;
use PocketMine\Command\Defaults\SeedCommand;
@ -51,6 +52,7 @@ class SimpleCommandMap implements CommandMap{
$this->register("pocketmine", new PluginsCommand("plugins"));
$this->register("pocketmine", new SeedCommand("seed"));
$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(){
$this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
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_SNDBUF, 1024 * 1024 * 2); //2MB
@socket_set_option($this->socket, SOL_SOCKET, SO_RCVBUF, 1024 * 1024); //1MB
}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);
}
socket_set_nonblock($this->socket);

View File

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

View File

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

View File

@ -49,11 +49,8 @@ class PermissionAttachmentInfo{
* @param PermissionAttachment $attachment
* @param bool $value
*/
public function __construct(Permissible $permissible, $permission, PermissionAttachment $attachment, $value){
if($permissible === null){
trigger_error("Permissible may not be null", E_USER_WARNING);
return;
}elseif($permission === null){
public function __construct(Permissible $permissible, $permission, $attachment, $value){
if($permission === null){
trigger_error("Permission may not be null", E_USER_WARNING);
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;
}
$workers[] = new ServerWorker($asyncTask, $thread);
}, $this->workers, $thread, $this);
}, $thread, $this);
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();
/**
* @var \Threaded<ServerTask>
* @var ServerTask[]
*/
private $runners;
@ -77,14 +77,14 @@ class ServerScheduler{
/**
* @param int $workers
*/
public function __construct($workers = 2){
public function __construct($workers = 8){
self::$instance = $this;
$this->head = new ServerTask();
$this->tail = new ServerTask();
$this->pending = new \SplPriorityQueue();
$this->temp = array();
$this->runners = new \Threaded();
//TODO: $this->executor = new \Pool($workers);
$this->executor = new TaskPool($workers);
}
@ -256,7 +256,7 @@ class ServerScheduler{
}
//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);
for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){
if($taskPending === $task){
@ -277,7 +277,7 @@ class ServerScheduler{
}
//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);
for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){
if($taskPending === $task){
@ -300,7 +300,7 @@ class ServerScheduler{
*/
public function cancelAllTasks(){
//TODO
$task = new ServerTask(null, new ServerAllTaskCanceller());
$task = new ServerTask(null, new ServerAllTaskCanceller($this->temp, $this->pending, $this->runners));
$this->handle($task, 0);
for($taskPending = $this->head->getNext(); $taskPending !== null; $taskPending = $taskPending->getNext()){
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-iconv \
--without-pdo-sqlite \
--with-pic \
--enable-phar \
--enable-ctype \
--enable-sockets \