Added new Event system

This commit is contained in:
Shoghi Cervantes 2014-03-28 02:13:03 +01:00
parent 9e8cf2d42c
commit 2f20d95e5d
44 changed files with 591 additions and 353 deletions

View File

@ -23,7 +23,6 @@ namespace PocketMine;
use PocketMine\Entity\RealHuman;
use PocketMine\Event;
use PocketMine\Event\EventHandler;
use PocketMine\Item\Item;
use PocketMine\Level\Level;
use PocketMine\Level\Position;
@ -402,9 +401,9 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
if($this->connected === false){
return false;
}
if(EventHandler::callEvent(new Event\Server\DataPacketSendEvent($this, $packet)) === Event\Event::DENY){
return;
$this->server->getPluginManager()->callEvent($ev = new Event\Server\DataPacketSendEvent($this, $packet));
if($ev->isCancelled()){
return false;
}
$packet->encode();
@ -660,7 +659,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
return false;
}
}
if(EventHandler::callEvent(new Event\Player\PlayerAchievementAwardedEvent($this, $achievementId)) !== Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerAchievementAwardedEvent($this, $achievementId));
if(!$ev->isCancelled()){
$this->achievements[$achievementId] = true;
Achievement::broadcast($this, $achievementId);
@ -682,7 +682,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
return false;
}
if(EventHandler::callEvent(new Event\Player\PlayerGameModeChangeEvent($this, (int) $gm)) === Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerGameModeChangeEvent($this, (int) $gm));
if($ev->isCancelled()){
return false;
}
@ -908,7 +909,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
return;
}
if(EventHandler::callEvent(new Event\Server\DataPacketReceiveEvent($this, $packet)) === Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Server\DataPacketReceiveEvent($this, $packet));
if($ev->isCancelled()){
return;
}
@ -973,7 +975,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
return;
}
if(EventHandler::callEvent($ev = new Event\Player\PlayerPreLoginEvent($this, "Plugin reason")) === Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerPreLoginEvent($this, "Plugin reason"));
if($ev->isCancelled()){
$this->close($ev->getKickMessage(), "Plugin reason");
return;
@ -1037,7 +1040,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
$this->slot = $this->hotbar[0];
}
if(EventHandler::callEvent($ev = new Event\Player\PlayerLoginEvent($this, "Plugin reason")) === Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerLoginEvent($this, "Plugin reason"));
if($ev->isCancelled()){
$this->close($ev->getKickMessage(), "Plugin reason");
return;
@ -1078,7 +1082,7 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
$this->server->schedule(50, array($this, "measureLag"), array(), true);
console("[INFO] " . TextFormat::AQUA . $this->username . TextFormat::RESET . "[/" . $this->ip . ":" . $this->port . "] logged in with entity id " . $this->id . " at (" . $this->level->getName() . ", " . round($this->x, 4) . ", " . round($this->y, 4) . ", " . round($this->z, 4) . ")");
EventHandler::callEvent(new Event\Player\PlayerJoinEvent($this, $this->username . " joined the game"));
$this->server->getPluginManager()->callEvent(new Event\Player\PlayerJoinEvent($this, $this->username . " joined the game"));
break;
case ProtocolInfo::READY_PACKET:
@ -1173,15 +1177,21 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
$item = $this->getSlot($packet->slot);
}
if($packet->slot === false or EventHandler::callEvent(new Event\Player\PlayerItemHeldEvent($this, $item, $packet->slot, 0)) === Event\Event::DENY){
if($packet->slot === false){
$this->sendInventorySlot($packet->slot);
}elseif($item instanceof Item){
$this->setEquipmentSlot(0, $packet->slot);
$this->setCurrentEquipmentSlot(0);
if(($this->gamemode & 0x01) === 0){
if(!in_array($this->slot, $this->hotbar)){
array_pop($this->hotbar);
array_unshift($this->hotbar, $this->slot);
}else{
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerItemHeldEvent($this, $item, $packet->slot, 0));
if($ev->isCancelled()){
$this->sendInventorySlot($packet->slot);
}elseif($item instanceof Item){
$this->setEquipmentSlot(0, $packet->slot);
$this->setCurrentEquipmentSlot(0);
if(($this->gamemode & 0x01) === 0){
if(!in_array($this->slot, $this->hotbar)){
array_pop($this->hotbar);
array_unshift($this->hotbar, $this->slot);
}
}
}
}
@ -1631,8 +1641,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
if($message{0} === "/"){ //Command
$this->server->api->console->run(substr($message, 1), $this);
}else{
$ev = new Event\Player\PlayerChatEvent($this, $message);
if(EventHandler::callEvent($ev) !== Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerChatEvent($this, $message));
if(!$ev->isCancelled()){
Player::groupChat(sprintf($ev->getFormat(), $ev->getPlayer()->getDisplayName(), $ev->getMessage()), $ev->getRecipients());
}
}
@ -1889,7 +1899,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
* @return bool
*/
public function kick($reason = ""){
if(EventHandler::callEvent($ev = new Event\Player\PlayerKickEvent($this, $reason, "Kicked player " . $this->username . "." . ($reason !== "" ? " With reason: $reason" : ""))) !== Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerKickEvent($this, $reason, "Kicked player " . $this->username . "." . ($reason !== "" ? " With reason: $reason" : "")));
if(!$ev->isCancelled()){
$this->sendMessage("You have been kicked. " . ($reason !== "" ? " Reason: $reason" : "") . "\n");
$this->close($ev->getQuitMessage(), $reason);
@ -1941,7 +1952,7 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
public function close($message = "", $reason = "generic reason"){
if($this->connected === true){
if($this->username != ""){
EventHandler::callEvent($ev = new Event\Player\PlayerQuitEvent($this, $message));
$this->server->getPluginManager()->callEvent($ev = new Event\Player\PlayerQuitEvent($this, $message));
$this->save();
}
@ -2010,7 +2021,8 @@ class Player extends RealHuman /*TODO: implements CommandSender*/{
return false;
}
if(EventHandler::callEvent(new Event\Server\DataPacketSendEvent($this, $packet)) === Event\Event::DENY){
$this->server->getPluginManager()->callEvent($ev = new Event\Server\DataPacketSendEvent($this, $packet));
if($ev->isCancelled()){
return array();
}
$packet->encode();

View File

@ -33,7 +33,6 @@ use PocketMine\Command\PluginCommand;
use PocketMine\Command\SimpleCommandMap;
use PocketMine\Entity\Entity;
use PocketMine\Event\Event;
use PocketMine\Event\EventHandler;
use PocketMine\Event\Server\PacketReceiveEvent;
use PocketMine\Event\Server\PacketSendEvent;
use PocketMine\Item\Item;
@ -685,7 +684,8 @@ class Server{
$lastLoop = 0;
while($this->isRunning){
if(($packet = $this->interface->readPacket()) instanceof Packet){
if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){
$this->pluginManager->callEvent($ev = new PacketReceiveEvent($packet));
if(!$ev->isCancelled()){
$this->handlePacket($packet);
}
$lastLoop = 0;
@ -705,7 +705,8 @@ class Server{
$lastLoop = 0;
while($this->isRunning){
if(($packet = $this->interface->readPacket()) instanceof Packet){
if(EventHandler::callEvent(new PacketReceiveEvent($packet)) !== Event::DENY){
$this->pluginManager->callEvent($ev = new PacketReceiveEvent($packet));
if(!$ev->isCancelled()){
$this->handlePacket($packet);
}
$lastLoop = 0;
@ -739,7 +740,8 @@ class Server{
* @return int
*/
public function sendPacket(Packet $packet){
if(EventHandler::callEvent(new PacketSendEvent($packet)) !== Event::DENY){
$this->pluginManager->callEvent($ev = new PacketSendEvent($packet));
if(!$ev->isCancelled()){
return $this->interface->writePacket($packet);
}

View File

@ -30,7 +30,6 @@ use PocketMine\Event\Entity\EntityMotionEvent;
use PocketMine\Event\Entity\EntityMoveEvent;
use PocketMine\Event\Entity\EntitySpawnEvent;
use PocketMine\Event\Event;
use PocketMine\Event\EventHandler;
use PocketMine\Level\Level;
use PocketMine\Level\Position;
use PocketMine\Math\AxisAlignedBB;
@ -43,6 +42,7 @@ use PocketMine\Network\Protocol\RemoveEntityPacket;
use PocketMine\Network\Protocol\SetEntityMotionPacket;
use PocketMine\Player;
use PocketMine\PMF\LevelFormat;
use PocketMine\Server;
abstract class Entity extends Position{
public static $entityCount = 1;
@ -141,7 +141,7 @@ abstract class Entity extends Position{
$this->level->chunkEntities[$this->chunkIndex][$this->id] = $this;
$this->lastUpdate = microtime(true);
$this->initEntity();
EventHandler::callEvent(new EntitySpawnEvent($this));
Server::getInstance()->getPluginManager()->callEvent(new EntitySpawnEvent($this));
}
public function saveNBT(){
@ -353,7 +353,8 @@ abstract class Entity extends Position{
protected function switchLevel(Level $targetLevel){
if($this->level instanceof Level){
if(EventHandler::callEvent(new EntityLevelChangeEvent($this, $this->level, $targetLevel)) === Event::DENY){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityLevelChangeEvent($this, $this->level, $targetLevel));
if($ev->isCancelled()){
return false;
}
unset($this->level->entities[$this->id]);
@ -423,7 +424,8 @@ abstract class Entity extends Position{
return false;
}
}
if(EventHandler::callEvent(new EntityMoveEvent($this, $pos)) === Event::DENY){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityMoveEvent($this, $pos));
if($ev->isCancelled()){
return false;
}
$this->x = $pos->x;
@ -464,7 +466,8 @@ abstract class Entity extends Position{
}
public function setMotion(Vector3 $motion){
if(EventHandler::callEvent(new EntityMotionEvent($this, $motion)) === Event::DENY){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityMotionEvent($this, $motion));
if($ev->isCancelled()){
return false;
}
$this->motionX = $motion->x;
@ -538,7 +541,7 @@ abstract class Entity extends Position{
unset($this->level->chunkEntities[$this->chunkIndex][$this->id]);
unset(Entity::$list[$this->id]);
$this->despawnFromAll();
EventHandler::callEvent(new EntityDespawnEvent($this));
Server::getInstance()->getPluginManager()->callEvent(new EntityDespawnEvent($this));
}
}

View File

@ -24,7 +24,6 @@ namespace PocketMine\Entity;
use PocketMine\Event\Entity\EntityArmorChangeEvent;
use PocketMine\Event\Entity\EntityInventoryChangeEvent;
use PocketMine\Event\Event;
use PocketMine\Event\EventHandler;
use PocketMine\Item\Item;
use PocketMine\NBT\NBT;
use PocketMine\NBT\Tag\Byte;
@ -38,6 +37,7 @@ use PocketMine\Network\Protocol\PlayerEquipmentPacket;
use PocketMine\Network\Protocol\RemovePlayerPacket;
use PocketMine\Network\Protocol\SetEntityMotionPacket;
use PocketMine\Player;
use PocketMine\Server;
class Human extends Creature implements ProjectileSource, InventorySource{
@ -197,7 +197,8 @@ class Human extends Creature implements ProjectileSource, InventorySource{
}
public function setArmorSlot($slot, Item $item){
if(EventHandler::callEvent($ev = new EntityArmorChangeEvent($this, $this->getArmorSlot($slot), $item, $slot)) === Event::DENY){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this, $this->getArmorSlot($slot), $item, $slot));
if($ev->isCancelled()){
return false;
}
$this->armor[(int) $slot] = $ev->getNewItem();
@ -379,7 +380,8 @@ class Human extends Creature implements ProjectileSource, InventorySource{
}
public function setSlot($slot, Item $item){
if(EventHandler::callEvent($ev = new EntityInventoryChangeEvent($this, $this->getSlot($slot), $item, $slot)) === Event::DENY){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($this, $this->getSlot($slot), $item, $slot));
if($ev->isCancelled()){
return false;
}
$this->inventory[(int) $slot] = $ev->getNewItem();

View File

@ -23,8 +23,10 @@ namespace PocketMine\Event;
/**
* Events that can be cancelled must use the interface CancellableEvent
* Events that can be cancelled must use the interface Cancellable
*/
interface CancellableEvent{
interface Cancellable{
public function isCancelled();
public function setCancelled($forceCancel = false);
}

View File

@ -19,169 +19,52 @@
*
*/
/**
* Classes referenced to Event handling and Events itself
*/
namespace PocketMine\Event;
use PocketMine\Plugin\Plugin;
use PocketMine\Utils\Utils;
abstract class Event{
const ALLOW = 0;
const DENY = 1;
const NORMAL = 2;
const FORCE = 0x80000000;
private static $pluginEvents = array();
/**
* Any callable event must declare the static variables
* Any callable event must declare the static variable
*
* public static $handlers;
* public static $handlerPriority;
* public static $handlerList = null;
*
* Not doing so will deny the proper event initialization
*/
public static function getHandlerList(){
return static::$handlers;
}
public static function getPriorityList(){
return static::$handlerPriority;
}
public static function unregisterAll(){
static::$handlers = array();
static::$handlerPriority = array();
}
/**
* @param callable $handler
* @param int $priority
*
* @return bool
*/
public static function register(callable $handler, $priority = EventPriority::NORMAL){
if($priority < EventPriority::MONITOR or $priority > EventPriority::LOWEST){
return false;
}
$identifier = Utils::getCallableIdentifier($handler);
if(isset(static::$handlers[$identifier])){ //Already registered
return false;
}else{
if(is_array($handler) and $handler[0] instanceof Plugin){
$name = $handler[0]->getDescription()->getName();
if(!isset(self::$pluginEvents[$name])){
self::$pluginEvents[$name] = array();
}
self::$pluginEvents[$name][get_called_class()] = $identifier;
}
static::$handlers[$identifier] = $handler;
if(!isset(static::$handlerPriority[(int) $priority])){
static::$handlerPriority[(int) $priority] = array();
krsort(static::$handlerPriority);
}
static::$handlerPriority[(int) $priority][$identifier] = $handler;
return true;
}
}
/**
* @param Plugin $plugin
*/
public static function unregisterPlugin(Plugin $plugin){
$name = $plugin->getDescription()->getName();
if(!isset(self::$pluginEvents[$name])){
return;
}
foreach(self::$pluginEvents[$name] as $className => $identifier){
if(isset($className::$handlers[$identifier])){
$className::unregister($className::$handlers[$identifier], -1);
}
}
}
/**
* @param callable $handler
* @param int $priority
*
* @return bool
*/
public static function unregister(callable $handler, $priority = EventPriority::NORMAL){
$identifier = Utils::getCallableIdentifier($handler);
if(isset(static::$handlers[$identifier])){
if(is_array(static::$handlers[$identifier]) and static::$handlers[$identifier][0] instanceof Plugin){
unset(self::$pluginEvents[static::$handlers[$identifier][0]->getDescription()->getName()][get_called_class()]);
}
if(isset(static::$handlerPriority[(int) $priority][$identifier])){
unset(static::$handlerPriority[(int) $priority][$identifier]);
}else{
for($priority = EventPriority::MONITOR; $priority <= EventPriority::LOWEST; ++$priority){
unset(static::$handlerPriority[$priority][$identifier]);
if(count(static::$handlerPriority[$priority]) === 0){
unset(static::$handlerPriority[$priority]);
}
}
}
unset(static::$handlers[$identifier]);
return true;
}else{
return false;
}
}
protected $eventName = null;
private $status = Event::NORMAL;
private $prioritySlot;
private $isCancelled = false;
/**
* @return string
*/
final public function getEventName(){
return $this->eventName !== null ? get_class($this) : $this->eventName;
}
final public function setPrioritySlot($slot){
$this->prioritySlot = (int) $slot;
}
final public function getPrioritySlot(){
return (int) $this->prioritySlot;
}
public function isAllowed(){
return ($this->status & 0x7FFFFFFF) === Event::ALLOW;
}
public function setAllowed($forceAllow = false){
$this->status = Event::ALLOW | ($forceAllow === true ? Event::FORCE : 0);
}
/**
* @return bool
*/
public function isCancelled(){
return ($this->status & 0x7FFFFFFF) === Event::DENY;
return $this->isCancelled === true;
}
public function setCancelled($forceCancel = false){
if($this instanceof CancellableEvent){
$this->status = Event::DENY | ($forceCancel === true ? Event::FORCE : 0);
/**
* @param bool $value
*
* @return bool
*/
public function setCancelled($value = true){
$this->isCancelled = (bool) $value;
}
/**
* @return HandlerList
*/
public function getHandlers(){
if(static::$handlerList === null){
static::$handlerList = new HandlerList();
}
return false;
}
public function isNormal(){
return $this->status === Event::NORMAL;
}
public function setNormal(){
$this->status = Event::NORMAL;
}
public function isForced(){
return ($this->status & Event::FORCE) > 0;
return static::$handlerList;
}
}

View File

@ -1,59 +0,0 @@
<?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\Event;
/**
* Triggers events and its handlers in the correct order, attaching and removing from them
*/
abstract class EventHandler{
public static function callEvent(Event $event){
if(count($event::$handlerPriority) === 0){
return Event::NORMAL;
}
foreach($event::$handlerPriority as $priority => $handlerList){
if(count($handlerList) > 0){
$event->setPrioritySlot($priority);
foreach($handlerList as $handler){
call_user_func($handler, $event);
}
if($event->isForced()){
if($event instanceof CancellableEvent and $event->isCancelled()){
return Event::DENY;
}else{
return Event::ALLOW;
}
}
}
}
if($event instanceof CancellableEvent and $event->isCancelled()){
return Event::DENY;
}elseif($event->isAllowed()){
return Event::ALLOW;
}else{
return Event::NORMAL;
}
}
}

View File

@ -0,0 +1,172 @@
<?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\Event;
use PocketMine\Plugin\Plugin;
use PocketMine\Plugin\RegisteredListener;
class HandlerList{
/**
* @var RegisteredListener[]
*/
private $handlers = null;
/**
* @var RegisteredListener[][]
*/
private $handlerSlots = array();
/**
* @var HandlerList[]
*/
private static $allLists = array();
public static function bakeAll(){
foreach(self::$allLists as $h){
$h->bake();
}
}
/**
* Unregisters all the listeners
* If a Plugin or Listener is passed, all the listeners with that object will be removed
*
* @param Plugin|Listener|null $object
*/
public static function unregisterAll($object = null){
if($object instanceof Listener or $object instanceof Plugin){
foreach(self::$allLists as $h){
$h->unregister($object);
}
}else{
foreach(self::$allLists as $h){
foreach($h->handlerSlots as $key => $list){
$h->handlerSlots[$key] = array();
}
$h->handlers = null;
}
}
}
public function __construct(){
$this->handlerSlots = array(
EventPriority::MONITOR => array(),
EventPriority::HIGHEST => array(),
EventPriority::HIGH => array(),
EventPriority::NORMAL => array(),
EventPriority::LOW => array(),
EventPriority::LOWEST => array()
);
self::$allLists[] = $this;
}
public function register(RegisteredListener $listener){
if($listener->getPriority() < EventPriority::MONITOR or $listener->getPriority() > EventPriority::LOWEST){
return;
}
if(isset($this->handlerSlots[$listener->getPriority()][spl_object_hash($listener)])){
trigger_error("This listener is already registered to priority ".$listener->getPriority(), E_USER_WARNING);
return;
}
$this->handlers = null;
$this->handlerSlots[$listener->getPriority()][spl_object_hash($listener)] = $listener;
}
/**
* @param RegisteredListener[] $listeners
*/
public function registerAll(array $listeners){
foreach($listeners as $listener){
$this->register($listener);
}
}
/**
* @param RegisteredListener|Listener|Plugin $object
*/
public function unregister($object){
if($object instanceof Plugin or $object instanceof Listener){
$changed = false;
foreach($this->handlerSlots as $priority => $list){
foreach($list as $hash => $listener){
if(($object instanceof Plugin and $listener->getPlugin() === $object)
or ($object instanceof Listener and $listener->getListener() === $object)){
unset($this->handlerSlots[$priority][$hash]);
$changed = true;
}
}
}
if($changed === true){
$this->handlers = null;
}
}elseif($object instanceof RegisteredListener){
if(isset($this->handlerSlots[$object->getPriority()][spl_object_hash($listener)])){
unset($this->handlerSlots[$object->getPriority()][spl_object_hash($listener)]);
$this->handlers = null;
}
}
}
public function bake(){
if($this->handlers !== null){
return;
}
$entries = array();
foreach($this->handlerSlots as $list){
foreach($list as $hash => $listener){
$entries[$hash] = $listener;
}
}
$this->handlers = $entries;
}
/**
* @param null|Plugin $plugin
*
* @return RegisteredListener[]
*/
public function getRegisteredListeners($plugin = null){
if($plugin instanceof Plugin){
$listeners = array();
foreach($this->getRegisteredListeners(null) as $hash => $listener){
if($listener->getPlugin() === $plugin){
$listeners[$hash] = $plugin;
}
}
return $listeners;
}else{
while(($handlers = $this->handlers) === null){
$this->bake();
}
return $handlers;
}
}
/**
* @return HandlerList[]
*/
public static function getHandlerLists(){
return self::$allLists;
}
}

View File

@ -0,0 +1,26 @@
<?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\Event;
interface Listener{
}

View File

@ -22,13 +22,12 @@
namespace PocketMine\Event\Block;
use PocketMine\Block\Block;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Item\Item;
use PocketMine\Player;
class BlockBreakEvent extends BlockEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class BlockBreakEvent extends BlockEvent implements Cancellable{
public static $handlerList = null;
/**
* @var \PocketMine\Player

View File

@ -22,16 +22,15 @@
namespace PocketMine\Event\Block;
use PocketMine\Block\Block;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Item\Item;
use PocketMine\Player;
/**
* Called when a player places a block
*/
class BlockPlaceEvent extends BlockEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class BlockPlaceEvent extends BlockEvent implements Cancellable{
public static $handlerList = null;
/**
* @var \PocketMine\Player

View File

@ -22,13 +22,12 @@
namespace PocketMine\Event\Entity;
use PocketMine\Entity\Entity;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Item\Item;
class EntityArmorChangeEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class EntityArmorChangeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
private $oldItem;
private $newItem;

View File

@ -32,8 +32,7 @@ use PocketMine\Entity\Vehicle;
* Called when a entity is despawned
*/
class EntityDespawnEvent extends EntityEvent{
public static $handlers;
public static $handlerPriority;
public static $handlerList = null;
/**
* @param Entity $entity

View File

@ -23,15 +23,14 @@ namespace PocketMine\Event\Entity;
use PocketMine\Block\Block;
use PocketMine\Entity\Entity;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Level\Position;
/**
* Called when a entity explodes
*/
class EntityExplodeEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class EntityExplodeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/**
* @var Position

View File

@ -22,13 +22,12 @@
namespace PocketMine\Event\Entity;
use PocketMine\Entity\Entity;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Item\Item;
class EntityInventoryChangeEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class EntityInventoryChangeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
private $oldItem;
private $newItem;

View File

@ -22,13 +22,12 @@
namespace PocketMine\Event\Entity;
use PocketMine\Entity\Entity;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Level\Level;
class EntityLevelChangeEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class EntityLevelChangeEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
private $originLevel;
private $targetLevel;

View File

@ -22,13 +22,12 @@
namespace PocketMine\Event\Entity;
use PocketMine\Entity\Entity;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Math\Vector3 as Vector3;
class EntityMotionEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class EntityMotionEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
private $mot;

View File

@ -22,13 +22,12 @@
namespace PocketMine\Event\Entity;
use PocketMine\Entity\Entity;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Math\Vector3 as Vector3;
class EntityMoveEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class EntityMoveEvent extends EntityEvent implements Cancellable{
public static $handlerList = null;
/**
* @var \PocketMine\Math\Vector3

View File

@ -32,8 +32,7 @@ use PocketMine\Entity\Vehicle;
* Called when a entity is spawned
*/
class EntitySpawnEvent extends EntityEvent{
public static $handlers;
public static $handlerPriority;
public static $handlerList = null;
/**
* @param Entity $entity

View File

@ -21,15 +21,14 @@
namespace PocketMine\Event\Player;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Player;
/**
* Called when a player is awarded an achievement
*/
class PlayerAchievementAwardedEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerAchievementAwardedEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/**
* @var string

View File

@ -21,15 +21,14 @@
namespace PocketMine\Event\Player;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Player;
/**
* Called when a player chats something
*/
class PlayerChatEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerChatEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/**
* @var string

View File

@ -21,15 +21,14 @@
namespace PocketMine\Event\Player;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Player;
/**
* Called when a player has its gamemode changed
*/
class PlayerGameModeChangeEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/**
* @var int

View File

@ -22,16 +22,15 @@
namespace PocketMine\Event\Player;
use PocketMine\Block\Block;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Item\Item;
use PocketMine\Player;
/**
* Called when a player interacts or touches a block (including air?)
*/
class PlayerInteractEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerInteractEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/**
* @var \PocketMine\Block\Block;

View File

@ -22,13 +22,12 @@
namespace PocketMine\Event\Player;
use PocketMine\Event;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Item\Item;
use PocketMine\Player;
class PlayerItemHeldEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerItemHeldEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
private $item;
private $slot;

View File

@ -27,8 +27,7 @@ use PocketMine\Player;
* Called when a player joins the server, after sending all the spawn packets
*/
class PlayerJoinEvent extends PlayerEvent{
public static $handlers;
public static $handlerPriority;
public static $handlerList = null;
/**
* @var string

View File

@ -21,15 +21,14 @@
namespace PocketMine\Event\Player;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Player;
/**
* Called when a player leaves the server
*/
class PlayerKickEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerKickEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/**
* @var string

View File

@ -21,15 +21,14 @@
namespace PocketMine\Event\Player;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Player;
/**
* Called when a player joins, after things have been correctly set up (you can change anything now)
*/
class PlayerLoginEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerLoginEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/**
* @var string

View File

@ -21,15 +21,14 @@
namespace PocketMine\Event\Player;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Player;
/**
* Called when the player logs in, before things have been set up
*/
class PlayerPreLoginEvent extends PlayerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PlayerPreLoginEvent extends PlayerEvent implements Cancellable{
public static $handlerList = null;
/**
* @var string

View File

@ -27,8 +27,7 @@ use PocketMine\Player;
* Called when a player leaves the server
*/
class PlayerQuitEvent extends PlayerEvent{
public static $handlers;
public static $handlerPriority;
public static $handlerList = null;
/**
* @var string

View File

@ -27,8 +27,7 @@ use PocketMine\Plugin\Plugin;
class PluginDisableEvent extends Event{
public static $handlers;
public static $handlerPriority;
public static $handlerList = null;
/**
* @param Plugin $plugin

View File

@ -27,8 +27,7 @@ use PocketMine\Plugin\Plugin;
class PluginEnableEvent extends Event{
public static $handlers;
public static $handlerPriority;
public static $handlerList = null;
/**
* @param Plugin $plugin

View File

@ -21,14 +21,13 @@
namespace PocketMine\Event\Server;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Network\Protocol\DataPacket;
use PocketMine\Player;
class DataPacketReceiveEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class DataPacketReceiveEvent extends ServerEvent implements Cancellable{
public static $handlerList = null;
private $packet;
private $player;

View File

@ -21,14 +21,13 @@
namespace PocketMine\Event\Server;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Network\Protocol\DataPacket;
use PocketMine\Player;
class DataPacketSendEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class DataPacketSendEvent extends ServerEvent implements Cancellable{
public static $handlerList = null;
private $packet;
private $player;

View File

@ -21,13 +21,12 @@
namespace PocketMine\Event\Server;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Network\Packet;
class PacketReceiveEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PacketReceiveEvent extends ServerEvent implements Cancellable{
public static $handlerList = null;
private $packet;

View File

@ -21,13 +21,12 @@
namespace PocketMine\Event\Server;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Network\Packet;
class PacketSendEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class PacketSendEvent extends ServerEvent implements Cancellable{
public static $handlerList = null;
private $packet;

View File

@ -21,14 +21,13 @@
namespace PocketMine\Event\Tile;
use PocketMine\Event\CancellableEvent;
use PocketMine\Event\Cancellable;
use PocketMine\Event;
use PocketMine\Item\Item;
use PocketMine\Tile\Tile;
class TileInventoryChangeEvent extends TileEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
class TileInventoryChangeEvent extends TileEvent implements Cancellable{
public static $handlerList = null;
private $oldItem;
private $newItem;

View File

@ -26,11 +26,11 @@ use PocketMine\Block\TNT;
use PocketMine\Entity\Entity;
use PocketMine\Event\Entity\EntityExplodeEvent;
use PocketMine\Event\Event;
use PocketMine\Event\EventHandler;
use PocketMine\Item\Item;
use PocketMine\Math\Vector3 as Vector3;
use PocketMine\Network\Protocol\ExplodePacket;
use PocketMine\Player;
use PocketMine\Server;
class Explosion{
public static $specialDrops = array(
@ -102,8 +102,9 @@ class Explosion{
$yield = (1 / $this->size) * 100;
if($this->what instanceof Entity){
if(EventHandler::callEvent($ev = new EntityExplodeEvent($this->what, $this->source, $this->affectedBlocks, $yield)) === Event::DENY){
return;
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityExplodeEvent($this->what, $this->source, $this->affectedBlocks, $yield));
if($ev->isCancelled()){
return false;
}else{
$yield = $ev->getYield();
$this->affectedBlocks = $ev->getBlockList();

View File

@ -29,7 +29,6 @@ use PocketMine\Block\Block;
use PocketMine\Event\Block\BlockBreakEvent;
use PocketMine\Event\Block\BlockPlaceEvent;
use PocketMine\Event\Event;
use PocketMine\Event\EventHandler;
use PocketMine\Event\Player\PlayerInteractEvent;
use PocketMine\Item\Item;
use PocketMine\Level\Generator\Flat;
@ -750,7 +749,8 @@ class Level{
if($item instanceof Item and !$target->isBreakable($item) and $ev->getInstaBreak() === false){
$ev->setCancelled();
}
if(EventHandler::callEvent($ev) === Event::DENY){
$this->server->getPluginManager()->callEvent($ev);
if($ev->isCancelled()){
return false;
}
}elseif($item instanceof Item and !$target->isBreakable($item)){
@ -793,8 +793,11 @@ class Level{
return false;
}
if($player instanceof Player and EventHandler::callEvent($ev = new PlayerInteractEvent($player, $item, $target, $face)) !== Event::DENY){
$target->onUpdate(Level::BLOCK_UPDATE_TOUCH);
if($player instanceof Player){
$this->server->getPluginManager()->callEvent($ev = new PlayerInteractEvent($player, $item, $target, $face));
if(!$ev->isCancelled()){
$target->onUpdate(Level::BLOCK_UPDATE_TOUCH);
}
}
if($target->isActivable === true and $target->onActivate($item, $player) === true){
@ -826,10 +829,13 @@ class Level{
/*if($hand->isSolid === true and $player->inBlock($block)){
return false; //Entity in block
}*/
$ev = new BlockPlaceEvent($player, $hand, $block, $target, $item);
if($player instanceof Player and EventHandler::callEvent($ev) === Event::DENY){
return false;
if($player instanceof Player){
$this->server->getPluginManager()->callEvent($ev = new BlockPlaceEvent($player, $hand, $block, $target, $item));
if($ev->isCancelled()){
return false;
}
}elseif($hand->place($item, $block, $target, $face, $fx, $fy, $fz, $player) === false){
return false;
}

View File

@ -0,0 +1,36 @@
<?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\Plugin;
use PocketMine\Event\Event;
use PocketMine\Event\Listener;
interface EventExecutor{
/**
* @param Listener $listener
* @param Event $event
*
* @return void
*/
public function execute(Listener $listener, Event $event);
}

View File

@ -21,7 +21,6 @@
namespace PocketMine\Plugin;
use PocketMine\Event\EventHandler;
use PocketMine\Event\Plugin\PluginDisableEvent;
use PocketMine\Event\Plugin\PluginEnableEvent;
use PocketMine\Server;
@ -97,26 +96,38 @@ class FolderPluginLoader implements PluginLoader{
return "/[^\\.]/";
}
/**
* @param PluginBase $plugin
* @param PluginDescription $description
* @param string $dataFolder
* @param string $file
*/
private function initPlugin(PluginBase $plugin, PluginDescription $description, $dataFolder, $file){
$plugin->init($this, $this->server, $description, $dataFolder, $file);
$plugin->onLoad();
}
/**
* @param Plugin $plugin
*/
public function enablePlugin(Plugin $plugin){
if($plugin instanceof PluginBase and !$plugin->isEnabled()){
console("[INFO] Enabling ".$plugin->getDescription()->getName());
$plugin->setEnabled(true);
EventHandler::callEvent(new PluginEnableEvent($plugin));
Server::getInstance()->getPluginManager()->callEvent(new PluginEnableEvent($plugin));
}
}
/**
* @param Plugin $plugin
*/
public function disablePlugin(Plugin $plugin){
if($plugin instanceof PluginBase and $plugin->isEnabled()){
console("[INFO] Disabling ".$plugin->getDescription()->getName());
EventHandler::callEvent(new PluginDisableEvent($plugin));
Server::getInstance()->getPluginManager()->callEvent(new PluginDisableEvent($plugin));
$plugin->setEnabled(false);
}

View File

@ -20,6 +20,7 @@
*/
namespace PocketMine\Plugin;
use PocketMine\Event\Listener;
/**
* Handles different types of plugins
@ -65,4 +66,5 @@ interface PluginLoader{
*/
public function disablePlugin(Plugin $plugin);
}

View File

@ -22,11 +22,14 @@
namespace PocketMine\Plugin;
use PocketMine\Command\PluginCommand;
use PocketMine\Event\Cancellable;
use PocketMine\Event\Event;
use PocketMine\Event\Listener;
use PocketMine\Permission\Permissible;
use PocketMine\Permission\Permission;
use PocketMine\Server;
use PocketMine\Command\SimpleCommandMap;
use PocketMine\Event\HandlerList;
/**
* Manages all the plugins, Permissions and Permissibles
@ -569,7 +572,7 @@ class PluginManager{
if($plugin->isEnabled()){
$plugin->getPluginLoader()->disablePlugin($plugin);
$this->server->getScheduler()->cancelTasks($plugin);
Event::unregisterPlugin($plugin);
HandlerList::unregisterAll($plugin);
}
}
@ -582,5 +585,58 @@ class PluginManager{
$this->defaultPermsOp = array();
}
/**
* Calls an event
*
* @param Event $event
*/
public function callEvent(Event $event){
$this->fireEvent($event);
}
private function fireEvent(Event $event){
$handlers = $event->getHandlers();
$listeners = $handlers->getRegisteredListeners();
foreach($listeners as $registration){
if(!$registration->getPlugin()->isEnabled()){
continue;
}
$registration->callEvent($event);
}
}
/**
* @param string $event Class name that extends Event
* @param Listener $listener
* @param int $priority
* @param EventExecutor $executor
* @param Plugin $plugin
* @param bool $ignoreCancelled
*/
public function registerEvent($event, Listener $listener, $priority, EventExecutor $executor, Plugin $plugin, $ignoreCancelled = false){
if(!is_subclass_of($event, "PocketMine\\Event\\Event")){
trigger_error($event ." is not a valid Event", E_USER_WARNING);
return;
}
if(!$plugin->isEnabled()){
trigger_error("Plugin attempted to register ".$event." while not enabled");
return;
}
$this->getEventListeners($event)->register(new RegisteredListener($listener, $executor, $priority, $plugin, $ignoreCancelled));
}
/**
* @param string $event
*
* @return HandlerList
*/
private function getEventListeners($event){
if($event::$handlerList === null){
$event::$handlerList = new HandlerList();
}
return $event::$handlerList;
}
}

View File

@ -0,0 +1,107 @@
<?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\Plugin;
use PocketMine\Event\Cancellable;
use PocketMine\Event\Event;
use PocketMine\Event\Listener;
class RegisteredListener{
/**
* @var Listener
*/
private $listener;
/**
* @var int
*/
private $priority;
/**
* @var Plugin
*/
private $plugin;
/**
* @var EventExecutor
*/
private $executor;
/**
* @var bool
*/
private $ignoreCancelled;
/**
* @param Listener $listener
* @param EventExecutor $executor
* @param int $priority
* @param Plugin $plugin
* @param boolean $ignoreCancelled
*/
public function __construct(Listener $listener, EventExecutor $executor, $priority, Plugin $plugin, $ignoreCancelled){
$this->listener = $listener;
$this->priority = $priority;
$this->plugin = $plugin;
$this->executor = $executor;
$this->ignoreCancelled = $ignoreCancelled;
}
/**
* @return Listener
*/
public function getListener(){
return $this->listener;
}
/**
* @return Plugin
*/
public function getPlugin(){
return $this->plugin;
}
/**
* @return int
*/
public function getPriority(){
return $this->priority;
}
/**
* @param Event $event
*/
public function callEvent(Event $event){
if($event instanceof Cancellable and $event->isCancelled() and $this->isIgnoringCancelled()){
return;
}
$this->executor->execute($this->listener, $event);
}
/**
* @return bool
*/
public function isIgnoringCancelled(){
return $this->ignoreCancelled === true;
}
}

View File

@ -22,7 +22,6 @@
namespace PocketMine\Tile;
use PocketMine\Event\Event;
use PocketMine\Event\EventHandler;
use PocketMine\Event\Tile\TileInventoryChangeEvent;
use PocketMine\Item\Item;
use PocketMine\NBT\Tag\Byte;
@ -30,6 +29,7 @@ use PocketMine\NBT\Tag\Compound;
use PocketMine\NBT\Tag\Short;
use PocketMine\Network;
use PocketMine\Player;
use PocketMine\Server;
trait Container{
public function openInventory(Player $player){
@ -158,8 +158,11 @@ trait Container{
public function setSlot($s, Item $item, $update = true, $offset = 0){
$i = $this->getSlotIndex($s);
if($i === false or EventHandler::callEvent($ev = new TileInventoryChangeEvent($this, $this->getSlot($s), $item, $s, $offset)) === Event::DENY){
if($i === false){
return false;
}
Server::getInstance()->getPluginManager()->callEvent($ev = new TileInventoryChangeEvent($this, $this->getSlot($s), $item, $s, $offset));
if($ev->isCancelled()){
return false;
}