From b4cc3bbd430f4142c61bae1714eafafe2b039d7e Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Tue, 1 Apr 2014 19:46:48 +0200 Subject: [PATCH] Added /op, /deop, /kick, OfflinePlayer, moved player list to Server instead of static Player --- src/pocketmine/IPlayer.php | 78 ++++++ src/pocketmine/OfflinePlayer.php | 118 +++++++++ src/pocketmine/Player.php | 232 ++++------------ src/pocketmine/Server.php | 249 +++++++++++++++++- src/pocketmine/command/SimpleCommandMap.php | 6 + .../command/defaults/BanCommand.php | 2 +- .../command/defaults/BanIpCommand.php | 4 +- .../command/defaults/DeopCommand.php | 63 +++++ .../command/defaults/KickCommand.php | 69 +++++ .../command/defaults/ListCommand.php | 4 +- src/pocketmine/command/defaults/OpCommand.php | 63 +++++ .../command/defaults/SayCommand.php | 2 +- .../command/defaults/StopCommand.php | 2 +- .../command/defaults/TellCommand.php | 3 +- .../event/player/PlayerChatEvent.php | 2 +- src/pocketmine/network/query/QueryHandler.php | 6 +- 16 files changed, 699 insertions(+), 204 deletions(-) create mode 100644 src/pocketmine/IPlayer.php create mode 100644 src/pocketmine/OfflinePlayer.php create mode 100644 src/pocketmine/command/defaults/DeopCommand.php create mode 100644 src/pocketmine/command/defaults/KickCommand.php create mode 100644 src/pocketmine/command/defaults/OpCommand.php diff --git a/src/pocketmine/IPlayer.php b/src/pocketmine/IPlayer.php new file mode 100644 index 000000000..78fdd45cc --- /dev/null +++ b/src/pocketmine/IPlayer.php @@ -0,0 +1,78 @@ +server = $server; + $this->name = $name; + if(file_exists($this->server->getDataPath() . "players/" . strtolower($this->getName()) . ".dat")){ + $this->namedtag = $this->server->getOfflinePlayerData($this->name); + }else{ + $this->namedtag = null; + } + } + + public function isOnline(){ + return $this->getPlayer() !== null; + } + + public function getName(){ + return $this->name; + } + + public function getServer(){ + return $this->server; + } + + public function isOp(){ + return $this->server->isOp(strtolower($this->getName())); + } + + public function setOp($value){ + if($value === $this->isOp()){ + return; + } + + if($value === true){ + $this->server->addOp(strtolower($this->getName())); + }else{ + $this->server->removeOp(strtolower($this->getName())); + } + } + + public function isBanned(){ + return $this->server->getNameBans()->isBanned(strtolower($this->getName())); + } + + public function setBanned($value){ + if($value === true){ + $this->server->getNameBans()->addBan($this->getName(), null, null, null); + }else{ + $this->server->getNameBans()->remove($this->getName()); + } + } + + public function isWhitelisted(){ + return $this->server->isWhitelisted(strtolower($this->getName())); + } + + public function setWhitelisted($value){ + if($value === true){ + $this->server->addWhitelist(strtolower($this->getName())); + }else{ + $this->server->removeWhitelist(strtolower($this->getName())); + } + } + + public function getPlayer(){ + return $this->server->getPlayerExact($this->getName()); + } + + public function getFirstPlayed(){ + return $this->namedtag instanceof Compound ? $this->namedtag["firstPlayed"] : null; + } + + public function getLastPlayed(){ + return $this->namedtag instanceof Compound ? $this->namedtag["lastPlayed"] : null; + } + + public function hasPlayedBefore(){ + return $this->namedtag instanceof Compound; + } + + + +} diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 6fb0475f4..497c5df0f 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -35,6 +35,7 @@ use pocketmine\nbt\tag\Double; use pocketmine\nbt\tag\Enum; use pocketmine\nbt\tag\Float; use pocketmine\nbt\tag\Int; +use pocketmine\nbt\tag\Long; use pocketmine\nbt\tag\Short; use pocketmine\nbt\tag\String; use pocketmine\network\protocol\AdventureSettingsPacket; @@ -75,11 +76,8 @@ use pocketmine\utils\Utils; /** * Main class that handles networking, recovery, and packet sending to the server part * TODO: Move reliability layer - * - * Class Player - * @package PocketMine */ -class Player extends Human implements CommandSender{ +class Player extends Human implements CommandSender, IPlayer{ const SURVIVAL = 0; const CREATIVE = 1; @@ -91,11 +89,6 @@ class Player extends Human implements CommandSender{ const SURVIVAL_SLOTS = 36; const CREATIVE_SLOTS = 112; - /** - * @var Player[] - */ - public static $list = array(); - public $CID; public $MTU; public $spawned = false; @@ -161,6 +154,45 @@ class Player extends Human implements CommandSender{ /** @var PermissibleBase */ private $perm = null; + public function isBanned(){ + return $this->server->getNameBans()->isBanned(strtolower($this->getName())); + } + + public function setBanned($value){ + if($value === true){ + $this->server->getNameBans()->addBan($this->getName(), null, null, null); + }else{ + $this->server->getNameBans()->remove($this->getName()); + } + } + + public function isWhitelisted(){ + return $this->server->isWhitelisted(strtolower($this->getName())); + } + + public function setWhitelisted($value){ + if($value === true){ + $this->server->addWhitelist(strtolower($this->getName())); + }else{ + $this->server->removeWhitelist(strtolower($this->getName())); + } + } + + public function getPlayer(){ + return $this; + } + + public function getFirstPlayed(){ + return $this->namedtag instanceof Compound ? $this->namedtag["firstPlayed"] : null; + } + + public function getLastPlayed(){ + return $this->namedtag instanceof Compound ? $this->namedtag["lastPlayed"] : null; + } + + public function hasPlayedBefore(){ + return $this->namedtag instanceof Compound; + } protected function initEntity(){ $this->level->players[$this->CID] = $this; @@ -317,7 +349,6 @@ class Player extends Human implements CommandSender{ $this->lastBreak = microtime(true); $this->clientID = $clientID; $this->CID = $ip . ":" . $port; - Player::$list[$this->CID] = $this; $this->ip = $ip; $this->port = $port; $this->spawnPosition = Level::getDefault()->getSafeSpawn(); @@ -1220,8 +1251,7 @@ class Player extends Human implements CommandSender{ $this->iusername = strtolower($this->username); $this->loginData = array("clientId" => $packet->clientId, "loginData" => $packet->loginData); - //TODO: op things - if(count(Player::$list) > $this->server->getMaxPlayers()){ + if(count($this->server->getOnlinePlayers()) > $this->server->getMaxPlayers()){ if($this->kick("server full") === true){ return; } @@ -1265,16 +1295,17 @@ class Player extends Human implements CommandSender{ $this->server->getPluginManager()->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this); $this->server->getPluginManager()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this); - $u = Player::get($this->iusername, false, true); + //TODO + /*$u = $this->server->matchPlayer($this->username); if(count($u) > 0){ foreach($u as $p){ if($p !== $this){ $p->close($p->getDisplayName() . " has left the game", "logged in from another location"); } } - } + }*/ - $nbt = Player::getOffline($this->username); + $nbt = $this->server->getOfflinePlayerData($this->username); if(!isset($nbt->NameTag)){ $nbt->NameTag = new String("NameTag", $this->username); }else{ @@ -1300,7 +1331,8 @@ class Player extends Human implements CommandSender{ $this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false; } - Player::saveOffline($this->username, $nbt); + $nbt["lastPlayed"] = floor(microtime(true) * 1000); + $this->server->saveOfflinePlayerData($this->username, $nbt); parent::__construct($this->level, $nbt); $this->loggedIn = true; @@ -2244,8 +2276,8 @@ class Player extends Human implements CommandSender{ $this->sendBuffer(); $this->directDataPacket(new DisconnectPacket); - unset(Player::$list[$this->CID]); $this->connected = false; + $this->server->removePlayer($this); $this->level->freeAllChunks($this); $this->loggedIn = false; foreach($this->tasks as $task){ @@ -2257,7 +2289,7 @@ class Player extends Human implements CommandSender{ $this->resendQueue = array(); $this->ackQueue = array(); if($this->username != "" and ($this->namedtag instanceof Compound)){ - Player::saveOffline($this->username, $this->namedtag); + $this->server->saveOfflinePlayerData($this->username, $this->namedtag); } if(isset($ev) and $this->username != "" and $this->spawned !== false and $ev->getQuitMessage() != ""){ $this->server->broadcastMessage($ev->getQuitMessage()); @@ -2295,6 +2327,7 @@ class Player extends Human implements CommandSender{ } $this->namedtag["playerGameType"] = $this->gamemode; + $this->namedtag["lastPlayed"] = floor(microtime(true) * 1000); //$this->data->set("health", $this->getHealth()); } @@ -2330,169 +2363,6 @@ class Player extends Human implements CommandSender{ return array($pk->seqNumber); } - /** - * @return Player[] - */ - public static function getAll(){ - return Player::$list; - } - - /** - * Gets a player, or multiple - * - * @param string $name name/partial name to search - * @param bool $alike = true, if false, will only return exact matches - * @param bool $multiple = false, if true, will return an array with all the players that match - * - * @return Player[]|bool|Player - */ - public static function get($name, $alike = true, $multiple = false){ - $name = trim(strtolower($name)); - if($name === ""){ - return false; - } - $players = array(); - foreach(Player::$list as $player){ - if($multiple === false and $player->iusername === $name){ - return $player; - }elseif(strpos($player->iusername, $name) !== false){ - $players[$player->CID] = $player; - } - } - - if($multiple === false){ - if(count($players) > 0){ - return array_shift($players); - }else{ - return false; - } - }else{ - return $players; - } - } - - /** - * Gets or generates the NBT data for a player - * - * @param string $name - * - * @return Compound - */ - public static function getOffline($name){ - $server = Server::getInstance(); - $iname = strtolower($name); - if(!file_exists(Server::getInstance()->getDataPath() . "players/" . $iname . ".dat")){ - $spawn = Level::getDefault()->getSafeSpawn(); - $nbt = new Compound(false, array( - new Enum("Pos", array( - new Double(0, $spawn->x), - new Double(1, $spawn->y), - new Double(2, $spawn->z) - )), - new String("Level", Level::getDefault()->getName()), - new String("SpawnLevel", Level::getDefault()->getName()), - new Int("SpawnX", (int) $spawn->x), - new Int("SpawnY", (int) $spawn->y), - new Int("SpawnZ", (int) $spawn->z), - new Byte("SpawnForced", 1), //TODO - new Enum("Inventory", array()), - new Compound("Achievements", array()), - new Int("playerGameType", $server->getGamemode()), - new Enum("Motion", array( - new Double(0, 0.0), - new Double(1, 0.0), - new Double(2, 0.0) - )), - new Enum("Rotation", array( - new Float(0, 0.0), - new Float(1, 0.0) - )), - new Float("FallDistance", 0.0), - new Short("Fire", 0), - new Short("Air", 0), - new Byte("OnGround", 1), - new Byte("Invulnerable", 0), - new String("NameTag", $name), - )); - $nbt->Pos->setTagType(NBT::TAG_Double); - $nbt->Inventory->setTagType(NBT::TAG_Compound); - $nbt->Motion->setTagType(NBT::TAG_Double); - $nbt->Rotation->setTagType(NBT::TAG_Float); - if(file_exists(Server::getInstance()->getDataPath() . "players/" . $iname . ".yml")){ - $data = new Config(Server::getInstance()->getDataPath() . "players/" . $iname . ".yml", Config::YAML, array()); - $nbt["playerGameType"] = (int) $data->get("gamemode"); - $nbt["Level"] = $data->get("position")["level"]; - $nbt["Pos"][0] = $data->get("position")["x"]; - $nbt["Pos"][1] = $data->get("position")["y"]; - $nbt["Pos"][2] = $data->get("position")["z"]; - $nbt["SpawnLevel"] = $data->get("spawn")["level"]; - $nbt["SpawnX"] = (int) $data->get("spawn")["x"]; - $nbt["SpawnY"] = (int) $data->get("spawn")["y"]; - $nbt["SpawnZ"] = (int) $data->get("spawn")["z"]; - console("[NOTICE] Old Player data found for \"" . $iname . "\", upgrading profile"); - foreach($data->get("inventory") as $slot => $item){ - if(count($item) === 3){ - $nbt->Inventory[$slot + 9] = new Compound(false, array( - new Short("id", $item[0]), - new Short("Damage", $item[1]), - new Byte("Count", $item[2]), - new Byte("Slot", $slot + 9), - new Byte("TrueSlot", $slot + 9) - )); - } - } - foreach($data->get("hotbar") as $slot => $itemSlot){ - if(isset($nbt->Inventory[$itemSlot + 9])){ - $item = $nbt->Inventory[$itemSlot + 9]; - $nbt->Inventory[$slot] = new Compound(false, array( - new Short("id", $item->id), - new Short("Damage", $item->Damage), - new Byte("Count", $item->Count), - new Byte("Slot", $slot), - new Byte("TrueSlot", $item->TrueSlot) - )); - } - } - foreach($data->get("armor") as $slot => $item){ - if(count($item) === 2){ - $nbt->Inventory[$slot + 100] = new Compound(false, array( - new Short("id", $item[0]), - new Short("Damage", $item[1]), - new Byte("Count", 1), - new Byte("Slot", $slot + 100) - )); - } - } - foreach($data->get("achievements") as $achievement => $status){ - $nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0); - } - unlink(Server::getInstance()->getDataPath() . "players/" . $iname . ".yml"); - }else{ - console("[NOTICE] Player data not found for \"" . $iname . "\", creating new profile"); - Player::saveOffline($name, $nbt); - } - - }else{ - $nbt = new NBT(NBT::BIG_ENDIAN); - $nbt->readCompressed(file_get_contents(Server::getInstance()->getDataPath() . "players/" . $iname . ".dat")); - $nbt = $nbt->getData(); - } - - return $nbt; - } - - /** - * Saves a compressed NBT Coumpound tag as a player data - * - * @param string $name - * @param Compound $nbtTag - */ - public static function saveOffline($name, Compound $nbtTag){ - $nbt = new NBT(NBT::BIG_ENDIAN); - $nbt->setData($nbtTag); - file_put_contents(Server::getInstance()->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed()); - } - /** * Gets the username * diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 71ed0999c..bb1e8e805 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -39,6 +39,16 @@ use pocketmine\event\server\ServerCommandEvent; use pocketmine\item\Item; use pocketmine\level\generator\Generator; use pocketmine\level\Level; +use pocketmine\nbt\NBT; +use pocketmine\nbt\tag\Byte; +use pocketmine\nbt\tag\Compound; +use pocketmine\nbt\tag\Double; +use pocketmine\nbt\tag\Enum; +use pocketmine\nbt\tag\Float; +use pocketmine\nbt\tag\Int; +use pocketmine\nbt\tag\Long; +use pocketmine\nbt\tag\Short; +use pocketmine\nbt\tag\String; use pocketmine\network\Packet; use pocketmine\network\query\QueryHandler; use pocketmine\network\query\QueryPacket; @@ -128,6 +138,9 @@ class Server{ /** @var Config */ private $properties; + /** @var Player[] */ + private $players = array(); + /** * @return string */ @@ -432,6 +445,216 @@ class Server{ return $this->commandMap; } + /** + * @return Player[] + */ + public function getOnlinePlayers(){ + return $this->players; + } + + /** + * @param string $name + * + * @return OfflinePlayer|Player + */ + public function getOfflinePlayer($name){ + $name = strtolower($name); + $result = $this->getPlayerExact($name); + + if($result === null){ + $result = new OfflinePlayer($this, $name); + } + return $result; + } + + /** + * @param string $name + * + * @return Compound + */ + public function getOfflinePlayerData($name){ + $name = strtolower($name); + $path = $this->getDataPath() . "players/"; + if(!file_exists($path . "$name.dat")){ + $spawn = Level::getDefault()->getSafeSpawn(); + $nbt = new Compound(false, array( + new Long("firstPlayed", floor(microtime(true) * 1000)), + new Long("lastPlayed", floor(microtime(true) * 1000)), + new Enum("Pos", array( + new Double(0, $spawn->x), + new Double(1, $spawn->y), + new Double(2, $spawn->z) + )), + new String("Level", Level::getDefault()->getName()), + new String("SpawnLevel", Level::getDefault()->getName()), + new Int("SpawnX", (int) $spawn->x), + new Int("SpawnY", (int) $spawn->y), + new Int("SpawnZ", (int) $spawn->z), + new Byte("SpawnForced", 1), //TODO + new Enum("Inventory", array()), + new Compound("Achievements", array()), + new Int("playerGameType", $this->getGamemode()), + new Enum("Motion", array( + new Double(0, 0.0), + new Double(1, 0.0), + new Double(2, 0.0) + )), + new Enum("Rotation", array( + new Float(0, 0.0), + new Float(1, 0.0) + )), + new Float("FallDistance", 0.0), + new Short("Fire", 0), + new Short("Air", 0), + new Byte("OnGround", 1), + new Byte("Invulnerable", 0), + new String("NameTag", $name), + )); + $nbt->Pos->setTagType(NBT::TAG_Double); + $nbt->Inventory->setTagType(NBT::TAG_Compound); + $nbt->Motion->setTagType(NBT::TAG_Double); + $nbt->Rotation->setTagType(NBT::TAG_Float); + + if(file_exists($path . "$name.yml")){ //Importing old PocketMine-MP files + $data = new Config($path . "$name.yml", Config::YAML, array()); + $nbt["playerGameType"] = (int) $data->get("gamemode"); + $nbt["Level"] = $data->get("position")["level"]; + $nbt["Pos"][0] = $data->get("position")["x"]; + $nbt["Pos"][1] = $data->get("position")["y"]; + $nbt["Pos"][2] = $data->get("position")["z"]; + $nbt["SpawnLevel"] = $data->get("spawn")["level"]; + $nbt["SpawnX"] = (int) $data->get("spawn")["x"]; + $nbt["SpawnY"] = (int) $data->get("spawn")["y"]; + $nbt["SpawnZ"] = (int) $data->get("spawn")["z"]; + console("[NOTICE] Old Player data found for \"" . $name . "\", upgrading profile"); + foreach($data->get("inventory") as $slot => $item){ + if(count($item) === 3){ + $nbt->Inventory[$slot + 9] = new Compound(false, array( + new Short("id", $item[0]), + new Short("Damage", $item[1]), + new Byte("Count", $item[2]), + new Byte("Slot", $slot + 9), + new Byte("TrueSlot", $slot + 9) + )); + } + } + foreach($data->get("hotbar") as $slot => $itemSlot){ + if(isset($nbt->Inventory[$itemSlot + 9])){ + $item = $nbt->Inventory[$itemSlot + 9]; + $nbt->Inventory[$slot] = new Compound(false, array( + new Short("id", $item->id), + new Short("Damage", $item->Damage), + new Byte("Count", $item->Count), + new Byte("Slot", $slot), + new Byte("TrueSlot", $item->TrueSlot) + )); + } + } + foreach($data->get("armor") as $slot => $item){ + if(count($item) === 2){ + $nbt->Inventory[$slot + 100] = new Compound(false, array( + new Short("id", $item[0]), + new Short("Damage", $item[1]), + new Byte("Count", 1), + new Byte("Slot", $slot + 100) + )); + } + } + foreach($data->get("achievements") as $achievement => $status){ + $nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0); + } + unlink($path . "$name.yml"); + }else{ + console("[NOTICE] Player data not found for \"" . $name . "\", creating new profile"); + } + $this->saveOfflinePlayerData($name, $nbt); + return $nbt; + }else{ + $nbt = new NBT(NBT::BIG_ENDIAN); + $nbt->readCompressed(file_get_contents($path . "$name.dat")); + return $nbt->getData(); + } + } + + /** + * @param string $name + * @param Compound $nbtTag + */ + public function saveOfflinePlayerData($name, Compound $nbtTag){ + $nbt = new NBT(NBT::BIG_ENDIAN); + $nbt->setData($nbtTag); + file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed()); + } + + /** + * @param string $name + * + * @return Player + */ + public function getPlayer($name){ + $found = null; + $name = strtolower($name); + $delta = PHP_INT_MAX; + foreach($this->getOnlinePlayers() as $player){ + if(stripos($player->getName(), $name) === 0){ + $curDelta = strlen($player->getName()) - strlen($name); + if($curDelta < $delta){ + $found = $player; + $delta = $curDelta; + } + if($curDelta === 0){ + break; + } + } + } + return $found; + } + + /** + * @param string $name + * + * @return Player + */ + public function getPlayerExact($name){ + $name = strtolower($name); + foreach($this->getOnlinePlayers() as $player){ + if(strtolower($player->getName()) === $name){ + return $player; + } + } + + return null; + } + + /** + * @param string $partialName + * + * @return Player[] + */ + public function matchPlayer($partialName){ + $partialName = strtolower($partialName); + $matchedPlayers = array(); + foreach($this->getOnlinePlayers() as $player){ + if(strtolower($player->getName()) === $partialName){ + $matchedPlayers = array($player); + break; + }elseif(stripos($player->getName(), $partialName) !== false){ + $matchedPlayers[] = $player; + } + } + + return $matchedPlayers; + } + + /** + * @param Player $player + */ + public function removePlayer(Player $player){ + if($player->isOnline() === false){ + unset($this->players[$player->getAddress() . ":" . $player->getPort()]); + } + } + /** * @param string $variable * @param string $defaultValue @@ -547,9 +770,10 @@ class Server{ public function addOp($name){ $this->operators->set(strtolower($name), true); - if(($player = Player::get($name, false, false)) instanceof Player){ + if(($player = $this->getPlayerExact($name)) instanceof Player){ $player->recalculatePermissions(); } + $this->operators->save(); } /** @@ -558,9 +782,10 @@ class Server{ public function removeOp($name){ $this->operators->remove(strtolower($name)); - if(($player = Player::get($name, false, false)) instanceof Player){ + if(($player = $this->getPlayerExact($name)) instanceof Player){ $player->recalculatePermissions(); } + $this->operators->save(); } /** @@ -568,6 +793,7 @@ class Server{ */ public function addWhitelist($name){ $this->whitelist->set(strtolower($name), true); + $this->whitelist->save(); } /** @@ -575,6 +801,7 @@ class Server{ */ public function removeWhitelist($name){ $this->whitelist->remove(strtolower($name)); + $this->whitelist->save(); } /** @@ -748,9 +975,9 @@ class Server{ if(!defined("NO_THREADS") and $this->getProperty("enable-rcon") === true){ $this->rcon = new RCON($this->getProperty("rcon.password", ""), $this->getProperty("rcon.port", $this->getProperty("server-port")), ($ip = $this->getProperty("server-ip")) != "" ? $ip : "0.0.0.0", $this->getProperty("rcon.threads", 1), $this->getProperty("rcon.clients-per-thread", 50)); }*/ - $this->scheduler->scheduleRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), 20 * 45); + $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), 20 * 45, 20 * 45); if($this->getConfigBoolean("auto-save", true) === true){ - $this->scheduler->scheduleRepeatingTask(new CallbackTask(array($this, "doAutoSave")), 18000); + $this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), 18000, 18000); } $this->enablePlugins(PluginLoadOrder::POSTWORLD); @@ -883,7 +1110,7 @@ class Server{ $this->pluginManager->disablePlugins(); - foreach(Player::getAll() as $player){ + foreach($this->players as $player){ $player->kick("server stop"); } @@ -953,8 +1180,8 @@ class Server{ $this->queryHandler->handle($packet); }elseif($packet instanceof RakNetPacket){ $CID = $packet->ip . ":" . $packet->port; - if(isset(Player::$list[$CID])){ - Player::$list[$CID]->handlePacket($packet); + if(isset($this->players[$CID])){ + $this->players[$CID]->handlePacket($packet); }else{ switch($packet->pid()){ case RakNetInfo::UNCONNECTED_PING: @@ -962,7 +1189,7 @@ class Server{ $pk = new RakNetPacket(RakNetInfo::UNCONNECTED_PONG); $pk->pingID = $packet->pingID; $pk->serverID = $this->serverID; - $pk->serverType = "MCCPP;Demo;" . $this->getMotd() . " [" . count(Player::$list) . "/" . $this->getMaxPlayers() . "]"; + $pk->serverType = "MCCPP;Demo;" . $this->getMotd() . " [" . count($this->players) . "/" . $this->getMaxPlayers() . "]"; $pk->ip = $packet->ip; $pk->port = $packet->port; $this->sendPacket($pk); @@ -985,7 +1212,7 @@ class Server{ } break; case RakNetInfo::OPEN_CONNECTION_REQUEST_2: - new Player($packet->clientID, $packet->ip, $packet->port, $packet->mtuSize); //New Session! + $this->players[$CID] = new Player($packet->clientID, $packet->ip, $packet->port, $packet->mtuSize); //New Session! $pk = new RakNetPacket(RakNetInfo::OPEN_CONNECTION_REPLY_2); $pk->serverID = $this->serverID; $pk->serverPort = $this->getPort(); @@ -1068,7 +1295,7 @@ class Server{ "version" => VERSION, "mc_version" => MINECRAFT_VERSION, "protocol" => Info::CURRENT_PROTOCOL, - "online" => count(Player::$list), + "online" => count($this->players), "max" => $this->server->maxClients, "plugins" => $plist, ), @@ -1077,7 +1304,7 @@ class Server{ public function titleTick(){ if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and \pocketmine\ANSI === true){ - echo "\x1b]0;PocketMine-MP " . $this->getPocketMineVersion() . " | Online " . count(Player::$list) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . round($this->interface->getUploadSpeed() / 1024, 2) . " D " . round($this->interface->getDownloadSpeed() / 1024, 2) . " kB/s | TPS " . $this->getTicksPerSecond() . "\x07"; + echo "\x1b]0;PocketMine-MP " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . round($this->interface->getUploadSpeed() / 1024, 2) . " D " . round($this->interface->getDownloadSpeed() / 1024, 2) . " kB/s | TPS " . $this->getTicksPerSecond() . "\x07"; } } diff --git a/src/pocketmine/command/SimpleCommandMap.php b/src/pocketmine/command/SimpleCommandMap.php index 366c98266..eb644291c 100644 --- a/src/pocketmine/command/SimpleCommandMap.php +++ b/src/pocketmine/command/SimpleCommandMap.php @@ -25,10 +25,13 @@ use pocketmine\command\defaults\BanCommand; use pocketmine\command\defaults\BanIpCommand; use pocketmine\command\defaults\BanListCommand; use pocketmine\command\defaults\DefaultGamemodeCommand; +use pocketmine\command\defaults\DeopCommand; use pocketmine\command\defaults\DifficultyCommand; use pocketmine\command\defaults\HelpCommand; +use pocketmine\command\defaults\KickCommand; use pocketmine\command\defaults\ListCommand; use pocketmine\command\defaults\MeCommand; +use pocketmine\command\defaults\OpCommand; use pocketmine\command\defaults\PardonCommand; use pocketmine\command\defaults\PardonIpCommand; use pocketmine\command\defaults\PluginsCommand; @@ -72,6 +75,9 @@ class SimpleCommandMap implements CommandMap{ $this->register("pocketmine", new MeCommand("me")); $this->register("pocketmine", new ListCommand("list")); $this->register("pocketmine", new DifficultyCommand("difficulty")); + $this->register("pocketmine", new KickCommand("kick")); + $this->register("pocketmine", new OpCommand("op")); + $this->register("pocketmine", new DeopCommand("deop")); } diff --git a/src/pocketmine/command/defaults/BanCommand.php b/src/pocketmine/command/defaults/BanCommand.php index 2367a3667..9967eb9e1 100644 --- a/src/pocketmine/command/defaults/BanCommand.php +++ b/src/pocketmine/command/defaults/BanCommand.php @@ -54,7 +54,7 @@ class BanCommand extends VanillaCommand{ Server::getInstance()->getNameBans()->addBan($name, $reason, null, $sender->getName()); - if(($player = Player::get($name, true)) instanceof Player){ + if(($player = Server::getInstance()->getPlayerExact($name)) instanceof Player){ $player->kick("Banned by admin."); } diff --git a/src/pocketmine/command/defaults/BanIpCommand.php b/src/pocketmine/command/defaults/BanIpCommand.php index 5aaa7e92f..161750698 100644 --- a/src/pocketmine/command/defaults/BanIpCommand.php +++ b/src/pocketmine/command/defaults/BanIpCommand.php @@ -55,7 +55,7 @@ class BanIpCommand extends VanillaCommand{ if(preg_match("/^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$/", $value)){ $this->processIPBan($value, $sender, $reason); }else{ - if(($player = Player::get($value, true)) instanceof Player){ + if(($player = Server::getInstance()->getPlayer($value)) instanceof Player){ $this->processIPBan($player->getAddress(), $sender, $reason); }else{ $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); @@ -70,7 +70,7 @@ class BanIpCommand extends VanillaCommand{ private function processIPBan($ip, CommandSender $sender, $reason){ Server::getInstance()->getIPBans()->addBan($ip, $reason, null, $sender->getName()); - foreach(Player::getAll() as $player){ + foreach(Server::getInstance()->getOnlinePlayers() as $player){ if($player->getAddress() === $ip){ $player->kick("You have been IP banned."); } diff --git a/src/pocketmine/command/defaults/DeopCommand.php b/src/pocketmine/command/defaults/DeopCommand.php new file mode 100644 index 000000000..50f812010 --- /dev/null +++ b/src/pocketmine/command/defaults/DeopCommand.php @@ -0,0 +1,63 @@ +" + ); + $this->setPermission("pocketmine.command.op.take"); + } + + public function execute(CommandSender $sender, $currentAlias, array $args){ + if(!$this->testPermission($sender)){ + return true; + } + + if(count($args) === 0){ + $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); + + return false; + } + + $name = array_shift($args); + + $player = Server::getInstance()->getOfflinePlayer($name); + $player->setOp(false); + if($player instanceof Player){ + $player->sendMessage(TextFormat::YELLOW . "You are no longer op!"); + } + Command::broadcastCommandMessage($sender, "De-opped " . $player->getName()); + + return true; + } +} \ No newline at end of file diff --git a/src/pocketmine/command/defaults/KickCommand.php b/src/pocketmine/command/defaults/KickCommand.php new file mode 100644 index 000000000..6946c10ed --- /dev/null +++ b/src/pocketmine/command/defaults/KickCommand.php @@ -0,0 +1,69 @@ + [reason...]" + ); + $this->setPermission("pocketmine.command.kick"); + } + + public function execute(CommandSender $sender, $currentAlias, array $args){ + if(!$this->testPermission($sender)){ + return true; + } + + if(count($args) === 0){ + $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); + + return false; + } + + $name = array_shift($args); + $reason = trim(implode(" ", $args)); + + if($reason === ""){ + $reason = "Kicked by an operator."; + } + + if(($player = Server::getInstance()->getPlayer($name)) instanceof Player){ + $player->kick("Banned by admin."); + }else{ + $sender->sendMessage($name . " not found."); + } + + Command::broadcastCommandMessage($sender, "Kicked player " . $name . ". With reason:\n" . $reason); + + return true; + } +} \ No newline at end of file diff --git a/src/pocketmine/command/defaults/ListCommand.php b/src/pocketmine/command/defaults/ListCommand.php index 0db5fdc8e..570b1a36f 100644 --- a/src/pocketmine/command/defaults/ListCommand.php +++ b/src/pocketmine/command/defaults/ListCommand.php @@ -45,13 +45,13 @@ class ListCommand extends VanillaCommand{ $online = ""; - foreach(Player::getAll() as $player){ + foreach(Server::getInstance()->getOnlinePlayers() as $player){ if($player->isOnline() and (!($sender instanceof Player) or $sender->canSee($player))){ $online .= $player->getDisplayName() . ", "; } } - $sender->sendMessage("There are ".count(Player::getAll())."/".Server::getInstance()->getMaxPlayers()." players online:\n" . substr($online, 0, -2)); + $sender->sendMessage("There are ".count(Server::getInstance()->getOnlinePlayers())."/".Server::getInstance()->getMaxPlayers()." players online:\n" . substr($online, 0, -2)); return true; } diff --git a/src/pocketmine/command/defaults/OpCommand.php b/src/pocketmine/command/defaults/OpCommand.php new file mode 100644 index 000000000..8898037e5 --- /dev/null +++ b/src/pocketmine/command/defaults/OpCommand.php @@ -0,0 +1,63 @@ +" + ); + $this->setPermission("pocketmine.command.op.give"); + } + + public function execute(CommandSender $sender, $currentAlias, array $args){ + if(!$this->testPermission($sender)){ + return true; + } + + if(count($args) === 0){ + $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); + + return false; + } + + $name = array_shift($args); + + $player = Server::getInstance()->getOfflinePlayer($name); + Command::broadcastCommandMessage($sender, "Opped " . $player->getName()); + if($player instanceof Player){ + $player->sendMessage("You are now op!"); + } + $player->setOp(true); + + return true; + } +} \ No newline at end of file diff --git a/src/pocketmine/command/defaults/SayCommand.php b/src/pocketmine/command/defaults/SayCommand.php index 710aac1f9..d71ea6491 100644 --- a/src/pocketmine/command/defaults/SayCommand.php +++ b/src/pocketmine/command/defaults/SayCommand.php @@ -35,7 +35,7 @@ class SayCommand extends VanillaCommand{ "Broadcasts the given message as the sender", "/say " ); - $this->setPermission("pocketmine.command.seed"); + $this->setPermission("pocketmine.command.say"); } public function execute(CommandSender $sender, $currentAlias, array $args){ diff --git a/src/pocketmine/command/defaults/StopCommand.php b/src/pocketmine/command/defaults/StopCommand.php index ff867749d..a4edc73fd 100644 --- a/src/pocketmine/command/defaults/StopCommand.php +++ b/src/pocketmine/command/defaults/StopCommand.php @@ -46,7 +46,7 @@ class StopCommand extends VanillaCommand{ $reason = implode(" ", $args); if($reason !== ""){ - foreach(Player::getAll() as $player){ + foreach(Server::getInstance()->getOnlinePlayers() as $player){ $player->kick($reason); } } diff --git a/src/pocketmine/command/defaults/TellCommand.php b/src/pocketmine/command/defaults/TellCommand.php index 7b5825ef5..362b5e64d 100644 --- a/src/pocketmine/command/defaults/TellCommand.php +++ b/src/pocketmine/command/defaults/TellCommand.php @@ -23,6 +23,7 @@ namespace pocketmine\command\defaults; use pocketmine\command\CommandSender; use pocketmine\Player; +use pocketmine\Server; use pocketmine\utils\TextFormat; class TellCommand extends VanillaCommand{ @@ -50,7 +51,7 @@ class TellCommand extends VanillaCommand{ $name = strtolower(array_shift($args)); - $player = Player::get($name, true, false); + $player = Server::getInstance()->getPlayer($name); if($player instanceof Player){ $sender->sendMessage("[me -> " . $player->getName() . "] " . implode($args)); diff --git a/src/pocketmine/event/player/PlayerChatEvent.php b/src/pocketmine/event/player/PlayerChatEvent.php index 31a1779b5..5822adf74 100644 --- a/src/pocketmine/event/player/PlayerChatEvent.php +++ b/src/pocketmine/event/player/PlayerChatEvent.php @@ -47,7 +47,7 @@ class PlayerChatEvent extends PlayerEvent implements Cancellable{ $this->message = $message; $this->format = $format; if($recipients === null){ - $this->recipients = Server::getInstance()->getPluginManager()->getPermissionSubscriptions(Player::BROADCAST_CHANNEL_USERS); + $this->recipients = Server::getInstance()->getPluginManager()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_USERS); }else{ $this->recipients = $recipients; } diff --git a/src/pocketmine/network/query/QueryHandler.php b/src/pocketmine/network/query/QueryHandler.php index ae218568f..f4191d763 100644 --- a/src/pocketmine/network/query/QueryHandler.php +++ b/src/pocketmine/network/query/QueryHandler.php @@ -75,7 +75,7 @@ class QueryHandler{ "server_engine" => $this->server->getName() . " " . $this->server->getPocketMineVersion(), "plugins" => $plist, "map" => Level::getDefault()->getName(), - "numplayers" => count(Player::$list), + "numplayers" => count($this->server->getOnlinePlayers()), "maxplayers" => $this->server->getMaxPlayers(), "whitelist" => $this->server->hasWhitelist() === true ? "on" : "off", "hostport" => $this->server->getPort() @@ -84,7 +84,7 @@ class QueryHandler{ $str .= $key . "\x00" . $value . "\x00"; } $str .= "\x00\x01player_\x00\x00"; - foreach(Player::$list as $player){ + foreach($this->server->getOnlinePlayers() as $player){ if($player->getName() != ""){ $str .= $player->getName() . "\x00"; } @@ -132,7 +132,7 @@ class QueryHandler{ } $pk->payload = $this->longData; }else{ - $pk->payload = $this->server->getServerName() . "\x00" . (($this->server->getGamemode() & 0x01) === 0 ? "SMP" : "CMP") . "\x00" . Level::getDefault()->getName() . "\x00" . count(Player::$list) . "\x00" . $this->server->getMaxPlayers() . "\x00" . Utils::writeLShort($this->server->getPort()) . $this->server->getIp() . "\x00"; + $pk->payload = $this->server->getServerName() . "\x00" . (($this->server->getGamemode() & 0x01) === 0 ? "SMP" : "CMP") . "\x00" . Level::getDefault()->getName() . "\x00" . count($this->server->getOnlinePlayers()) . "\x00" . $this->server->getMaxPlayers() . "\x00" . Utils::writeLShort($this->server->getPort()) . $this->server->getIp() . "\x00"; } $pk->encode(); $this->server->sendPacket($pk);