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; namespace pocketmine;
final class GameMode{ use pocketmine\utils\EnumTrait;
public const SURVIVAL = 0;
public const CREATIVE = 1;
public const ADVENTURE = 2;
public const SPECTATOR = 3;
public const VIEW = GameMode::SPECTATOR;
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 int $n
*
* @param string $str
*
* @return int
* *
* @return GameMode
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public static function fromString(string $str) : int{ public static function fromMagicNumber(int $n) : self{
switch(strtolower(trim($str))){ self::checkInit();
case (string) self::SURVIVAL: if(!isset(self::$magicNumberMap[$n])){
case "survival": throw new \InvalidArgumentException("No " . self::class . " enum member matches magic number $n");
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;
} }
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;
} }
/** /**
* Returns the gamemode text name * @return int
*
* @param int $mode
*
* @return string
*/ */
public static function toTranslation(int $mode) : string{ public function getMagicNumber() : int{
switch($mode){ return $this->magicNumber;
case self::SURVIVAL:
return "%gameMode.survival";
case self::CREATIVE:
return "%gameMode.creative";
case self::ADVENTURE:
return "%gameMode.adventure";
case self::SPECTATOR:
return "%gameMode.spectator";
}
return "UNKNOWN";
} }
public static function toString(int $mode) : string{ /**
switch($mode){ * @return string
case self::SURVIVAL: */
return "Survival"; public function getEnglishName() : string{
case self::CREATIVE: return $this->englishName;
return "Creative"; }
case self::ADVENTURE:
return "Adventure"; /**
case self::SPECTATOR: * @return string
return "Spectator"; */
default: public function getTranslationKey() : string{
throw new \InvalidArgumentException("Invalid gamemode $mode"); return "%" . $this->translationKey;
} }
/**
* @return string[]
*/
public function getAliases() : array{
return $this->aliases;
} }
//TODO: ability sets per gamemode //TODO: ability sets per gamemode

View File

@ -94,6 +94,7 @@ use pocketmine\metadata\MetadataValue;
use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag; use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\CompressBatchPromise; use pocketmine\network\mcpe\CompressBatchPromise;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
@ -224,7 +225,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
protected $firstPlayed; protected $firstPlayed;
/** @var int */ /** @var int */
protected $lastPlayed; protected $lastPlayed;
/** @var int */ /** @var GameMode */
protected $gamemode; protected $gamemode;
/** @var bool[] chunkHash => bool (true = sent, false = needs sending) */ /** @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->firstPlayed = $nbt->getLong("firstPlayed", $now = (int) (microtime(true) * 1000));
$this->lastPlayed = $nbt->getLong("lastPlayed", $now); $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->allowFlight = $this->isCreative();
$this->keepMovement = $this->isSpectator() || $this->allowMovementCheats(); $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; 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 * TODO: remove this when Spectator Mode gets added properly to MCPE
* *
* @param int $gamemode * @param GameMode $gamemode
* *
* @return int * @return int
*/ */
public static function getClientFriendlyGamemode(int $gamemode) : int{ public static function getClientFriendlyGamemode(GameMode $gamemode) : int{
$gamemode &= 0x03; if($gamemode === GameMode::SPECTATOR()){
if($gamemode === GameMode::SPECTATOR){ return GameMode::CREATIVE()->getMagicNumber();
return GameMode::CREATIVE;
} }
return $gamemode; return $gamemode->getMagicNumber();
} }
/** /**
* Sets the gamemode, and if needed, kicks the Player. * 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 * @param bool $client if the client made this change in their GUI
* *
* @return bool * @return bool
*/ */
public function setGamemode(int $gm, bool $client = false) : bool{ public function setGamemode(GameMode $gm, bool $client = false) : bool{
if($gm < 0 or $gm > 3 or $this->gamemode === $gm){ if($this->gamemode === $gm){
return false; 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 if(!$client){ //Gamemode changed by server, do not send for client changes
$this->sendGamemode(); $this->sendGamemode();
}else{ }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(); $this->sendSettings();
@ -1475,7 +1479,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
* @return bool * @return bool
*/ */
public function isSurvival(bool $literal = false) : 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 * @return bool
*/ */
public function isCreative(bool $literal = false) : 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 * @return bool
*/ */
public function isAdventure(bool $literal = false) : 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 * @return bool
*/ */
public function isSpectator() : bool{ public function isSpectator() : bool{
return $this->gamemode === GameMode::SPECTATOR; return $this->gamemode === GameMode::SPECTATOR();
} }
public function isFireProof() : bool{ public function isFireProof() : bool{
@ -2793,7 +2797,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
} }
$nbt->setTag("Achievements", $achievements); $nbt->setTag("Achievements", $achievements);
$nbt->setInt("playerGameType", $this->gamemode); $nbt->setInt("playerGameType", $this->gamemode->getMagicNumber());
$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

@ -422,10 +422,10 @@ class Server{
} }
/** /**
* @return int * @return GameMode
*/ */
public function getGamemode() : int{ public function getGamemode() : GameMode{
return $this->getConfigInt("gamemode", 0) & 0b11; return GameMode::fromMagicNumber($this->getConfigInt("gamemode", 0) & 0b11);
} }
/** /**
@ -1322,7 +1322,7 @@ class Server{
$this->tickCounter = 0; $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)])); $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; return true;
} }
$sender->getServer()->setConfigInt("gamemode", $gameMode); $sender->getServer()->setConfigInt("gamemode", $gameMode->getMagicNumber());
$sender->sendMessage(new TranslationContainer("commands.defaultgamemode.success", [GameMode::toTranslation($gameMode)])); $sender->sendMessage(new TranslationContainer("commands.defaultgamemode.success", [$gameMode->getTranslationKey()]));
return true; return true;
} }
} }

View File

@ -76,10 +76,10 @@ class GamemodeCommand extends VanillaCommand{
$sender->sendMessage("Game mode change for " . $target->getName() . " failed!"); $sender->sendMessage("Game mode change for " . $target->getName() . " failed!");
}else{ }else{
if($target === $sender){ 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{ }else{
$target->sendMessage(new TranslationContainer("gameMode.changed", [GameMode::toTranslation($gameMode)])); $target->sendMessage(new TranslationContainer("gameMode.changed", [$gameMode->getTranslationKey()]));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.other", [GameMode::toTranslation($gameMode), $target->getName()])); 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\Cancellable;
use pocketmine\event\CancellableTrait; use pocketmine\event\CancellableTrait;
use pocketmine\GameMode;
use pocketmine\Player; use pocketmine\Player;
/** /**
@ -33,15 +34,15 @@ use pocketmine\Player;
class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellable{ class PlayerGameModeChangeEvent extends PlayerEvent implements Cancellable{
use CancellableTrait; use CancellableTrait;
/** @var int */ /** @var GameMode */
protected $gamemode; protected $gamemode;
public function __construct(Player $player, int $newGamemode){ public function __construct(Player $player, GameMode $newGamemode){
$this->player = $player; $this->player = $player;
$this->gamemode = $newGamemode; $this->gamemode = $newGamemode;
} }
public function getNewGamemode() : int{ public function getNewGamemode() : GameMode{
return $this->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->version = $server->getVersion();
$this->server_engine = $server->getName() . " " . $server->getPocketMineVersion(); $this->server_engine = $server->getName() . " " . $server->getPocketMineVersion();
$level = $server->getLevelManager()->getDefaultLevel(); $level = $server->getLevelManager()->getDefaultLevel();

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe; namespace pocketmine\network\mcpe;
use pocketmine\GameMode;
use pocketmine\network\AdvancedNetworkInterface; use pocketmine\network\AdvancedNetworkInterface;
use pocketmine\network\BadPacketException; use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\ProtocolInfo; use pocketmine\network\mcpe\protocol\ProtocolInfo;
@ -210,7 +209,7 @@ class RakLibInterface implements ServerInstance, AdvancedNetworkInterface{
$info->getMaxPlayerCount(), $info->getMaxPlayerCount(),
$this->rakLib->getServerId(), $this->rakLib->getServerId(),
$this->server->getName(), $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{ 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 //Set this back to default. TODO: handle this properly
$this->player->sendGamemode(); $this->player->sendGamemode();
$this->player->sendSettings(); $this->player->sendSettings();