GameMode is now an enum

This commit is contained in:
Dylan K. Taylor 2019-03-31 16:19:36 +01:00
parent 0017c0087a
commit 42a263a9df
9 changed files with 128 additions and 104 deletions

View File

@ -23,88 +23,109 @@ declare(strict_types=1);
namespace pocketmine;
final class GameMode{
public const SURVIVAL = 0;
public const CREATIVE = 1;
public const ADVENTURE = 2;
public const SPECTATOR = 3;
public const VIEW = GameMode::SPECTATOR;
use pocketmine\utils\EnumTrait;
private function __construct(){
//NOOP
/**
* This doc-block is generated automatically, do not modify it manually.
* This must be regenerated whenever enum members are added, removed or changed.
* @see EnumTrait::_generateMethodAnnotations()
*
* @method static self SURVIVAL()
* @method static self CREATIVE()
* @method static self ADVENTURE()
* @method static self SPECTATOR()
*/
final class GameMode{
use EnumTrait {
__construct as Enum___construct;
register as Enum_register;
fromString as Enum_fromString;
}
/** @var self[] */
protected static $aliasMap = [];
/** @var self[] */
protected static $magicNumberMap = [];
protected static function setup() : array{
return [
new self("survival", 0, "Survival", "gameMode.survival", ["s", "0"]),
new self("creative", 1, "Creative", "gameMode.creative", ["c", "1"]),
new self("adventure", 2, "Adventure", "gameMode.adventure", ["a", "2"]),
new self("spectator", 3, "Spectator", "gameMode.spectator", ["v", "view", "3"])
];
}
protected static function register(self $member) : void{
self::Enum_register($member);
self::$magicNumberMap[$member->getMagicNumber()] = $member;
foreach($member->getAliases() as $alias){
self::$aliasMap[$alias] = $member;
}
}
public static function fromString(string $str) : self{
self::checkInit();
return self::$aliasMap[$str] ?? self::Enum_fromString($str);
}
/**
* Parses a string and returns a gamemode integer, -1 if not found
*
* @param string $str
*
* @return int
* @param int $n
*
* @return GameMode
* @throws \InvalidArgumentException
*/
public static function fromString(string $str) : int{
switch(strtolower(trim($str))){
case (string) self::SURVIVAL:
case "survival":
case "s":
return self::SURVIVAL;
case (string) self::CREATIVE:
case "creative":
case "c":
return self::CREATIVE;
case (string) self::ADVENTURE:
case "adventure":
case "a":
return self::ADVENTURE;
case (string) self::SPECTATOR:
case "spectator":
case "view":
case "v":
return self::SPECTATOR;
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];
}
throw new \InvalidArgumentException("Unknown gamemode string \"$str\"");
/** @var int */
private $magicNumber;
/** @var string */
private $englishName;
/** @var string */
private $translationKey;
/** @var string[] */
private $aliases;
private function __construct(string $enumName, int $magicNumber, string $englishName, string $translationKey, array $aliases = []){
$this->Enum___construct($enumName);
$this->magicNumber = $magicNumber;
$this->englishName = $englishName;
$this->translationKey = $translationKey;
$this->aliases = $aliases;
}
/**
* @return int
*/
public function getMagicNumber() : int{
return $this->magicNumber;
}
/**
* Returns the gamemode text name
*
* @param int $mode
*
* @return string
*/
public static function toTranslation(int $mode) : string{
switch($mode){
case self::SURVIVAL:
return "%gameMode.survival";
case self::CREATIVE:
return "%gameMode.creative";
case self::ADVENTURE:
return "%gameMode.adventure";
case self::SPECTATOR:
return "%gameMode.spectator";
public function getEnglishName() : string{
return $this->englishName;
}
return "UNKNOWN";
/**
* @return string
*/
public function getTranslationKey() : string{
return "%" . $this->translationKey;
}
public static function toString(int $mode) : string{
switch($mode){
case self::SURVIVAL:
return "Survival";
case self::CREATIVE:
return "Creative";
case self::ADVENTURE:
return "Adventure";
case self::SPECTATOR:
return "Spectator";
default:
throw new \InvalidArgumentException("Invalid gamemode $mode");
}
/**
* @return string[]
*/
public function getAliases() : array{
return $this->aliases;
}
//TODO: ability sets per gamemode

View File

@ -94,6 +94,7 @@ use pocketmine\metadata\MetadataValue;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\CompressBatchPromise;
use pocketmine\network\mcpe\NetworkSession;
@ -224,7 +225,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
protected $firstPlayed;
/** @var int */
protected $lastPlayed;
/** @var int */
/** @var GameMode */
protected $gamemode;
/** @var bool[] chunkHash => bool (true = sent, false = needs sending) */
@ -387,7 +388,11 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
$this->firstPlayed = $nbt->getLong("firstPlayed", $now = (int) (microtime(true) * 1000));
$this->lastPlayed = $nbt->getLong("lastPlayed", $now);
$this->gamemode = $this->server->getForceGamemode() ? $this->server->getGamemode() : $nbt->getInt("playerGameType", $this->server->getGamemode()) & 0x03;
if($this->server->getForceGamemode() or !$nbt->hasTag("playerGameType", IntTag::class)){
$this->gamemode = $this->server->getGamemode();
}else{
$this->gamemode = GameMode::fromMagicNumber($nbt->getInt("playerGameType") & 0x03); //TODO: bad hack here to avoid crashes on corrupted data
}
$this->allowFlight = $this->isCreative();
$this->keepMovement = $this->isSpectator() || $this->allowMovementCheats();
@ -1360,9 +1365,9 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
}
/**
* @return int
* @return GameMode
*/
public function getGamemode() : int{
public function getGamemode() : GameMode{
return $this->gamemode;
}
@ -1374,29 +1379,28 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
*
* TODO: remove this when Spectator Mode gets added properly to MCPE
*
* @param int $gamemode
* @param GameMode $gamemode
*
* @return int
*/
public static function getClientFriendlyGamemode(int $gamemode) : int{
$gamemode &= 0x03;
if($gamemode === GameMode::SPECTATOR){
return GameMode::CREATIVE;
public static function getClientFriendlyGamemode(GameMode $gamemode) : int{
if($gamemode === GameMode::SPECTATOR()){
return GameMode::CREATIVE()->getMagicNumber();
}
return $gamemode;
return $gamemode->getMagicNumber();
}
/**
* Sets the gamemode, and if needed, kicks the Player.
*
* @param int $gm
* @param GameMode $gm
* @param bool $client if the client made this change in their GUI
*
* @return bool
*/
public function setGamemode(int $gm, bool $client = false) : bool{
if($gm < 0 or $gm > 3 or $this->gamemode === $gm){
public function setGamemode(GameMode $gm, bool $client = false) : bool{
if($this->gamemode === $gm){
return false;
}
@ -1427,7 +1431,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
if(!$client){ //Gamemode changed by server, do not send for client changes
$this->sendGamemode();
}else{
Command::broadcastCommandMessage($this, new TranslationContainer("commands.gamemode.success.self", [GameMode::toTranslation($gm)]));
Command::broadcastCommandMessage($this, new TranslationContainer("commands.gamemode.success.self", [$gm->getTranslationKey()]));
}
$this->sendSettings();
@ -1475,7 +1479,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
* @return bool
*/
public function isSurvival(bool $literal = false) : bool{
return $this->gamemode === GameMode::SURVIVAL or (!$literal and $this->gamemode === GameMode::ADVENTURE);
return $this->gamemode === GameMode::SURVIVAL() or (!$literal and $this->gamemode === GameMode::ADVENTURE());
}
/**
@ -1487,7 +1491,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
* @return bool
*/
public function isCreative(bool $literal = false) : bool{
return $this->gamemode === GameMode::CREATIVE or (!$literal and $this->gamemode === GameMode::SPECTATOR);
return $this->gamemode === GameMode::CREATIVE() or (!$literal and $this->gamemode === GameMode::SPECTATOR());
}
/**
@ -1499,14 +1503,14 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
* @return bool
*/
public function isAdventure(bool $literal = false) : bool{
return $this->gamemode === GameMode::ADVENTURE or (!$literal and $this->gamemode === GameMode::SPECTATOR);
return $this->gamemode === GameMode::ADVENTURE() or (!$literal and $this->gamemode === GameMode::SPECTATOR());
}
/**
* @return bool
*/
public function isSpectator() : bool{
return $this->gamemode === GameMode::SPECTATOR;
return $this->gamemode === GameMode::SPECTATOR();
}
public function isFireProof() : bool{
@ -2793,7 +2797,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
}
$nbt->setTag("Achievements", $achievements);
$nbt->setInt("playerGameType", $this->gamemode);
$nbt->setInt("playerGameType", $this->gamemode->getMagicNumber());
$nbt->setLong("firstPlayed", $this->firstPlayed);
$nbt->setLong("lastPlayed", (int) floor(microtime(true) * 1000));

View File

@ -422,10 +422,10 @@ class Server{
}
/**
* @return int
* @return GameMode
*/
public function getGamemode() : int{
return $this->getConfigInt("gamemode", 0) & 0b11;
public function getGamemode() : GameMode{
return GameMode::fromMagicNumber($this->getConfigInt("gamemode", 0) & 0b11);
}
/**
@ -1322,7 +1322,7 @@ class Server{
$this->tickCounter = 0;
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.defaultGameMode", [GameMode::toTranslation($this->getGamemode())]));
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.defaultGameMode", [$this->getGamemode()->getTranslationKey()]));
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.startFinished", [round(microtime(true) - \pocketmine\START_TIME, 3)]));

View File

@ -56,9 +56,8 @@ class DefaultGamemodeCommand extends VanillaCommand{
return true;
}
$sender->getServer()->setConfigInt("gamemode", $gameMode);
$sender->sendMessage(new TranslationContainer("commands.defaultgamemode.success", [GameMode::toTranslation($gameMode)]));
$sender->getServer()->setConfigInt("gamemode", $gameMode->getMagicNumber());
$sender->sendMessage(new TranslationContainer("commands.defaultgamemode.success", [$gameMode->getTranslationKey()]));
return true;
}
}

View File

@ -76,10 +76,10 @@ class GamemodeCommand extends VanillaCommand{
$sender->sendMessage("Game mode change for " . $target->getName() . " failed!");
}else{
if($target === $sender){
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.self", [GameMode::toTranslation($gameMode)]));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.self", [$gameMode->getTranslationKey()]));
}else{
$target->sendMessage(new TranslationContainer("gameMode.changed", [GameMode::toTranslation($gameMode)]));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.other", [GameMode::toTranslation($gameMode), $target->getName()]));
$target->sendMessage(new TranslationContainer("gameMode.changed", [$gameMode->getTranslationKey()]));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.other", [$gameMode->getTranslationKey(), $target->getName()]));
}
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\event\player;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\GameMode;
use pocketmine\Player;
/**
@ -33,15 +34,15 @@ use pocketmine\Player;
class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellable{
use CancellableTrait;
/** @var int */
/** @var GameMode */
protected $gamemode;
public function __construct(Player $player, int $newGamemode){
public function __construct(Player $player, GameMode $newGamemode){
$this->player = $player;
$this->gamemode = $newGamemode;
}
public function getNewGamemode() : int{
public function getNewGamemode() : GameMode{
return $this->gamemode;
}
}

View File

@ -86,7 +86,7 @@ class QueryRegenerateEvent extends ServerEvent{
}
}
$this->gametype = ($server->getGamemode() & 0x01) === 0 ? "SMP" : "CMP";
$this->gametype = ($server->getGamemode()->getMagicNumber() & 0x01) === 0 ? "SMP" : "CMP";
$this->version = $server->getVersion();
$this->server_engine = $server->getName() . " " . $server->getPocketMineVersion();
$level = $server->getLevelManager()->getDefaultLevel();

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe;
use pocketmine\GameMode;
use pocketmine\network\AdvancedNetworkInterface;
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
@ -210,7 +209,7 @@ class RakLibInterface implements ServerInstance, AdvancedNetworkInterface{
$info->getMaxPlayerCount(),
$this->rakLib->getServerId(),
$this->server->getName(),
GameMode::toString($this->server->getGamemode())
$this->server->getGamemode()->getEnglishName()
]) . ";"
);
}

View File

@ -468,7 +468,7 @@ class SimpleSessionHandler extends SessionHandler{
}
public function handleSetPlayerGameType(SetPlayerGameTypePacket $packet) : bool{
if($packet->gamemode !== $this->player->getGamemode()){
if($packet->gamemode !== $this->player->getGamemode()->getMagicNumber()){
//Set this back to default. TODO: handle this properly
$this->player->sendGamemode();
$this->player->sendSettings();