Added /op, /deop, /kick, OfflinePlayer, moved player list to Server instead of static Player

This commit is contained in:
Shoghi Cervantes 2014-04-01 19:46:48 +02:00
parent e60ea2eb15
commit b4cc3bbd43
16 changed files with 699 additions and 204 deletions

View File

@ -0,0 +1,78 @@
<?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/
*
*
*/
namespace pocketmine;
use pocketmine\permission\ServerOperator;
interface IPlayer extends ServerOperator{
/**
* @return bool
*/
public function isOnline();
/**
* @return string
*/
public function getName();
/**
* @return bool
*/
public function isBanned();
/**
* @param bool $banned
*/
public function setBanned($banned);
/**
* @return bool
*/
public function isWhitelisted();
/**
* @param bool $value
*/
public function setWhitelisted($value);
/**
* @return Player|null
*/
public function getPlayer();
/**
* @return int|double
*/
public function getFirstPlayed();
/**
* @return int|double
*/
public function getLastPlayed();
/**
* @return mixed
*/
public function hasPlayedBefore();
}

View File

@ -0,0 +1,118 @@
<?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/
*
*
*/
namespace pocketmine;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Compound;
class OfflinePlayer implements IPlayer{
private $name;
private $server;
private $namedtag;
/**
* @param Server $server
* @param string $name
*/
public function __construct(Server $server, $name){
$this->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;
}
}

View File

@ -35,6 +35,7 @@ use pocketmine\nbt\tag\Double;
use pocketmine\nbt\tag\Enum; use pocketmine\nbt\tag\Enum;
use pocketmine\nbt\tag\Float; use pocketmine\nbt\tag\Float;
use pocketmine\nbt\tag\Int; use pocketmine\nbt\tag\Int;
use pocketmine\nbt\tag\Long;
use pocketmine\nbt\tag\Short; use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String; use pocketmine\nbt\tag\String;
use pocketmine\network\protocol\AdventureSettingsPacket; 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 * Main class that handles networking, recovery, and packet sending to the server part
* TODO: Move reliability layer * 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 SURVIVAL = 0;
const CREATIVE = 1; const CREATIVE = 1;
@ -91,11 +89,6 @@ class Player extends Human implements CommandSender{
const SURVIVAL_SLOTS = 36; const SURVIVAL_SLOTS = 36;
const CREATIVE_SLOTS = 112; const CREATIVE_SLOTS = 112;
/**
* @var Player[]
*/
public static $list = array();
public $CID; public $CID;
public $MTU; public $MTU;
public $spawned = false; public $spawned = false;
@ -161,6 +154,45 @@ class Player extends Human implements CommandSender{
/** @var PermissibleBase */ /** @var PermissibleBase */
private $perm = null; 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(){ protected function initEntity(){
$this->level->players[$this->CID] = $this; $this->level->players[$this->CID] = $this;
@ -317,7 +349,6 @@ class Player extends Human implements CommandSender{
$this->lastBreak = microtime(true); $this->lastBreak = microtime(true);
$this->clientID = $clientID; $this->clientID = $clientID;
$this->CID = $ip . ":" . $port; $this->CID = $ip . ":" . $port;
Player::$list[$this->CID] = $this;
$this->ip = $ip; $this->ip = $ip;
$this->port = $port; $this->port = $port;
$this->spawnPosition = Level::getDefault()->getSafeSpawn(); $this->spawnPosition = Level::getDefault()->getSafeSpawn();
@ -1220,8 +1251,7 @@ class Player extends Human implements CommandSender{
$this->iusername = strtolower($this->username); $this->iusername = strtolower($this->username);
$this->loginData = array("clientId" => $packet->clientId, "loginData" => $packet->loginData); $this->loginData = array("clientId" => $packet->clientId, "loginData" => $packet->loginData);
//TODO: op things if(count($this->server->getOnlinePlayers()) > $this->server->getMaxPlayers()){
if(count(Player::$list) > $this->server->getMaxPlayers()){
if($this->kick("server full") === true){ if($this->kick("server full") === true){
return; 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_ADMINISTRATIVE, $this);
$this->server->getPluginManager()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $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){ if(count($u) > 0){
foreach($u as $p){ foreach($u as $p){
if($p !== $this){ if($p !== $this){
$p->close($p->getDisplayName() . " has left the game", "logged in from another location"); $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)){ if(!isset($nbt->NameTag)){
$nbt->NameTag = new String("NameTag", $this->username); $nbt->NameTag = new String("NameTag", $this->username);
}else{ }else{
@ -1300,7 +1331,8 @@ class Player extends Human implements CommandSender{
$this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false; $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); parent::__construct($this->level, $nbt);
$this->loggedIn = true; $this->loggedIn = true;
@ -2244,8 +2276,8 @@ class Player extends Human implements CommandSender{
$this->sendBuffer(); $this->sendBuffer();
$this->directDataPacket(new DisconnectPacket); $this->directDataPacket(new DisconnectPacket);
unset(Player::$list[$this->CID]);
$this->connected = false; $this->connected = false;
$this->server->removePlayer($this);
$this->level->freeAllChunks($this); $this->level->freeAllChunks($this);
$this->loggedIn = false; $this->loggedIn = false;
foreach($this->tasks as $task){ foreach($this->tasks as $task){
@ -2257,7 +2289,7 @@ class Player extends Human implements CommandSender{
$this->resendQueue = array(); $this->resendQueue = array();
$this->ackQueue = array(); $this->ackQueue = array();
if($this->username != "" and ($this->namedtag instanceof Compound)){ 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() != ""){ if(isset($ev) and $this->username != "" and $this->spawned !== false and $ev->getQuitMessage() != ""){
$this->server->broadcastMessage($ev->getQuitMessage()); $this->server->broadcastMessage($ev->getQuitMessage());
@ -2295,6 +2327,7 @@ class Player extends Human implements CommandSender{
} }
$this->namedtag["playerGameType"] = $this->gamemode; $this->namedtag["playerGameType"] = $this->gamemode;
$this->namedtag["lastPlayed"] = floor(microtime(true) * 1000);
//$this->data->set("health", $this->getHealth()); //$this->data->set("health", $this->getHealth());
} }
@ -2330,169 +2363,6 @@ class Player extends Human implements CommandSender{
return array($pk->seqNumber); 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 * Gets the username
* *

View File

@ -39,6 +39,16 @@ use pocketmine\event\server\ServerCommandEvent;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\level\generator\Generator; use pocketmine\level\generator\Generator;
use pocketmine\level\Level; 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\Packet;
use pocketmine\network\query\QueryHandler; use pocketmine\network\query\QueryHandler;
use pocketmine\network\query\QueryPacket; use pocketmine\network\query\QueryPacket;
@ -128,6 +138,9 @@ class Server{
/** @var Config */ /** @var Config */
private $properties; private $properties;
/** @var Player[] */
private $players = array();
/** /**
* @return string * @return string
*/ */
@ -432,6 +445,216 @@ class Server{
return $this->commandMap; 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 $variable
* @param string $defaultValue * @param string $defaultValue
@ -547,9 +770,10 @@ class Server{
public function addOp($name){ public function addOp($name){
$this->operators->set(strtolower($name), true); $this->operators->set(strtolower($name), true);
if(($player = Player::get($name, false, false)) instanceof Player){ if(($player = $this->getPlayerExact($name)) instanceof Player){
$player->recalculatePermissions(); $player->recalculatePermissions();
} }
$this->operators->save();
} }
/** /**
@ -558,9 +782,10 @@ class Server{
public function removeOp($name){ public function removeOp($name){
$this->operators->remove(strtolower($name)); $this->operators->remove(strtolower($name));
if(($player = Player::get($name, false, false)) instanceof Player){ if(($player = $this->getPlayerExact($name)) instanceof Player){
$player->recalculatePermissions(); $player->recalculatePermissions();
} }
$this->operators->save();
} }
/** /**
@ -568,6 +793,7 @@ class Server{
*/ */
public function addWhitelist($name){ public function addWhitelist($name){
$this->whitelist->set(strtolower($name), true); $this->whitelist->set(strtolower($name), true);
$this->whitelist->save();
} }
/** /**
@ -575,6 +801,7 @@ class Server{
*/ */
public function removeWhitelist($name){ public function removeWhitelist($name){
$this->whitelist->remove(strtolower($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){ 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->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){ 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); $this->enablePlugins(PluginLoadOrder::POSTWORLD);
@ -883,7 +1110,7 @@ class Server{
$this->pluginManager->disablePlugins(); $this->pluginManager->disablePlugins();
foreach(Player::getAll() as $player){ foreach($this->players as $player){
$player->kick("server stop"); $player->kick("server stop");
} }
@ -953,8 +1180,8 @@ class Server{
$this->queryHandler->handle($packet); $this->queryHandler->handle($packet);
}elseif($packet instanceof RakNetPacket){ }elseif($packet instanceof RakNetPacket){
$CID = $packet->ip . ":" . $packet->port; $CID = $packet->ip . ":" . $packet->port;
if(isset(Player::$list[$CID])){ if(isset($this->players[$CID])){
Player::$list[$CID]->handlePacket($packet); $this->players[$CID]->handlePacket($packet);
}else{ }else{
switch($packet->pid()){ switch($packet->pid()){
case RakNetInfo::UNCONNECTED_PING: case RakNetInfo::UNCONNECTED_PING:
@ -962,7 +1189,7 @@ class Server{
$pk = new RakNetPacket(RakNetInfo::UNCONNECTED_PONG); $pk = new RakNetPacket(RakNetInfo::UNCONNECTED_PONG);
$pk->pingID = $packet->pingID; $pk->pingID = $packet->pingID;
$pk->serverID = $this->serverID; $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->ip = $packet->ip;
$pk->port = $packet->port; $pk->port = $packet->port;
$this->sendPacket($pk); $this->sendPacket($pk);
@ -985,7 +1212,7 @@ class Server{
} }
break; break;
case RakNetInfo::OPEN_CONNECTION_REQUEST_2: 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 = new RakNetPacket(RakNetInfo::OPEN_CONNECTION_REPLY_2);
$pk->serverID = $this->serverID; $pk->serverID = $this->serverID;
$pk->serverPort = $this->getPort(); $pk->serverPort = $this->getPort();
@ -1068,7 +1295,7 @@ class Server{
"version" => VERSION, "version" => VERSION,
"mc_version" => MINECRAFT_VERSION, "mc_version" => MINECRAFT_VERSION,
"protocol" => Info::CURRENT_PROTOCOL, "protocol" => Info::CURRENT_PROTOCOL,
"online" => count(Player::$list), "online" => count($this->players),
"max" => $this->server->maxClients, "max" => $this->server->maxClients,
"plugins" => $plist, "plugins" => $plist,
), ),
@ -1077,7 +1304,7 @@ class Server{
public function titleTick(){ public function titleTick(){
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and \pocketmine\ANSI === true){ 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";
} }
} }

View File

@ -25,10 +25,13 @@ use pocketmine\command\defaults\BanCommand;
use pocketmine\command\defaults\BanIpCommand; use pocketmine\command\defaults\BanIpCommand;
use pocketmine\command\defaults\BanListCommand; use pocketmine\command\defaults\BanListCommand;
use pocketmine\command\defaults\DefaultGamemodeCommand; use pocketmine\command\defaults\DefaultGamemodeCommand;
use pocketmine\command\defaults\DeopCommand;
use pocketmine\command\defaults\DifficultyCommand; use pocketmine\command\defaults\DifficultyCommand;
use pocketmine\command\defaults\HelpCommand; use pocketmine\command\defaults\HelpCommand;
use pocketmine\command\defaults\KickCommand;
use pocketmine\command\defaults\ListCommand; use pocketmine\command\defaults\ListCommand;
use pocketmine\command\defaults\MeCommand; use pocketmine\command\defaults\MeCommand;
use pocketmine\command\defaults\OpCommand;
use pocketmine\command\defaults\PardonCommand; use pocketmine\command\defaults\PardonCommand;
use pocketmine\command\defaults\PardonIpCommand; use pocketmine\command\defaults\PardonIpCommand;
use pocketmine\command\defaults\PluginsCommand; use pocketmine\command\defaults\PluginsCommand;
@ -72,6 +75,9 @@ class SimpleCommandMap implements CommandMap{
$this->register("pocketmine", new MeCommand("me")); $this->register("pocketmine", new MeCommand("me"));
$this->register("pocketmine", new ListCommand("list")); $this->register("pocketmine", new ListCommand("list"));
$this->register("pocketmine", new DifficultyCommand("difficulty")); $this->register("pocketmine", new DifficultyCommand("difficulty"));
$this->register("pocketmine", new KickCommand("kick"));
$this->register("pocketmine", new OpCommand("op"));
$this->register("pocketmine", new DeopCommand("deop"));
} }

View File

@ -54,7 +54,7 @@ class BanCommand extends VanillaCommand{
Server::getInstance()->getNameBans()->addBan($name, $reason, null, $sender->getName()); 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."); $player->kick("Banned by admin.");
} }

View File

@ -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)){ 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); $this->processIPBan($value, $sender, $reason);
}else{ }else{
if(($player = Player::get($value, true)) instanceof Player){ if(($player = Server::getInstance()->getPlayer($value)) instanceof Player){
$this->processIPBan($player->getAddress(), $sender, $reason); $this->processIPBan($player->getAddress(), $sender, $reason);
}else{ }else{
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
@ -70,7 +70,7 @@ class BanIpCommand extends VanillaCommand{
private function processIPBan($ip, CommandSender $sender, $reason){ private function processIPBan($ip, CommandSender $sender, $reason){
Server::getInstance()->getIPBans()->addBan($ip, $reason, null, $sender->getName()); Server::getInstance()->getIPBans()->addBan($ip, $reason, null, $sender->getName());
foreach(Player::getAll() as $player){ foreach(Server::getInstance()->getOnlinePlayers() as $player){
if($player->getAddress() === $ip){ if($player->getAddress() === $ip){
$player->kick("You have been IP banned."); $player->kick("You have been IP banned.");
} }

View File

@ -0,0 +1,63 @@
<?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/
*
*
*/
namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
class DeopCommand extends VanillaCommand{
public function __construct($name){
parent::__construct(
$name,
"Takes the specified player's operator status",
"/deop <player>"
);
$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;
}
}

View File

@ -0,0 +1,69 @@
<?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/
*
*
*/
namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
class KickCommand extends VanillaCommand{
public function __construct($name){
parent::__construct(
$name,
"Removes the specified player from the server",
"/kick <player> [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;
}
}

View File

@ -45,13 +45,13 @@ class ListCommand extends VanillaCommand{
$online = ""; $online = "";
foreach(Player::getAll() as $player){ foreach(Server::getInstance()->getOnlinePlayers() as $player){
if($player->isOnline() and (!($sender instanceof Player) or $sender->canSee($player))){ if($player->isOnline() and (!($sender instanceof Player) or $sender->canSee($player))){
$online .= $player->getDisplayName() . ", "; $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; return true;
} }

View File

@ -0,0 +1,63 @@
<?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/
*
*
*/
namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
class OpCommand extends VanillaCommand{
public function __construct($name){
parent::__construct(
$name,
"Gives the specified player operator status",
"/op <player>"
);
$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;
}
}

View File

@ -35,7 +35,7 @@ class SayCommand extends VanillaCommand{
"Broadcasts the given message as the sender", "Broadcasts the given message as the sender",
"/say <message...>" "/say <message...>"
); );
$this->setPermission("pocketmine.command.seed"); $this->setPermission("pocketmine.command.say");
} }
public function execute(CommandSender $sender, $currentAlias, array $args){ public function execute(CommandSender $sender, $currentAlias, array $args){

View File

@ -46,7 +46,7 @@ class StopCommand extends VanillaCommand{
$reason = implode(" ", $args); $reason = implode(" ", $args);
if($reason !== ""){ if($reason !== ""){
foreach(Player::getAll() as $player){ foreach(Server::getInstance()->getOnlinePlayers() as $player){
$player->kick($reason); $player->kick($reason);
} }
} }

View File

@ -23,6 +23,7 @@ namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender; use pocketmine\command\CommandSender;
use pocketmine\Player; use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat; use pocketmine\utils\TextFormat;
class TellCommand extends VanillaCommand{ class TellCommand extends VanillaCommand{
@ -50,7 +51,7 @@ class TellCommand extends VanillaCommand{
$name = strtolower(array_shift($args)); $name = strtolower(array_shift($args));
$player = Player::get($name, true, false); $player = Server::getInstance()->getPlayer($name);
if($player instanceof Player){ if($player instanceof Player){
$sender->sendMessage("[me -> " . $player->getName() . "] " . implode($args)); $sender->sendMessage("[me -> " . $player->getName() . "] " . implode($args));

View File

@ -47,7 +47,7 @@ class PlayerChatEvent extends PlayerEvent implements Cancellable{
$this->message = $message; $this->message = $message;
$this->format = $format; $this->format = $format;
if($recipients === null){ if($recipients === null){
$this->recipients = Server::getInstance()->getPluginManager()->getPermissionSubscriptions(Player::BROADCAST_CHANNEL_USERS); $this->recipients = Server::getInstance()->getPluginManager()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_USERS);
}else{ }else{
$this->recipients = $recipients; $this->recipients = $recipients;
} }

View File

@ -75,7 +75,7 @@ class QueryHandler{
"server_engine" => $this->server->getName() . " " . $this->server->getPocketMineVersion(), "server_engine" => $this->server->getName() . " " . $this->server->getPocketMineVersion(),
"plugins" => $plist, "plugins" => $plist,
"map" => Level::getDefault()->getName(), "map" => Level::getDefault()->getName(),
"numplayers" => count(Player::$list), "numplayers" => count($this->server->getOnlinePlayers()),
"maxplayers" => $this->server->getMaxPlayers(), "maxplayers" => $this->server->getMaxPlayers(),
"whitelist" => $this->server->hasWhitelist() === true ? "on" : "off", "whitelist" => $this->server->hasWhitelist() === true ? "on" : "off",
"hostport" => $this->server->getPort() "hostport" => $this->server->getPort()
@ -84,7 +84,7 @@ class QueryHandler{
$str .= $key . "\x00" . $value . "\x00"; $str .= $key . "\x00" . $value . "\x00";
} }
$str .= "\x00\x01player_\x00\x00"; $str .= "\x00\x01player_\x00\x00";
foreach(Player::$list as $player){ foreach($this->server->getOnlinePlayers() as $player){
if($player->getName() != ""){ if($player->getName() != ""){
$str .= $player->getName() . "\x00"; $str .= $player->getName() . "\x00";
} }
@ -132,7 +132,7 @@ class QueryHandler{
} }
$pk->payload = $this->longData; $pk->payload = $this->longData;
}else{ }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(); $pk->encode();
$this->server->sendPacket($pk); $this->server->sendPacket($pk);