diff --git a/src/Server.php b/src/Server.php index 137b65f19..ddcb05027 100644 --- a/src/Server.php +++ b/src/Server.php @@ -62,7 +62,6 @@ use pocketmine\network\query\QueryInfo; use pocketmine\network\upnp\UPnP; use pocketmine\permission\BanList; use pocketmine\permission\DefaultPermissions; -use pocketmine\permission\PermissionManager; use pocketmine\player\GameMode; use pocketmine\player\OfflinePlayer; use pocketmine\player\Player; @@ -277,6 +276,12 @@ class Server{ /** @var Player[] */ private $playerList = []; + /** + * @var CommandSender[][] + * @phpstan-var array> + */ + private $broadcastSubscribers = []; + public function getName() : string{ return VersionInfo::NAME; } @@ -1063,8 +1068,8 @@ class Server{ //TODO: move console parts to a separate component $consoleSender = new ConsoleCommandSender($this, $this->language); - PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $consoleSender); - PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $consoleSender); + $this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $consoleSender); + $this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $consoleSender); $consoleNotifier = new SleeperNotifier(); $this->console = new CommandReader($consoleNotifier); @@ -1084,19 +1089,51 @@ class Server{ } } + /** + * Subscribes to a particular message broadcast channel. + * The channel ID can be any arbitrary string. + */ + public function subscribeToBroadcastChannel(string $channelId, CommandSender $subscriber) : void{ + $this->broadcastSubscribers[$channelId][spl_object_id($subscriber)] = $subscriber; + } + + /** + * Unsubscribes from a particular message broadcast channel. + */ + public function unsubscribeFromBroadcastChannel(string $channelId, CommandSender $subscriber) : void{ + if(isset($this->broadcastSubscribers[$channelId][spl_object_id($subscriber)])){ + unset($this->broadcastSubscribers[$channelId][spl_object_id($subscriber)]); + if(count($this->broadcastSubscribers[$channelId]) === 0){ + unset($this->broadcastSubscribers[$channelId]); + } + } + } + + /** + * Unsubscribes from all broadcast channels. + */ + public function unsubscribeFromAllBroadcastChannels(CommandSender $subscriber) : void{ + foreach($this->broadcastSubscribers as $channelId => $recipients){ + $this->unsubscribeFromBroadcastChannel($channelId, $subscriber); + } + } + + /** + * Returns a list of all the CommandSenders subscribed to the given broadcast channel. + * + * @return CommandSender[] + * @phpstan-return array + */ + public function getBroadcastChannelSubscribers(string $channelId) : array{ + return $this->broadcastSubscribers[$channelId] ?? []; + } + /** * @param TranslationContainer|string $message * @param CommandSender[]|null $recipients */ public function broadcastMessage($message, ?array $recipients = null) : int{ - if(!is_array($recipients)){ - $recipients = []; - foreach(PermissionManager::getInstance()->getPermissionSubscriptions(self::BROADCAST_CHANNEL_USERS) as $permissible){ - if($permissible instanceof CommandSender and $permissible->hasPermission(self::BROADCAST_CHANNEL_USERS)){ - $recipients[spl_object_id($permissible)] = $permissible; // do not send messages directly, or some might be repeated - } - } - } + $recipients = $recipients ?? $this->getBroadcastChannelSubscribers(self::BROADCAST_CHANNEL_USERS); foreach($recipients as $recipient){ $recipient->sendMessage($message); @@ -1108,12 +1145,12 @@ class Server{ /** * @return Player[] */ - private function selectPermittedPlayers(string $permission) : array{ + private function getPlayerBroadcastSubscribers(string $channelId) : array{ /** @var Player[] $players */ $players = []; - foreach(PermissionManager::getInstance()->getPermissionSubscriptions($permission) as $permissible){ - if($permissible instanceof Player and $permissible->hasPermission($permission)){ - $players[spl_object_id($permissible)] = $permissible; //prevent duplication + foreach($this->broadcastSubscribers[$channelId] as $subscriber){ + if($subscriber instanceof Player){ + $players[spl_object_id($subscriber)] = $subscriber; } } return $players; @@ -1123,7 +1160,7 @@ class Server{ * @param Player[]|null $recipients */ public function broadcastTip(string $tip, ?array $recipients = null) : int{ - $recipients = $recipients ?? $this->selectPermittedPlayers(self::BROADCAST_CHANNEL_USERS); + $recipients = $recipients ?? $this->getPlayerBroadcastSubscribers(self::BROADCAST_CHANNEL_USERS); foreach($recipients as $recipient){ $recipient->sendTip($tip); @@ -1136,7 +1173,7 @@ class Server{ * @param Player[]|null $recipients */ public function broadcastPopup(string $popup, ?array $recipients = null) : int{ - $recipients = $recipients ?? $this->selectPermittedPlayers(self::BROADCAST_CHANNEL_USERS); + $recipients = $recipients ?? $this->getPlayerBroadcastSubscribers(self::BROADCAST_CHANNEL_USERS); foreach($recipients as $recipient){ $recipient->sendPopup($popup); @@ -1152,7 +1189,7 @@ class Server{ * @param Player[]|null $recipients */ public function broadcastTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1, ?array $recipients = null) : int{ - $recipients = $recipients ?? $this->selectPermittedPlayers(self::BROADCAST_CHANNEL_USERS); + $recipients = $recipients ?? $this->getPlayerBroadcastSubscribers(self::BROADCAST_CHANNEL_USERS); foreach($recipients as $recipient){ $recipient->sendTitle($title, $subtitle, $fadeIn, $stay, $fadeOut); diff --git a/src/command/Command.php b/src/command/Command.php index 4ab99e0a5..3c52ed4d4 100644 --- a/src/command/Command.php +++ b/src/command/Command.php @@ -234,7 +234,7 @@ abstract class Command{ * @param TranslationContainer|string $message */ public static function broadcastCommandMessage(CommandSender $source, $message, bool $sendToSource = true) : void{ - $users = PermissionManager::getInstance()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_ADMINISTRATIVE); + $users = $source->getServer()->getBroadcastChannelSubscribers(Server::BROADCAST_CHANNEL_ADMINISTRATIVE); if($message instanceof TranslationContainer){ $formatted = "[" . $source->getName() . ": " . ($source->getLanguage()->get($message->getText()) !== $message->getText() ? "%" : "") . $message->getText() . "]"; @@ -250,12 +250,10 @@ abstract class Command{ } foreach($users as $user){ - if($user instanceof CommandSender){ - if($user instanceof ConsoleCommandSender){ - $user->sendMessage($result); - }elseif($user !== $source){ - $user->sendMessage($colored); - } + if($user instanceof ConsoleCommandSender){ + $user->sendMessage($result); + }elseif($user !== $source){ + $user->sendMessage($colored); } } } diff --git a/src/event/player/PlayerChatEvent.php b/src/event/player/PlayerChatEvent.php index 33d56daeb..138410357 100644 --- a/src/event/player/PlayerChatEvent.php +++ b/src/event/player/PlayerChatEvent.php @@ -26,11 +26,8 @@ namespace pocketmine\event\player; use pocketmine\command\CommandSender; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -use pocketmine\permission\PermissionManager; use pocketmine\player\Player; -use pocketmine\Server; use pocketmine\utils\Utils; -use function spl_object_id; /** * Called when a player chats something @@ -50,21 +47,13 @@ class PlayerChatEvent extends PlayerEvent implements Cancellable{ /** * @param CommandSender[] $recipients */ - public function __construct(Player $player, string $message, string $format = "chat.type.text", ?array $recipients = null){ + public function __construct(Player $player, string $message, array $recipients, string $format = "chat.type.text"){ $this->player = $player; $this->message = $message; $this->format = $format; - if($recipients === null){ - foreach(PermissionManager::getInstance()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_USERS) as $permissible){ - if($permissible instanceof CommandSender){ - $this->recipients[spl_object_id($permissible)] = $permissible; - } - } - }else{ - $this->recipients = $recipients; - } + $this->recipients = $recipients; } public function getMessage() : string{ diff --git a/src/player/Player.php b/src/player/Player.php index aaca80951..bbafa4302 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -97,7 +97,6 @@ use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties; use pocketmine\network\mcpe\protocol\types\entity\PlayerMetadataFlags; use pocketmine\permission\PermissibleBase; use pocketmine\permission\PermissibleDelegateTrait; -use pocketmine\permission\PermissionManager; use pocketmine\Server; use pocketmine\timings\Timings; use pocketmine\utils\TextFormat; @@ -524,9 +523,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ } public function recalculatePermissions() : void{ - $permManager = PermissionManager::getInstance(); - $permManager->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this); - $permManager->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); + $this->server->unsubscribeFromBroadcastChannel(Server::BROADCAST_CHANNEL_USERS, $this); + $this->server->unsubscribeFromBroadcastChannel(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); if($this->perm === null){ return; @@ -538,10 +536,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ if($this->spawned){ if($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)){ - $permManager->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this); + $this->server->subscribeToBroadcastChannel(Server::BROADCAST_CHANNEL_USERS, $this); } if($this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)){ - $permManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); + $this->server->subscribeToBroadcastChannel(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); } $this->networkSession->syncAvailableCommands(); @@ -781,10 +779,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ } $this->spawned = true; if($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)){ - PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this); + $this->server->subscribeToBroadcastChannel(Server::BROADCAST_CHANNEL_USERS, $this); } if($this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)){ - PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); + $this->server->subscribeToBroadcastChannel(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); } $ev = new PlayerJoinEvent($this, @@ -1363,7 +1361,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ $this->server->dispatchCommand($ev->getPlayer(), substr($ev->getMessage(), 1)); Timings::$playerCommandTimer->stopTiming(); }else{ - $ev = new PlayerChatEvent($this, $ev->getMessage()); + $ev = new PlayerChatEvent($this, $ev->getMessage(), $this->server->getBroadcastChannelSubscribers(Server::BROADCAST_CHANNEL_USERS)); $ev->call(); if(!$ev->isCancelled()){ $this->server->broadcastMessage($this->getServer()->getLanguage()->translateString($ev->getFormat(), [$ev->getPlayer()->getDisplayName(), $ev->getMessage()]), $ev->getRecipients()); @@ -1972,8 +1970,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ } //prevent the player receiving their own disconnect message - PermissionManager::getInstance()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this); - PermissionManager::getInstance()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); + $this->server->unsubscribeFromAllBroadcastChannels($this); $ev = new PlayerQuitEvent($this, $quitMessage ?? $this->getLeaveMessage(), $reason); $ev->call();