PocketMine-MP 5.23.3 git-f7687af337d001ddbcc47b8e773f014a33faa662
Loading...
Searching...
No Matches
HandlerList.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\event;
25
27use function array_merge;
28use function krsort;
29use function spl_object_id;
30use const SORT_NUMERIC;
31
37 private array $handlerSlots = [];
38
40 private array $affectedHandlerCaches = [];
41
45 public function __construct(
46 private string $class,
47 private ?HandlerList $parentList,
48 private RegisteredListenerCache $handlerCache = new RegisteredListenerCache()
49 ){
50 for($list = $this; $list !== null; $list = $list->parentList){
51 $list->affectedHandlerCaches[spl_object_id($this->handlerCache)] = $this->handlerCache;
52 }
53 }
54
58 public function register(RegisteredListener $listener) : void{
59 if(isset($this->handlerSlots[$listener->getPriority()][spl_object_id($listener)])){
60 throw new \InvalidArgumentException("This listener is already registered to priority {$listener->getPriority()} of event {$this->class}");
61 }
62 $this->handlerSlots[$listener->getPriority()][spl_object_id($listener)] = $listener;
63 $this->invalidateAffectedCaches();
64 }
65
69 public function registerAll(array $listeners) : void{
70 foreach($listeners as $listener){
71 $this->register($listener);
72 }
73 $this->invalidateAffectedCaches();
74 }
75
76 public function unregister(RegisteredListener|Plugin|Listener $object) : void{
77 if($object instanceof Plugin || $object instanceof Listener){
78 foreach($this->handlerSlots as $priority => $list){
79 foreach($list as $hash => $listener){
80 if(($object instanceof Plugin && $listener->getPlugin() === $object)
81 || ($object instanceof Listener && (new \ReflectionFunction($listener->getHandler()))->getClosureThis() === $object) //this doesn't even need to be a listener :D
82 ){
83 unset($this->handlerSlots[$priority][$hash]);
84 }
85 }
86 }
87 }else{
88 unset($this->handlerSlots[$object->getPriority()][spl_object_id($object)]);
89 }
90 $this->invalidateAffectedCaches();
91 }
92
93 public function clear() : void{
94 $this->handlerSlots = [];
95 $this->invalidateAffectedCaches();
96 }
97
101 public function getListenersByPriority(int $priority) : array{
102 return $this->handlerSlots[$priority] ?? [];
103 }
104
105 public function getParent() : ?HandlerList{
106 return $this->parentList;
107 }
108
112 private function invalidateAffectedCaches() : void{
113 foreach($this->affectedHandlerCaches as $cache){
114 $cache->list = null;
115 }
116 }
117
122 public function getListenerList() : array{
123 if($this->handlerCache->list !== null){
124 return $this->handlerCache->list;
125 }
126
127 $handlerLists = [];
128 for($currentList = $this; $currentList !== null; $currentList = $currentList->parentList){
129 $handlerLists[] = $currentList;
130 }
131
132 $listenersByPriority = [];
133 foreach($handlerLists as $currentList){
134 foreach($currentList->handlerSlots as $priority => $listeners){
135 $listenersByPriority[$priority] = array_merge($listenersByPriority[$priority] ?? [], $listeners);
136 }
137 }
138
139 //TODO: why on earth do the priorities have higher values for lower priority?
140 krsort($listenersByPriority, SORT_NUMERIC);
141
142 return $this->handlerCache->list = array_merge(...$listenersByPriority);
143 }
144}
__construct(private string $class, private ?HandlerList $parentList, private RegisteredListenerCache $handlerCache=new RegisteredListenerCache())
registerAll(array $listeners)
getListenersByPriority(int $priority)