Separate ID handling from GameMode

the aliases of 0,1,2,3 remain for user-interface level compatibility.
This commit is contained in:
Dylan K. Taylor 2021-06-27 20:32:35 +01:00
parent 5cdf0b169f
commit 902ea515f7
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
7 changed files with 83 additions and 31 deletions

View File

@ -34,6 +34,7 @@ use pocketmine\console\ConsoleCommandSender;
use pocketmine\console\ConsoleReaderThread; use pocketmine\console\ConsoleReaderThread;
use pocketmine\crafting\CraftingManager; use pocketmine\crafting\CraftingManager;
use pocketmine\crafting\CraftingManagerFromDataHelper; use pocketmine\crafting\CraftingManagerFromDataHelper;
use pocketmine\data\java\GameModeIdMap;
use pocketmine\entity\EntityDataHelper; use pocketmine\entity\EntityDataHelper;
use pocketmine\entity\Location; use pocketmine\entity\Location;
use pocketmine\event\HandlerListManager; use pocketmine\event\HandlerListManager;
@ -372,7 +373,7 @@ class Server{
} }
public function getGamemode() : GameMode{ public function getGamemode() : GameMode{
return GameMode::fromMagicNumber($this->configGroup->getConfigInt("gamemode", 0) & 0b11); return GameModeIdMap::getInstance()->fromId($this->configGroup->getConfigInt("gamemode", 0)) ?? GameMode::SURVIVAL();
} }
public function getForceGamemode() : bool{ public function getForceGamemode() : bool{

View File

@ -25,6 +25,7 @@ namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender; use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException; use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\data\java\GameModeIdMap;
use pocketmine\lang\TranslationContainer; use pocketmine\lang\TranslationContainer;
use pocketmine\permission\DefaultPermissionNames; use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\GameMode; use pocketmine\player\GameMode;
@ -57,7 +58,7 @@ class DefaultGamemodeCommand extends VanillaCommand{
return true; return true;
} }
$sender->getServer()->getConfigGroup()->setConfigInt("gamemode", $gameMode->getMagicNumber()); $sender->getServer()->getConfigGroup()->setConfigInt("gamemode", GameModeIdMap::getInstance()->toId($gameMode));
$sender->sendMessage(new TranslationContainer("commands.defaultgamemode.success", [$gameMode->getTranslationKey()])); $sender->sendMessage(new TranslationContainer("commands.defaultgamemode.success", [$gameMode->getTranslationKey()]));
return true; return true;
} }

View File

@ -0,0 +1,67 @@
<?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\data\java;
use pocketmine\player\GameMode;
use pocketmine\utils\SingletonTrait;
use function array_key_exists;
final class GameModeIdMap{
use SingletonTrait;
/**
* @var GameMode[]
* @phpstan-var array<int, GameMode>
*/
private array $idToEnum = [];
/**
* @var int[]
* @phpstan-var array<int, int>
*/
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());
}
private function register(int $id, GameMode $type) : void{
$this->idToEnum[$id] = $type;
$this->enumToId[$type->id()] = $id;
}
public function fromId(int $id) : ?GameMode{
return $this->idToEnum[$id] ?? null;
}
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
}
return $this->enumToId[$type->id()];
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\network\query; namespace pocketmine\network\query;
use pocketmine\player\GameMode;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\plugin\Plugin; use pocketmine\plugin\Plugin;
use pocketmine\Server; use pocketmine\Server;
@ -81,7 +82,7 @@ final class QueryInfo{
$this->plugins = $server->getPluginManager()->getPlugins(); $this->plugins = $server->getPluginManager()->getPlugins();
$this->players = $server->getOnlinePlayers(); $this->players = $server->getOnlinePlayers();
$this->gametype = ($server->getGamemode()->getMagicNumber() & 0x01) === 0 ? "SMP" : "CMP"; $this->gametype = ($server->getGamemode()->equals(GameMode::SURVIVAL()) || $server->getGamemode()->equals(GameMode::ADVENTURE())) ? "SMP" : "CMP";
$this->version = $server->getVersion(); $this->version = $server->getVersion();
$this->server_engine = $server->getName() . " " . $server->getPocketMineVersion(); $this->server_engine = $server->getName() . " " . $server->getPocketMineVersion();
$world = $server->getWorldManager()->getDefaultWorld(); $world = $server->getWorldManager()->getDefaultWorld();

View File

@ -44,21 +44,18 @@ final class GameMode{
/** @var self[] */ /** @var self[] */
protected static $aliasMap = []; protected static $aliasMap = [];
/** @var self[] */
protected static $magicNumberMap = [];
protected static function setup() : void{ protected static function setup() : void{
self::registerAll( self::registerAll(
new self("survival", 0, "Survival", "gameMode.survival", ["s", "0"]), new self("survival", "Survival", "gameMode.survival", ["s", "0"]),
new self("creative", 1, "Creative", "gameMode.creative", ["c", "1"]), new self("creative", "Creative", "gameMode.creative", ["c", "1"]),
new self("adventure", 2, "Adventure", "gameMode.adventure", ["a", "2"]), new self("adventure", "Adventure", "gameMode.adventure", ["a", "2"]),
new self("spectator", 3, "Spectator", "gameMode.spectator", ["v", "view", "3"]) new self("spectator", "Spectator", "gameMode.spectator", ["v", "view", "3"])
); );
} }
protected static function register(self $member) : void{ protected static function register(self $member) : void{
self::Enum_register($member); self::Enum_register($member);
self::$magicNumberMap[$member->getMagicNumber()] = $member;
foreach($member->getAliases() as $alias){ foreach($member->getAliases() as $alias){
self::$aliasMap[$alias] = $member; self::$aliasMap[$alias] = $member;
} }
@ -69,18 +66,6 @@ final class GameMode{
return self::$aliasMap[$str] ?? self::Enum_fromString($str); return self::$aliasMap[$str] ?? self::Enum_fromString($str);
} }
/**
* @return GameMode
* @throws \InvalidArgumentException
*/
public static function fromMagicNumber(int $n) : self{
self::checkInit();
if(!isset(self::$magicNumberMap[$n])){
throw new \InvalidArgumentException("No " . self::class . " enum member matches magic number $n");
}
return self::$magicNumberMap[$n];
}
/** @var int */ /** @var int */
private $magicNumber; private $magicNumber;
/** @var string */ /** @var string */
@ -93,18 +78,13 @@ final class GameMode{
/** /**
* @param string[] $aliases * @param string[] $aliases
*/ */
private function __construct(string $enumName, int $magicNumber, string $englishName, string $translationKey, array $aliases = []){ private function __construct(string $enumName, string $englishName, string $translationKey, array $aliases = []){
$this->Enum___construct($enumName); $this->Enum___construct($enumName);
$this->magicNumber = $magicNumber;
$this->englishName = $englishName; $this->englishName = $englishName;
$this->translationKey = $translationKey; $this->translationKey = $translationKey;
$this->aliases = $aliases; $this->aliases = $aliases;
} }
public function getMagicNumber() : int{
return $this->magicNumber;
}
public function getEnglishName() : string{ public function getEnglishName() : string{
return $this->englishName; return $this->englishName;
} }

View File

@ -29,6 +29,7 @@ use pocketmine\block\UnknownBlock;
use pocketmine\block\VanillaBlocks; use pocketmine\block\VanillaBlocks;
use pocketmine\command\CommandSender; use pocketmine\command\CommandSender;
use pocketmine\crafting\CraftingGrid; use pocketmine\crafting\CraftingGrid;
use pocketmine\data\java\GameModeIdMap;
use pocketmine\entity\animation\Animation; use pocketmine\entity\animation\Animation;
use pocketmine\entity\animation\ArmSwingAnimation; use pocketmine\entity\animation\ArmSwingAnimation;
use pocketmine\entity\animation\CriticalHitAnimation; use pocketmine\entity\animation\CriticalHitAnimation;
@ -332,7 +333,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->lastPlayed = $nbt->getLong("lastPlayed", $now); $this->lastPlayed = $nbt->getLong("lastPlayed", $now);
if(!$this->server->getForceGamemode() and ($gameModeTag = $nbt->getTag("playerGameType")) instanceof IntTag){ if(!$this->server->getForceGamemode() and ($gameModeTag = $nbt->getTag("playerGameType")) instanceof IntTag){
$this->internalSetGameMode(GameMode::fromMagicNumber($gameModeTag->getValue() & 0x03)); //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{ }else{
$this->internalSetGameMode($this->server->getGamemode()); $this->internalSetGameMode($this->server->getGamemode());
} }
@ -2069,7 +2070,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$nbt->setInt("SpawnZ", $spawn->getFloorZ()); $nbt->setInt("SpawnZ", $spawn->getFloorZ());
} }
$nbt->setInt("playerGameType", $this->gamemode->getMagicNumber()); $nbt->setInt("playerGameType", GameModeIdMap::getInstance()->toId($this->gamemode));
$nbt->setLong("firstPlayed", $this->firstPlayed); $nbt->setLong("firstPlayed", $this->firstPlayed);
$nbt->setLong("lastPlayed", (int) floor(microtime(true) * 1000)); $nbt->setLong("lastPlayed", (int) floor(microtime(true) * 1000));

View File

@ -27,6 +27,7 @@ declare(strict_types=1);
*/ */
namespace pocketmine\wizard; namespace pocketmine\wizard;
use pocketmine\data\java\GameModeIdMap;
use pocketmine\lang\Language; use pocketmine\lang\Language;
use pocketmine\lang\LanguageNotFoundException; use pocketmine\lang\LanguageNotFoundException;
use pocketmine\player\GameMode; use pocketmine\player\GameMode;
@ -158,7 +159,7 @@ LICENSE;
$this->message($this->lang->get("gamemode_info")); $this->message($this->lang->get("gamemode_info"));
do{ do{
$gamemode = (int) $this->getInput($this->lang->get("default_gamemode"), (string) GameMode::SURVIVAL()->getMagicNumber()); $gamemode = (int) $this->getInput($this->lang->get("default_gamemode"), (string) GameModeIdMap::getInstance()->toId(GameMode::SURVIVAL()));
}while($gamemode < 0 or $gamemode > 3); }while($gamemode < 0 or $gamemode > 3);
$config->set("gamemode", $gamemode); $config->set("gamemode", $gamemode);