PocketMine-MP 5.21.2 git-a6534ecbbbcf369264567d27e5ed70f7f5be9816
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
34 private array $handlerSlots = [];
35
37 private array $affectedHandlerCaches = [];
38
42 public function __construct(
43 private string $class,
44 private ?HandlerList $parentList,
45 private RegisteredListenerCache $handlerCache = new RegisteredListenerCache()
46 ){
47 for($list = $this; $list !== null; $list = $list->parentList){
48 $list->affectedHandlerCaches[spl_object_id($this->handlerCache)] = $this->handlerCache;
49 }
50 }
51
55 public function register(RegisteredListener $listener) : void{
56 if(isset($this->handlerSlots[$listener->getPriority()][spl_object_id($listener)])){
57 throw new \InvalidArgumentException("This listener is already registered to priority {$listener->getPriority()} of event {$this->class}");
58 }
59 $this->handlerSlots[$listener->getPriority()][spl_object_id($listener)] = $listener;
60 $this->invalidateAffectedCaches();
61 }
62
66 public function registerAll(array $listeners) : void{
67 foreach($listeners as $listener){
68 $this->register($listener);
69 }
70 $this->invalidateAffectedCaches();
71 }
72
73 public function unregister(RegisteredListener|Plugin|Listener $object) : void{
74 if($object instanceof Plugin || $object instanceof Listener){
75 foreach($this->handlerSlots as $priority => $list){
76 foreach($list as $hash => $listener){
77 if(($object instanceof Plugin && $listener->getPlugin() === $object)
78 || ($object instanceof Listener && (new \ReflectionFunction($listener->getHandler()))->getClosureThis() === $object) //this doesn't even need to be a listener :D
79 ){
80 unset($this->handlerSlots[$priority][$hash]);
81 }
82 }
83 }
84 }else{
85 unset($this->handlerSlots[$object->getPriority()][spl_object_id($object)]);
86 }
87 $this->invalidateAffectedCaches();
88 }
89
90 public function clear() : void{
91 $this->handlerSlots = [];
92 $this->invalidateAffectedCaches();
93 }
94
98 public function getListenersByPriority(int $priority) : array{
99 return $this->handlerSlots[$priority] ?? [];
100 }
101
102 public function getParent() : ?HandlerList{
103 return $this->parentList;
104 }
105
109 private function invalidateAffectedCaches() : void{
110 foreach($this->affectedHandlerCaches as $cache){
111 $cache->list = null;
112 }
113 }
114
119 public function getListenerList() : array{
120 if($this->handlerCache->list !== null){
121 return $this->handlerCache->list;
122 }
123
124 $handlerLists = [];
125 for($currentList = $this; $currentList !== null; $currentList = $currentList->parentList){
126 $handlerLists[] = $currentList;
127 }
128
129 $listenersByPriority = [];
130 foreach($handlerLists as $currentList){
131 foreach($currentList->handlerSlots as $priority => $listeners){
132 $listenersByPriority[$priority] = array_merge($listenersByPriority[$priority] ?? [], $listeners);
133 }
134 }
135
136 //TODO: why on earth do the priorities have higher values for lower priority?
137 krsort($listenersByPriority, SORT_NUMERIC);
138
139 return $this->handlerCache->list = array_merge(...$listenersByPriority);
140 }
141}
__construct(private string $class, private ?HandlerList $parentList, private RegisteredListenerCache $handlerCache=new RegisteredListenerCache())
registerAll(array $listeners)
getListenersByPriority(int $priority)