diff --git a/src/Server.php b/src/Server.php index 2f1e9a53b..59a6ec645 100644 --- a/src/Server.php +++ b/src/Server.php @@ -390,7 +390,7 @@ class Server{ } public function getGamemode() : GameMode{ - return GameMode::fromString($this->configGroup->getConfigString(ServerProperties::GAME_MODE, GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL(); + return GameMode::fromString($this->configGroup->getConfigString(ServerProperties::GAME_MODE)) ?? GameMode::SURVIVAL; } public function getForceGamemode() : bool{ @@ -817,7 +817,7 @@ class Server{ ServerProperties::ENABLE_IPV6 => true, ServerProperties::WHITELIST => false, ServerProperties::MAX_PLAYERS => self::DEFAULT_MAX_PLAYERS, - ServerProperties::GAME_MODE => GameMode::SURVIVAL()->name(), + ServerProperties::GAME_MODE => GameMode::SURVIVAL->name, //TODO: this probably shouldn't use the enum name directly ServerProperties::FORCE_GAME_MODE => false, ServerProperties::HARDCORE => false, ServerProperties::PVP => true, @@ -1019,7 +1019,7 @@ class Server{ $this->forceShutdownExit(); return; } - if(!$this->enablePlugins(PluginEnableOrder::STARTUP())){ + if(!$this->enablePlugins(PluginEnableOrder::STARTUP)){ $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someEnableErrors())); $this->forceShutdownExit(); return; @@ -1030,7 +1030,7 @@ class Server{ return; } - if(!$this->enablePlugins(PluginEnableOrder::POSTWORLD())){ + if(!$this->enablePlugins(PluginEnableOrder::POSTWORLD)){ $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someEnableErrors())); $this->forceShutdownExit(); return; @@ -1385,14 +1385,14 @@ class Server{ public function enablePlugins(PluginEnableOrder $type) : bool{ $allSuccess = true; foreach($this->pluginManager->getPlugins() as $plugin){ - if(!$plugin->isEnabled() && $plugin->getDescription()->getOrder()->equals($type)){ + if(!$plugin->isEnabled() && $plugin->getDescription()->getOrder() === $type){ if(!$this->pluginManager->enablePlugin($plugin)){ $allSuccess = false; } } } - if($type->equals(PluginEnableOrder::POSTWORLD())){ + if($type === PluginEnableOrder::POSTWORLD){ $this->commandMap->registerServerAliases(); } diff --git a/src/block/DragonEgg.php b/src/block/DragonEgg.php index d76a91058..10fec6394 100644 --- a/src/block/DragonEgg.php +++ b/src/block/DragonEgg.php @@ -50,7 +50,7 @@ class DragonEgg extends Transparent implements Fallable{ } public function onAttack(Item $item, int $face, ?Player $player = null) : bool{ - if($player !== null && !$player->getGamemode()->equals(GameMode::CREATIVE())){ + if($player !== null && $player->getGamemode() !== GameMode::CREATIVE){ $this->teleport(); return true; } diff --git a/src/command/defaults/DefaultGamemodeCommand.php b/src/command/defaults/DefaultGamemodeCommand.php index bac98e678..d3030eb27 100644 --- a/src/command/defaults/DefaultGamemodeCommand.php +++ b/src/command/defaults/DefaultGamemodeCommand.php @@ -53,7 +53,8 @@ class DefaultGamemodeCommand extends VanillaCommand{ return true; } - $sender->getServer()->getConfigGroup()->setConfigString(ServerProperties::GAME_MODE, $gameMode->name()); + //TODO: this probably shouldn't use the enum name directly + $sender->getServer()->getConfigGroup()->setConfigString(ServerProperties::GAME_MODE, $gameMode->name); $sender->sendMessage(KnownTranslationFactory::commands_defaultgamemode_success($gameMode->getTranslatableName())); return true; } diff --git a/src/command/defaults/GamemodeCommand.php b/src/command/defaults/GamemodeCommand.php index 86ca8e9df..666626a69 100644 --- a/src/command/defaults/GamemodeCommand.php +++ b/src/command/defaults/GamemodeCommand.php @@ -61,13 +61,13 @@ class GamemodeCommand extends VanillaCommand{ return true; } - if($target->getGamemode()->equals($gameMode)){ + if($target->getGamemode() === $gameMode){ $sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_failure($target->getName())); return true; } $target->setGamemode($gameMode); - if(!$gameMode->equals($target->getGamemode())){ + if($gameMode !== $target->getGamemode()){ $sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_failure($target->getName())); }else{ if($target === $sender){ diff --git a/src/crash/CrashDump.php b/src/crash/CrashDump.php index b0e58fd16..1a558b499 100644 --- a/src/crash/CrashDump.php +++ b/src/crash/CrashDump.php @@ -143,7 +143,7 @@ class CrashDump{ depends: $d->getDepend(), softDepends: $d->getSoftDepend(), main: $d->getMain(), - load: mb_strtoupper($d->getOrder()->name()), + load: mb_strtoupper($d->getOrder()->name), website: $d->getWebsite() ); } diff --git a/src/data/java/GameModeIdMap.php b/src/data/java/GameModeIdMap.php index 348749b51..41258dd66 100644 --- a/src/data/java/GameModeIdMap.php +++ b/src/data/java/GameModeIdMap.php @@ -26,6 +26,7 @@ namespace pocketmine\data\java; use pocketmine\player\GameMode; use pocketmine\utils\SingletonTrait; use function array_key_exists; +use function spl_object_id; final class GameModeIdMap{ use SingletonTrait; @@ -43,15 +44,15 @@ final class GameModeIdMap{ private array $enumToId = []; public function __construct(){ - $this->register(0, GameMode::SURVIVAL()); - $this->register(1, GameMode::CREATIVE()); - $this->register(2, GameMode::ADVENTURE()); - $this->register(3, GameMode::SPECTATOR()); + $this->register(0, GameMode::SURVIVAL); + $this->register(1, GameMode::CREATIVE); + $this->register(2, GameMode::ADVENTURE); + $this->register(3, GameMode::SPECTATOR); } private function register(int $id, GameMode $type) : void{ $this->idToEnum[$id] = $type; - $this->enumToId[$type->id()] = $id; + $this->enumToId[spl_object_id($type)] = $id; } public function fromId(int $id) : ?GameMode{ @@ -59,9 +60,10 @@ final class GameModeIdMap{ } public function toId(GameMode $type) : int{ - if(!array_key_exists($type->id(), $this->enumToId)){ - throw new \InvalidArgumentException("Game mode does not have a mapped ID"); //this should never happen + $k = spl_object_id($type); + if(!array_key_exists($k, $this->enumToId)){ + throw new \InvalidArgumentException("Game mode $type->name does not have a mapped ID"); //this should never happen } - return $this->enumToId[$type->id()]; + return $this->enumToId[$k]; } } diff --git a/src/network/mcpe/convert/TypeConverter.php b/src/network/mcpe/convert/TypeConverter.php index 94f476e9c..53ce6e98a 100644 --- a/src/network/mcpe/convert/TypeConverter.php +++ b/src/network/mcpe/convert/TypeConverter.php @@ -108,33 +108,23 @@ class TypeConverter{ * @internal */ public function coreGameModeToProtocol(GameMode $gamemode) : int{ - switch($gamemode->id()){ - case GameMode::SURVIVAL()->id(): - return ProtocolGameMode::SURVIVAL; - case GameMode::CREATIVE()->id(): - case GameMode::SPECTATOR()->id(): - return ProtocolGameMode::CREATIVE; - case GameMode::ADVENTURE()->id(): - return ProtocolGameMode::ADVENTURE; - default: - throw new AssumptionFailedError("Unknown game mode"); - } + return match($gamemode){ + GameMode::SURVIVAL => ProtocolGameMode::SURVIVAL, + //TODO: native spectator support + GameMode::CREATIVE, GameMode::SPECTATOR => ProtocolGameMode::CREATIVE, + GameMode::ADVENTURE => ProtocolGameMode::ADVENTURE, + }; } public function protocolGameModeToCore(int $gameMode) : ?GameMode{ - switch($gameMode){ - case ProtocolGameMode::SURVIVAL: - return GameMode::SURVIVAL(); - case ProtocolGameMode::CREATIVE: - return GameMode::CREATIVE(); - case ProtocolGameMode::ADVENTURE: - return GameMode::ADVENTURE(); - case ProtocolGameMode::CREATIVE_VIEWER: - case ProtocolGameMode::SURVIVAL_VIEWER: - return GameMode::SPECTATOR(); - default: - return null; - } + return match($gameMode){ + ProtocolGameMode::SURVIVAL => GameMode::SURVIVAL, + ProtocolGameMode::CREATIVE => GameMode::CREATIVE, + ProtocolGameMode::ADVENTURE => GameMode::ADVENTURE, + ProtocolGameMode::SURVIVAL_VIEWER, ProtocolGameMode::CREATIVE_VIEWER => GameMode::SPECTATOR, + //TODO: native spectator support + default => null, + }; } public function coreRecipeIngredientToNet(?RecipeIngredient $ingredient) : ProtocolRecipeIngredient{ diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 30841d806..84ea10d36 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -783,7 +783,7 @@ class InGamePacketHandler extends PacketHandler{ public function handleSetPlayerGameType(SetPlayerGameTypePacket $packet) : bool{ $gameMode = $this->session->getTypeConverter()->protocolGameModeToCore($packet->gamemode); - if($gameMode === null || !$gameMode->equals($this->player->getGamemode())){ + if($gameMode !== $this->player->getGamemode()){ //Set this back to default. TODO: handle this properly $this->session->syncGameMode($this->player->getGamemode(), true); } diff --git a/src/network/mcpe/raklib/RakLibInterface.php b/src/network/mcpe/raklib/RakLibInterface.php index 759a992e8..d189cf0fd 100644 --- a/src/network/mcpe/raklib/RakLibInterface.php +++ b/src/network/mcpe/raklib/RakLibInterface.php @@ -271,8 +271,8 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{ $this->rakServerId, $this->server->getName(), match($this->server->getGamemode()){ - GameMode::SURVIVAL() => "Survival", - GameMode::ADVENTURE() => "Adventure", + GameMode::SURVIVAL => "Survival", + GameMode::ADVENTURE => "Adventure", default => "Creative" } ]) . ";" diff --git a/src/network/query/QueryInfo.php b/src/network/query/QueryInfo.php index cdb1c66db..0bf5b4f65 100644 --- a/src/network/query/QueryInfo.php +++ b/src/network/query/QueryInfo.php @@ -71,7 +71,7 @@ final class QueryInfo{ $this->plugins = $server->getPluginManager()->getPlugins(); $this->players = array_map(fn(Player $p) => $p->getName(), $server->getOnlinePlayers()); - $this->gametype = ($server->getGamemode()->equals(GameMode::SURVIVAL()) || $server->getGamemode()->equals(GameMode::ADVENTURE())) ? "SMP" : "CMP"; + $this->gametype = ($server->getGamemode() === GameMode::SURVIVAL || $server->getGamemode() === GameMode::ADVENTURE) ? "SMP" : "CMP"; $this->version = $server->getVersion(); $this->server_engine = $server->getName() . " " . $server->getPocketMineVersion(); $world = $server->getWorldManager()->getDefaultWorld(); diff --git a/src/player/GameMode.php b/src/player/GameMode.php index 0fc60ece4..519cbbe8a 100644 --- a/src/player/GameMode.php +++ b/src/player/GameMode.php @@ -25,73 +25,76 @@ namespace pocketmine\player; use pocketmine\lang\KnownTranslationFactory; use pocketmine\lang\Translatable; -use pocketmine\utils\EnumTrait; +use pocketmine\utils\LegacyEnumShimTrait; use function mb_strtolower; +use function spl_object_id; /** - * This doc-block is generated automatically, do not modify it manually. - * This must be regenerated whenever registry members are added, removed or changed. - * @see build/generate-registry-annotations.php - * @generate-registry-docblock + * TODO: These tags need to be removed once we get rid of LegacyEnumShimTrait (PM6) + * These are retained for backwards compatibility only. * * @method static GameMode ADVENTURE() * @method static GameMode CREATIVE() * @method static GameMode SPECTATOR() * @method static GameMode SURVIVAL() + * + * @phpstan-type TMetadata array{0: string, 1: Translatable, 2: list} */ -final class GameMode{ - use EnumTrait { - __construct as Enum___construct; - register as Enum_register; - } +enum GameMode{ + use LegacyEnumShimTrait; - /** @var self[] */ - protected static array $aliasMap = []; - - protected static function setup() : void{ - self::registerAll( - new self("survival", "Survival", KnownTranslationFactory::gameMode_survival(), ["survival", "s", "0"]), - new self("creative", "Creative", KnownTranslationFactory::gameMode_creative(), ["creative", "c", "1"]), - new self("adventure", "Adventure", KnownTranslationFactory::gameMode_adventure(), ["adventure", "a", "2"]), - new self("spectator", "Spectator", KnownTranslationFactory::gameMode_spectator(), ["spectator", "v", "view", "3"]) - ); - } - - protected static function register(self $member) : void{ - self::Enum_register($member); - foreach($member->getAliases() as $alias){ - self::$aliasMap[mb_strtolower($alias)] = $member; - } - } + case SURVIVAL; + case CREATIVE; + case ADVENTURE; + case SPECTATOR; public static function fromString(string $str) : ?self{ - self::checkInit(); - return self::$aliasMap[mb_strtolower($str)] ?? null; + /** + * @var self[]|null $aliasMap + * @phpstan-var array|null $aliasMap + */ + static $aliasMap = null; + + if($aliasMap === null){ + $aliasMap = []; + foreach(self::cases() as $case){ + foreach($case->getAliases() as $alias){ + $aliasMap[$alias] = $case; + } + } + } + + return $aliasMap[mb_strtolower($str)] ?? null; } /** - * @param string[] $aliases + * @phpstan-return TMetadata */ - private function __construct( - string $enumName, - private string $englishName, - private Translatable $translatableName, - private array $aliases = [] - ){ - $this->Enum___construct($enumName); + private function getMetadata() : array{ + /** @phpstan-var array $cache */ + static $cache = []; + + return $cache[spl_object_id($this)] ??= match($this){ + self::SURVIVAL => ["Survival", KnownTranslationFactory::gameMode_survival(), ["survival", "s", "0"]], + self::CREATIVE => ["Creative", KnownTranslationFactory::gameMode_creative(), ["creative", "c", "1"]], + self::ADVENTURE => ["Adventure", KnownTranslationFactory::gameMode_adventure(), ["adventure", "a", "2"]], + self::SPECTATOR => ["Spectator", KnownTranslationFactory::gameMode_spectator(), ["spectator", "v", "view", "3"]] + }; } public function getEnglishName() : string{ - return $this->englishName; + return $this->getMetadata()[0]; } - public function getTranslatableName() : Translatable{ return $this->translatableName; } + public function getTranslatableName() : Translatable{ + return $this->getMetadata()[1]; + } /** * @return string[] */ public function getAliases() : array{ - return $this->aliases; + return $this->getMetadata()[2]; } //TODO: ability sets per gamemode diff --git a/src/player/Player.php b/src/player/Player.php index 06d1c3103..0afa0bffe 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -372,7 +372,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ $this->lastPlayed = $nbt->getLong(self::TAG_LAST_PLAYED, $now); if(!$this->server->getForceGamemode() && ($gameModeTag = $nbt->getTag(self::TAG_GAME_MODE)) instanceof IntTag){ - $this->internalSetGameMode(GameModeIdMap::getInstance()->fromId($gameModeTag->getValue()) ?? GameMode::SURVIVAL()); //TODO: bad hack here to avoid crashes on corrupted data + $this->internalSetGameMode(GameModeIdMap::getInstance()->fromId($gameModeTag->getValue()) ?? GameMode::SURVIVAL); //TODO: bad hack here to avoid crashes on corrupted data }else{ $this->internalSetGameMode($this->server->getGamemode()); } @@ -1113,7 +1113,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ protected function internalSetGameMode(GameMode $gameMode) : void{ $this->gamemode = $gameMode; - $this->allowFlight = $this->gamemode->equals(GameMode::CREATIVE()); + $this->allowFlight = $this->gamemode === GameMode::CREATIVE; $this->hungerManager->setEnabled($this->isSurvival()); if($this->isSpectator()){ @@ -1139,7 +1139,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ * Sets the provided gamemode. */ public function setGamemode(GameMode $gm) : bool{ - if($this->gamemode->equals($gm)){ + if($this->gamemode === $gm){ return false; } @@ -1168,7 +1168,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ * @param bool $literal whether a literal check should be performed */ public function isSurvival(bool $literal = false) : bool{ - return $this->gamemode->equals(GameMode::SURVIVAL()) || (!$literal && $this->gamemode->equals(GameMode::ADVENTURE())); + return $this->gamemode === GameMode::SURVIVAL || (!$literal && $this->gamemode === GameMode::ADVENTURE); } /** @@ -1178,7 +1178,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ * @param bool $literal whether a literal check should be performed */ public function isCreative(bool $literal = false) : bool{ - return $this->gamemode->equals(GameMode::CREATIVE()) || (!$literal && $this->gamemode->equals(GameMode::SPECTATOR())); + return $this->gamemode === GameMode::CREATIVE || (!$literal && $this->gamemode === GameMode::SPECTATOR); } /** @@ -1188,18 +1188,18 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ * @param bool $literal whether a literal check should be performed */ public function isAdventure(bool $literal = false) : bool{ - return $this->gamemode->equals(GameMode::ADVENTURE()) || (!$literal && $this->gamemode->equals(GameMode::SPECTATOR())); + return $this->gamemode === GameMode::ADVENTURE || (!$literal && $this->gamemode === GameMode::SPECTATOR); } public function isSpectator() : bool{ - return $this->gamemode->equals(GameMode::SPECTATOR()); + return $this->gamemode === GameMode::SPECTATOR; } /** * TODO: make this a dynamic ability instead of being hardcoded */ public function hasFiniteResources() : bool{ - return !$this->gamemode->equals(GameMode::CREATIVE()); + return $this->gamemode !== GameMode::CREATIVE; } public function getDrops() : array{ diff --git a/src/plugin/PluginDescription.php b/src/plugin/PluginDescription.php index 9fc562af9..72f0add7f 100644 --- a/src/plugin/PluginDescription.php +++ b/src/plugin/PluginDescription.php @@ -203,7 +203,7 @@ class PluginDescription{ } $this->order = $order; }else{ - $this->order = PluginEnableOrder::POSTWORLD(); + $this->order = PluginEnableOrder::POSTWORLD; } $this->authors = []; diff --git a/src/plugin/PluginEnableOrder.php b/src/plugin/PluginEnableOrder.php index 5e6255a16..c942ea33f 100644 --- a/src/plugin/PluginEnableOrder.php +++ b/src/plugin/PluginEnableOrder.php @@ -23,63 +23,48 @@ declare(strict_types=1); namespace pocketmine\plugin; -use pocketmine\utils\EnumTrait; +use pocketmine\utils\LegacyEnumShimTrait; use function mb_strtolower; /** - * This doc-block is generated automatically, do not modify it manually. - * This must be regenerated whenever registry members are added, removed or changed. - * @see build/generate-registry-annotations.php - * @generate-registry-docblock + * TODO: These tags need to be removed once we get rid of LegacyEnumShimTrait (PM6) + * These are retained for backwards compatibility only. * * @method static PluginEnableOrder POSTWORLD() * @method static PluginEnableOrder STARTUP() */ -final class PluginEnableOrder{ - use EnumTrait { - __construct as Enum___construct; - register as Enum_register; - } +enum PluginEnableOrder{ + use LegacyEnumShimTrait; - protected static function setup() : void{ - self::registerAll( - new self("startup", ["startup"]), - new self("postworld", ["postworld"]) - ); - } - - /** - * @var self[] - * @phpstan-var array - */ - private static array $aliasMap = []; - - protected static function register(self $member) : void{ - self::Enum_register($member); - foreach($member->getAliases() as $alias){ - self::$aliasMap[mb_strtolower($alias)] = $member; - } - } + case STARTUP; + case POSTWORLD; public static function fromString(string $name) : ?self{ - self::checkInit(); - return self::$aliasMap[mb_strtolower($name)] ?? null; - } + /** + * @var self[]|null $aliasMap + * @phpstan-var array|null $aliasMap + */ + static $aliasMap = null; - /** - * @param string[] $aliases - * @phpstan-param list $aliases - */ - private function __construct( - string $enumName, - private array $aliases - ){ - $this->Enum___construct($enumName); + if($aliasMap === null){ + $aliasMap = []; + foreach(self::cases() as $case){ + foreach($case->getAliases() as $alias){ + $aliasMap[$alias] = $case; + } + } + } + return $aliasMap[mb_strtolower($name)] ?? null; } /** * @return string[] * @phpstan-return list */ - public function getAliases() : array{ return $this->aliases; } + public function getAliases() : array{ + return match($this){ + self::STARTUP => ["startup"], + self::POSTWORLD => ["postworld"] + }; + } } diff --git a/src/wizard/SetupWizard.php b/src/wizard/SetupWizard.php index c9170bd8d..8c1906080 100644 --- a/src/wizard/SetupWizard.php +++ b/src/wizard/SetupWizard.php @@ -165,9 +165,11 @@ LICENSE; $this->message($this->lang->translate(KnownTranslationFactory::gamemode_info())); do{ - $gamemode = GameModeIdMap::getInstance()->fromId((int) $this->getInput($this->lang->translate(KnownTranslationFactory::default_gamemode()), (string) GameModeIdMap::getInstance()->toId(GameMode::SURVIVAL()))); + //TODO: drop the usage of internal Mojang IDs for this - we really just need a set of options to choose from + $gamemode = GameModeIdMap::getInstance()->fromId((int) $this->getInput($this->lang->translate(KnownTranslationFactory::default_gamemode()), (string) GameModeIdMap::getInstance()->toId(GameMode::SURVIVAL))); }while($gamemode === null); - $config->set("gamemode", $gamemode->name()); + //TODO: this probably shouldn't use the enum name directly + $config->set("gamemode", $gamemode->name); $config->set("max-players", (int) $this->getInput($this->lang->translate(KnownTranslationFactory::max_players()), (string) self::DEFAULT_PLAYERS));