Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions build/generate-translation-api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

declare(strict_types=1);

use pocketmine\lang\Translatable;

require dirname(__DIR__) . '/vendor/autoload.php';

const SHARED_HEADER = <<<'HEADER'
<?php

declare(strict_types=1);

namespace ColinHDev\CPlot\language;

HEADER;

const FACTORY_HEADER = SHARED_HEADER . <<<'HEADER'

use pocketmine\lang\Translatable;

/**
* This class contains factory methods for all the translations known to CPlot.
* This class is generated automatically, do NOT modify it by hand.
*
* @internal
*/
final class KnownTranslationFactory {


HEADER;

const KEY_HEADER = SHARED_HEADER . <<<'HEADER'

/**
* This class contains constants for all the translations known to CPlot.
* This class is generated automatically, do NOT modify it by hand.
*
* @internal
*/
final class KnownTranslationKeys {


HEADER;

$fileContents = file(dirname(__DIR__) . "/resources/language/en_us.ini", FILE_SKIP_EMPTY_LINES);
if ($fileContents === false) {
fwrite(STDERR, "Missing language files!\n");
exit(1);
}

generateClasses($fileContents);

/**
* @param array<string, string> $fileContents
* @return void
*/
function generateClasses(array $fileContents) : void {
$factoryClass = FACTORY_HEADER;
$keyClass = KEY_HEADER;
$translatableClassName = (new ReflectionClass(Translatable::class))->getShortName();
$parameters = [];
foreach ($fileContents as $line) {
if (str_starts_with($line, ";")) {
preg_match_all("/{%(?P<digit>\d+)}\s=\s(?P<name>[^,()]+)/", $line, $matches);
foreach ($matches["name"] as $index => $name) {
$parameters[$matches["digit"][$index]] = parameterify($name);
}
continue;
}
preg_match("/^(.+?)\s*=\s*(.+)$/", $line, $matches);
if (!isset($matches[1])) {
continue;
}
$key = $matches[1];
$constantName = constantify($key);
ksort($parameters, SORT_NUMERIC);
$factoryClass .= " public static function " .
functionify($key) .
"(" . implode(", ", array_map(fn(string $paramName) => "$translatableClassName|string \$$paramName", $parameters)) . ") : $translatableClassName {\n" .
" return new $translatableClassName(KnownTranslationKeys::$constantName, [";
foreach($parameters as $parameterKey => $parameterName){
$factoryClass .= "\n $parameterKey => \$$parameterName,";
}
if(count($parameters) > 0){
$factoryClass .= "\n ";
$parameters = [];
}
$factoryClass .= "]);\n }\n\n";

$keyClass .= " public const " . $constantName . " = \"" . $key . "\";\n";
}
$factoryClass .= "}";
$keyClass .= "}";
file_put_contents(dirname(__DIR__) . "/src/ColinHDev/CPlot/language/KnownTranslationFactory.php", $factoryClass);
file_put_contents(dirname(__DIR__) . "/src/ColinHDev/CPlot/language/KnownTranslationKeys.php", $keyClass);
}

function constantify(string $name) : string {
return strtoupper(str_replace([".", "-"], "_", $name));
}

function functionify(string $name) : string {
return str_replace([".", "-"], "_", $name);
}

function parameterify(string $name) : string {
return str_replace([" ", ".", "-"], "_", trim($name));
}
6 changes: 3 additions & 3 deletions src/ColinHDev/CPlot/commands/AsyncSubcommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
declare(strict_types=1);

namespace ColinHDev\CPlot\commands;

use Generator;
use pocketmine\command\CommandSender;
use SOFe\AwaitGenerator\Await;

abstract class AsyncSubcommand extends Subcommand {

final public function execute(CommandSender $sender, array $args) : void {
final public function execute(CommandExecutor $sender, array $args) : void {
Await::g2c(
$this->executeAsync($sender, $args)
);
Expand All @@ -21,5 +21,5 @@ final public function execute(CommandSender $sender, array $args) : void {
* @param string[] $args
* @phpstan-return Generator<mixed, mixed, mixed, mixed>
*/
abstract public function executeAsync(CommandSender $sender, array $args) : Generator;
abstract public function executeAsync(CommandExecutor $sender, array $args) : Generator;
}
46 changes: 46 additions & 0 deletions src/ColinHDev/CPlot/commands/CommandExecutor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace ColinHDev\CPlot\commands;

use ColinHDev\CPlot\language\LanguageManager;
use pocketmine\command\CommandSender;
use pocketmine\lang\Language;
use pocketmine\lang\Translatable;

class CommandExecutor {

protected CommandSender $sender;
protected Language $language;

public function __construct(CommandSender $sender) {
$this->sender = $sender;
$this->language = LanguageManager::getInstance()->getLanguageForCommandSender($sender);
}

public function getSender() : CommandSender {
return $this->sender;
}

public function getLanguage() : Language {
return $this->language;
}

public function sendMessage(Translatable|string ...$messages) : void {
$this->sender->sendMessage($this->translate(...$messages));
}

public function translate(Translatable|string ...$messages) : string {
$result = "";
foreach ($messages as $message) {
if ($message instanceof Translatable) {
$result .= $this->language->translate($message);
} else {

$result .= $message;
}
}
return $result;
}
}
28 changes: 28 additions & 0 deletions src/ColinHDev/CPlot/commands/CommandExecutorManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace ColinHDev\CPlot\commands;

use ColinHDev\CPlot\player\PlayerData;
use pocketmine\player\Player;
use pocketmine\utils\SingletonTrait;
use WeakMap;

final class CommandExecutorManager {
use SingletonTrait;

private WeakMap $playerSessions;

public function __construct() {
$this->playerSessions = new WeakMap();
}

public function registerPlayerSession(Player $player, PlayerData $playerData) : void {
$this->playerSessions[$player] = new PlayerSession($player, $playerData);
}

public function getPlayerSession(Player $player) : ?PlayerSession {
return $this->playerSessions[$player] ?? null;
}
}
37 changes: 37 additions & 0 deletions src/ColinHDev/CPlot/commands/PlayerSession.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace ColinHDev\CPlot\commands;

use ColinHDev\CPlot\player\PlayerData;
use pocketmine\lang\Translatable;
use pocketmine\player\Player;
use function assert;

class PlayerSession extends CommandExecutor {

protected PlayerData $playerData;

public function __construct(Player $player, PlayerData $playerData) {
parent::__construct($player);
$this->playerData = $playerData;
}

public function getSender() : Player {
assert($this->sender instanceof Player);
return $this->sender;
}

public function getPlayer() : Player {
return $this->getSender();
}

public function getPlayerData() : PlayerData {
return $this->playerData;
}

public function sendTip(Translatable|string ...$messages) : void {
$this->getPlayer()->sendTip($this->translate(...$messages));
}
}
2 changes: 1 addition & 1 deletion src/ColinHDev/CPlot/commands/PlotCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
use ColinHDev\CPlot\commands\subcommands\WallSubcommand;
use ColinHDev\CPlot\commands\subcommands\WarpSubcommand;
use ColinHDev\CPlot\CPlot;
use ColinHDev\CPlot\provider\LanguageManager;
use ColinHDev\CPlot\language\LanguageManager;
use ColinHDev\CPlot\utils\ParseUtils;
use InvalidArgumentException;
use pocketmine\command\Command;
Expand Down
29 changes: 6 additions & 23 deletions src/ColinHDev/CPlot/commands/Subcommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

namespace ColinHDev\CPlot\commands;

use ColinHDev\CPlot\provider\LanguageManager;
use ColinHDev\CPlot\language\KnownTranslationFactory;
use ColinHDev\CPlot\language\LanguageManager;
use ColinHDev\CPlot\provider\LanguageProvider;
use ColinHDev\CPlot\utils\APIHolder;
use ColinHDev\CPlot\utils\ParseUtils;
use pocketmine\command\CommandSender;

/**
* @phpstan-import-type MessageKey from LanguageProvider
Expand Down Expand Up @@ -46,10 +46,11 @@ public function getPermission() : string {
return $this->permission;
}

public function testPermission(CommandSender $sender) : bool {
if ($sender->hasPermission($this->permission)) {
public function testPermission(CommandExecutor $sender) : bool {
if ($sender->getSender()->hasPermission($this->permission)) {
return true;
}
$sender->sendMessage(KnownTranslationFactory::prefix());
self::sendMessage($sender, ["prefix", $this->key . ".permissionMessage"]);
return false;
}
Expand All @@ -58,23 +59,5 @@ public function testPermission(CommandSender $sender) : bool {
* This method contains the code you want to be executed when the command is run.
* @param string[] $args
*/
abstract public function execute(CommandSender $sender, array $args) : void;

/**
* Utility method to send a message to a command sender, while also removing some boilerplate code within the
* subcommand classes.
* @phpstan-param array<int|MessageKey, MessageKey|MessageParam|array<MessageParam>>|MessageKey $keys
*/
final protected static function sendMessage(CommandSender $sender, array|string $keys) : void {
LanguageManager::getInstance()->getProvider()->sendMessage($sender, $keys);
}

/**
* Utility method to translate a message for a command sender, while also removing some boilerplate code within the
* subcommand classes.
* @phpstan-param array<int|MessageKey, MessageKey|MessageParam|array<MessageParam>>|MessageKey $keys
*/
final protected static function translateForCommandSender(CommandSender $sender, array|string $keys) : string {
return LanguageManager::getInstance()->getProvider()->translateForCommandSender($sender, $keys);
}
abstract public function execute(CommandExecutor $sender, array $args) : void;
}
Loading