PlayerChatEvent: introduce new formatting API

this API is simultaneously more powerful and cleaner than the previous system.
The previous system relied on undocumented behaviour and was limited to non-localizable strings.

This enables custom servers to implement their own chat formats (e.g. containing localizable tags) which will be displayed in each player's own language (once per-player language has been properly implemented, anyway).
This commit is contained in:
Dylan K. Taylor 2023-01-13 17:20:08 +00:00
parent b57fcb52d4
commit b76265cd37
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
5 changed files with 125 additions and 8 deletions

View File

@ -26,7 +26,7 @@ namespace pocketmine\event\player;
use pocketmine\command\CommandSender;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\lang\KnownTranslationKeys;
use pocketmine\player\chat\ChatFormatter;
use pocketmine\player\Player;
use pocketmine\utils\Utils;
@ -43,7 +43,7 @@ class PlayerChatEvent extends PlayerEvent implements Cancellable{
Player $player,
protected string $message,
protected array $recipients,
protected string $format = KnownTranslationKeys::CHAT_TYPE_TEXT
protected ChatFormatter $formatter
){
$this->player = $player;
}
@ -63,12 +63,12 @@ class PlayerChatEvent extends PlayerEvent implements Cancellable{
$this->player = $player;
}
public function getFormat() : string{
return $this->format;
public function getFormatter() : ChatFormatter{
return $this->formatter;
}
public function setFormat(string $format) : void{
$this->format = $format;
public function setFormatter(ChatFormatter $formatter) : void{
$this->formatter = $formatter;
}
/**

View File

@ -114,6 +114,7 @@ use pocketmine\permission\DefaultPermissionNames;
use pocketmine\permission\DefaultPermissions;
use pocketmine\permission\PermissibleBase;
use pocketmine\permission\PermissibleDelegateTrait;
use pocketmine\player\chat\StandardChatFormatter;
use pocketmine\Server;
use pocketmine\timings\Timings;
use pocketmine\utils\AssumptionFailedError;
@ -1445,10 +1446,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->server->dispatchCommand($this, substr($messagePart, 1));
Timings::$playerCommand->stopTiming();
}else{
$ev = new PlayerChatEvent($this, $messagePart, $this->server->getBroadcastChannelSubscribers(Server::BROADCAST_CHANNEL_USERS));
$ev = new PlayerChatEvent($this, $messagePart, $this->server->getBroadcastChannelSubscribers(Server::BROADCAST_CHANNEL_USERS), new StandardChatFormatter());
$ev->call();
if(!$ev->isCancelled()){
$this->server->broadcastMessage($this->getServer()->getLanguage()->translateString($ev->getFormat(), [$ev->getPlayer()->getDisplayName(), $ev->getMessage()]), $ev->getRecipients());
$this->server->broadcastMessage($ev->getFormatter()->format($ev->getPlayer()->getDisplayName(), $ev->getMessage()), $ev->getRecipients());
}
}
}

View File

@ -0,0 +1,38 @@
<?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/
*
*
*/
declare(strict_types=1);
namespace pocketmine\player\chat;
use pocketmine\lang\Translatable;
/**
* Formats chat messages for broadcasting. Used in PlayerChatEvent.
*/
interface ChatFormatter{
/**
* Returns the formatted message to broadcast.
* This can return a plain string (which will be used as-is) or a Translatable (which will be translated into
* each recipient's language).
*/
public function format(string $username, string $message) : Translatable|string;
}

View File

@ -0,0 +1,41 @@
<?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/
*
*
*/
declare(strict_types=1);
namespace pocketmine\player\chat;
use function str_replace;
/**
* Legacy raw string chat formatter with the same behaviour as the old PlayerChatEvent::setFormat() API.
* The format string should contain the placeholders {%0} and {%1} for the username and message respectively.
*/
final class LegacyRawChatFormatter implements ChatFormatter{
public function __construct(
private string $format
){}
public function format(string $username, string $message) : string{
return str_replace(["{%0}", "{%1}"], [$username, $message], $this->format);
}
}

View File

@ -0,0 +1,37 @@
<?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/
*
*
*/
declare(strict_types=1);
namespace pocketmine\player\chat;
use pocketmine\lang\KnownTranslationFactory;
use pocketmine\lang\Translatable;
/**
* Standard chat formatter, formats messages in the default Minecraft way.
*/
final class StandardChatFormatter implements ChatFormatter{
public function format(string $username, string $message) : Translatable{
return KnownTranslationFactory::chat_type_text($username, $message);
}
}