diff --git a/src/PocketMine/Player.php b/src/PocketMine/Player.php index e3d5492b1..73201e523 100644 --- a/src/PocketMine/Player.php +++ b/src/PocketMine/Player.php @@ -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(); diff --git a/src/PocketMine/Server.php b/src/PocketMine/Server.php index 26d7046a1..f8405b68a 100644 --- a/src/PocketMine/Server.php +++ b/src/PocketMine/Server.php @@ -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); } diff --git a/src/PocketMine/entity/Entity.php b/src/PocketMine/entity/Entity.php index 25677fea0..a7e705646 100644 --- a/src/PocketMine/entity/Entity.php +++ b/src/PocketMine/entity/Entity.php @@ -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)); } } diff --git a/src/PocketMine/entity/Human.php b/src/PocketMine/entity/Human.php index 225b02b9c..4c3aa033d 100644 --- a/src/PocketMine/entity/Human.php +++ b/src/PocketMine/entity/Human.php @@ -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(); diff --git a/src/PocketMine/event/CancellableEvent.php b/src/PocketMine/event/Cancellable.php similarity index 88% rename from src/PocketMine/event/CancellableEvent.php rename to src/PocketMine/event/Cancellable.php index 0c85353db..72f0fc0fa 100644 --- a/src/PocketMine/event/CancellableEvent.php +++ b/src/PocketMine/event/Cancellable.php @@ -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); } \ No newline at end of file diff --git a/src/PocketMine/event/Event.php b/src/PocketMine/event/Event.php index 673fe7fa5..274b00c19 100644 --- a/src/PocketMine/event/Event.php +++ b/src/PocketMine/event/Event.php @@ -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; } } \ No newline at end of file diff --git a/src/PocketMine/event/EventHandler.php b/src/PocketMine/event/EventHandler.php deleted file mode 100644 index 0ff11e2e3..000000000 --- a/src/PocketMine/event/EventHandler.php +++ /dev/null @@ -1,59 +0,0 @@ - $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; - } - } - -} \ No newline at end of file diff --git a/src/PocketMine/event/HandlerList.php b/src/PocketMine/event/HandlerList.php new file mode 100644 index 000000000..e4473890b --- /dev/null +++ b/src/PocketMine/event/HandlerList.php @@ -0,0 +1,172 @@ +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; + } + +} \ No newline at end of file diff --git a/src/PocketMine/event/Listener.php b/src/PocketMine/event/Listener.php new file mode 100644 index 000000000..d9afbbd36 --- /dev/null +++ b/src/PocketMine/event/Listener.php @@ -0,0 +1,26 @@ +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(); diff --git a/src/PocketMine/level/Level.php b/src/PocketMine/level/Level.php index 50c0738a2..69c77420e 100644 --- a/src/PocketMine/level/Level.php +++ b/src/PocketMine/level/Level.php @@ -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; } diff --git a/src/PocketMine/plugin/EventExecutor.php b/src/PocketMine/plugin/EventExecutor.php new file mode 100644 index 000000000..ddee9dd94 --- /dev/null +++ b/src/PocketMine/plugin/EventExecutor.php @@ -0,0 +1,36 @@ +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); } diff --git a/src/PocketMine/plugin/PluginLoader.php b/src/PocketMine/plugin/PluginLoader.php index 0fba6585b..9b69d5538 100644 --- a/src/PocketMine/plugin/PluginLoader.php +++ b/src/PocketMine/plugin/PluginLoader.php @@ -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); + } \ No newline at end of file diff --git a/src/PocketMine/plugin/PluginManager.php b/src/PocketMine/plugin/PluginManager.php index 75452b0b8..6178fcf23 100644 --- a/src/PocketMine/plugin/PluginManager.php +++ b/src/PocketMine/plugin/PluginManager.php @@ -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; + } } \ No newline at end of file diff --git a/src/PocketMine/plugin/RegisteredListener.php b/src/PocketMine/plugin/RegisteredListener.php new file mode 100644 index 000000000..6e94269f6 --- /dev/null +++ b/src/PocketMine/plugin/RegisteredListener.php @@ -0,0 +1,107 @@ +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; + } +} \ No newline at end of file diff --git a/src/PocketMine/tile/Container.php b/src/PocketMine/tile/Container.php index bde9a0351..895ad899d 100644 --- a/src/PocketMine/tile/Container.php +++ b/src/PocketMine/tile/Container.php @@ -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; }