Added Entity level switch, global Player static container

This commit is contained in:
Shoghi Cervantes 2014-03-01 14:05:45 +01:00
parent 914098310c
commit 648b02bc79
19 changed files with 425 additions and 318 deletions

View File

@ -133,7 +133,7 @@ class BanAPI{
switch($cmd){
case "sudo":
$target = strtolower(array_shift($params));
$player = $this->server->api->player->get($target);
$player = Player::get($target);
if(!($player instanceof Player)){
$output .= "Player not connected.\n";
break;
@ -147,7 +147,7 @@ class BanAPI{
$output .= "Usage: /op <player>\n";
break;
}
$player = $this->server->api->player->get($user);
$player = Player::get($user);
if(!($player instanceof Player)){
$this->ops->set($user);
$this->ops->save();
@ -161,7 +161,7 @@ class BanAPI{
break;
case "deop":
$user = strtolower($params[0]);
$player = $this->server->api->player->get($user);
$player = Player::get($user);
if(!($player instanceof Player)){
$this->ops->remove($user);
$this->ops->save();
@ -178,7 +178,7 @@ class BanAPI{
$output .= "Usage: /kick <player> [reason ...]\n";
}else{
$name = strtolower(array_shift($params));
$player = $this->server->api->player->get($name);
$player = Player::get($name);
if($player === false){
$output .= "Player \"".$name."\" does not exist\n";
}else{
@ -246,7 +246,7 @@ class BanAPI{
case "add":
case "ban":
$ip = strtolower($params[0]);
$player = $this->server->api->player->get($ip);
$player = Player::get($ip);
if($player instanceof Player){
$ip = $player->ip;
$player->close("banned");
@ -281,7 +281,7 @@ class BanAPI{
$user = strtolower($params[0]);
$this->banned->set($user);
$this->banned->save();
$player = $this->server->api->player->get($user);
$player = Player::get($user);
if($player !== false){
$player->close("You have been banned");
}

View File

@ -287,7 +287,7 @@ class BlockAPI{
$output .= "Usage: /give <player> <item[:damage]> [amount]\n";
break;
}
$player = $this->server->api->player->get($params[0]);
$player = Player::get($params[0]);
$item = BlockAPI::fromString($params[1]);
if(!isset($params[2])){

View File

@ -77,7 +77,7 @@ class ChatAPI{
$sender = $issuer->username;
}
$n = array_shift($params);
$target = $this->server->api->player->get($n);
$target = Player::get($n);
if($target instanceof Player){
$target = $target->username;
}else{

View File

@ -209,7 +209,7 @@ class ConsoleAPI{
if($issuer instanceof Player){
if($this->server->api->ban->isOp($issuer->username)){
$output = "";
foreach($this->server->api->player->getAll() as $p){
foreach(Player::getAll() as $p){
$output .= $this->run($cmd . " ". substr_replace($params, $p->username, $selector[1] + $offsetshift - 1, strlen($selector[0]) + 1), $issuer, $alias);
}
}else{
@ -217,7 +217,7 @@ class ConsoleAPI{
}
}else{
$output = "";
foreach($this->server->api->player->getAll() as $p){
foreach(Player::getAll() as $p){
$output .= $this->run($cmd . " ". substr_replace($params, $p->username, $selector[1] + $offsetshift - 1, strlen($selector[0]) + 1), $issuer, $alias);
}
}
@ -225,7 +225,7 @@ class ConsoleAPI{
case "r":
case "random":
$l = array();
foreach($this->server->api->player->getAll() as $p){
foreach(Player::getAll() as $p){
if($p !== $issuer){
$l[] = $p;
}

View File

@ -125,7 +125,7 @@ class LevelAPI{
console("[INFO] Unloading level \"".$name."\"");
$level->nextSave = PHP_INT_MAX;
$level->save();
foreach($this->server->api->player->getAll($level) as $player){
foreach($level->getPlayers() as $player){
$player->teleport($this->server->spawn);
}
/*foreach($this->server->api->entity->getAll($level) as $entity){

View File

@ -132,7 +132,7 @@ class PlayerAPI{
if(count($params) === 3 and substr($tg, 0, 2) === "w:"){
$target = $this->server->api->level->get(substr($tg, 2));
}else{
$target = $this->server->api->player->get($tg);
$target = Player::get($tg);
}
}else{
$target = $issuer;
@ -196,18 +196,18 @@ class PlayerAPI{
"v" => VIEW,
);
if(isset($params[1])){
if($this->server->api->player->get($params[1]) instanceof Player){
$player = $this->server->api->player->get($params[1]);
if(Player::get($params[1]) instanceof Player){
$player = Player::get($params[1]);
$setgm = $params[0];
}elseif($this->server->api->player->get($params[0]) instanceof Player){
$player = $this->server->api->player->get($params[0]);
}elseif(Player::get($params[0]) instanceof Player){
$player = Player::get($params[0]);
$setgm = $params[1];
}else{
$output .= "Usage: /$cmd <mode> [player] or /$cmd [player] <mode>\n";
break;
}
}elseif(isset($params[0])){
if(!($this->server->api->player->get($params[0]) instanceof Player)){
if(!(Player::get($params[0]) instanceof Player)){
if($issuer instanceof Player){
$setgm = $params[0];
$player = $issuer;
@ -277,11 +277,11 @@ class PlayerAPI{
}
break;
case "list":
$output .= "There are ".count($this->server->clients)."/".$this->server->maxClients." players online:\n";
if(count($this->server->clients) == 0){
$output .= "There are ".count(Player::$list)."/".$this->server->maxClients." players online:\n";
if(count(Player::$list) == 0){
break;
}
foreach($this->server->clients as $c){
foreach(Player::$list as $c){
$output .= $c->username.", ";
}
$output = substr($output, 0, -2)."\n";
@ -328,72 +328,15 @@ class PlayerAPI{
return false;
}
public function get($name, $alike = true, $multiple = false){
$name = trim(strtolower($name));
if($name === ""){
return false;
}
$query = $this->server->query("SELECT ip,port,name FROM players WHERE name ".($alike === true ? "LIKE '%".$name."%'":"= '".$name."'").";");
$players = array();
if($query !== false and $query !== true){
while(($d = $query->fetchArray(SQLITE3_ASSOC)) !== false){
$CID = MainServer::clientID($d["ip"], $d["port"]);
if(isset($this->server->clients[$CID])){
$players[$CID] = $this->server->clients[$CID];
if($multiple === false and $d["name"] === $name){
return $players[$CID];
}
}
}
}
if($multiple === false){
if(count($players) > 0){
return array_shift($players);
}else{
return false;
}
}else{
return $players;
}
}
public function getAll($level = null){
if($level instanceof Level){
$clients = array();
$l = $this->server->query("SELECT EID FROM entities WHERE level = '".$level->getName()."' AND class = '".ENTITY_PLAYER."';");
if($l !== false and $l !== true){
while(($e = $l->fetchArray(SQLITE3_ASSOC)) !== false){
$e = $this->getByEID($e["EID"]);
if($e instanceof Player){
$clients[$e->CID] = $e;
}
}
}
return $clients;
}
return $this->server->clients;
}
public function broadcastPacket(array $players, RakNetDataPacket $packet){
foreach($players as $p){
$p->dataPacket(clone $packet);
}
}
public function getByEID($eid){
$eid = (int) $eid;
$CID = $this->server->query("SELECT ip,port FROM players WHERE EID = '".$eid."';", true);
$CID = MainServer::clientID($CID["ip"], $CID["port"]);
if(isset($this->server->clients[$CID])){
return $this->server->clients[$CID];
}
return false;
}
public function online(){
$o = array();
foreach($this->server->clients as $p){
foreach(Player::$list as $p){
if($p->auth === true){
$o[] = $p->username;
}
@ -401,9 +344,10 @@ class PlayerAPI{
return $o;
}
//TODO (remove)
public function add($CID){
if(isset($this->server->clients[$CID])){
$player = $this->server->clients[$CID];
if(isset(Player::$list[$CID])){
$player =Player::$list[$CID];
$player->data = $this->getOffline($player->username);
$player->gamemode = $player->data->get("gamemode");
if(($player->level = $this->server->api->level->get($player->data->get("position")["level"])) === false){
@ -415,43 +359,6 @@ class PlayerAPI{
"z" => $player->level->getSpawn()->z,
));
}
$this->server->query("INSERT OR REPLACE INTO players (CID, ip, port, name) VALUES (".$player->CID.", '".$player->ip."', ".$player->port.", '".strtolower($player->username)."');");
}
}
public function spawnAllPlayers(Player $player){
foreach($this->getAll() as $p){
if($p !== $player and ($p->entity instanceof Entity)){
$p->entity->spawnTo($player);
if($p->level !== $player->level){
$pk = new MoveEntityPacket_PosRot;
$pk->eid = $p->entity->eid;
$pk->x = -256;
$pk->y = 128;
$pk->z = -256;
$pk->yaw = 0;
$pk->pitch = 0;
$player->dataPacket($pk);
}
}
}
}
public function spawnToAllPlayers(Player $player){
foreach($this->getAll() as $p){
if($p !== $player and ($p->entity instanceof Entity) and ($player->entity instanceof Entity)){
$player->entity->spawnTo($p);
if($p->level !== $player->level){
$pk = new MoveEntityPacket_PosRot;
$pk->eid = $player->entity->eid;
$pk->x = -256;
$pk->y = 128;
$pk->z = -256;
$pk->yaw = 0;
$pk->pitch = 0;
$p->dataPacket($pk);
}
}
}
}

View File

@ -271,7 +271,7 @@ class ServerAPI{
"version" => MAJOR_VERSION,
"mc_version" => CURRENT_MINECRAFT_VERSION,
"protocol" => ProtocolInfo::CURRENT_PROTOCOL,
"online" => count($this->server->clients),
"online" => count(Player::$list),
"max" => $this->server->maxClients,
"plugins" => $plist,
),

View File

@ -29,27 +29,36 @@ abstract class Entity extends Position{
//public $vehicle = null;
public $chunkIndex;
public $lastX;
public $lastY;
public $lastZ;
public $velocity;
public $motionX;
public $motionY;
public $motionZ;
public $yaw;
public $pitch;
public $lastYaw;
public $lastPitch;
public $boundingBox;
public $onGround;
public $positionChanged;
public $velocityChanged;
public $motionChanged;
public $dead;
public $height;
public $width;
public $length;
public $fallDistance;
public $ticksLived;
public $lastUpdate;
public $maxFireTicks;
public $fireTicks;
public $airTicks;
public $namedtag;
protected $inWater;
@ -65,7 +74,7 @@ abstract class Entity extends Position{
}
public static function getAll(){
return $this->list;
return Entity::$list;
}
@ -92,12 +101,31 @@ abstract class Entity extends Position{
$this->namedtag->Pos[0] = $this->x;
$this->namedtag->Pos[1] = $this->y;
$this->namedtag->Pos[2] = $this->z;
$this->namedtag->Motion[0] = $this->motionX;
$this->namedtag->Motion[1] = $this->motionY;
$this->namedtag->Motion[2] = $this->motionZ;
$this->namedtag->Rotation[0] = $this->yaw;
$this->namedtag->Rotation[1] = $this->pitch;
$this->namedtag->FallDistance = $this->fallDistance;
$this->namedtag->Fire = $this->fireTicks;
$this->namedtag->Air = $this->airTicks;
$this->namedtag->OnGround = $this->onGround == true ? 1:0;
$this->namedtag->Invulnerable = $this->invulnerable == true ? 1:0;
}
protected abstract function initEntity();
public abstract function spawnTo(Player $player);
public function despawnFrom(Player $player){
$pk = new RemoveEntityPacket;
$pk->eid = $this->id;
$player->dataPacket($pk);
}
abstract function attack($damage, $source = "generic");
abstract function heal($amount, $source = "generic");
@ -209,34 +237,91 @@ abstract class Entity extends Position{
}
public function setPositionAndRotation(Vector3 $pos, $yaw, $pitch){ //TODO
$this->x = $pos->x;
$this->y = $pos->y;
$this->z = $pos->z;
$this->yaw = $yaw;
$this->pitch = $pitch;
if($this->setPosition($pos) === true){
$this->yaw = $yaw;
$this->pitch = $pitch;
return true;
}
return false;
}
public function onCollideWithPlayer(EntityPlayer $entityPlayer){
}
protected function switchLevel(Level $targetLevel){
if($this->level instanceof Level){
if(EventHandler::callEvent(new EntityLevelChangeEvent($this, $this->level, $targetLevel)) === BaseEvent::DENY){
return false;
}
unset($this->level->entities[$this->id]);
unset($this->level->chunkEntities[$this->chunkIndex][$this->id]);
$this->despawnFromAll();
if($this instanceof Player){
foreach($this->chunksLoaded as $index => $boolean){
$X = null;
$Z = null;
PMFLevel::getXZ($index, $X, $Z);
foreach($this->level->getChunkEntities($X, $Z) as $entity){
$entity->despawnFrom($this);
}
}
$this->level->freeAllChunks($this);
}
}
$this->level = $targetLevel;
$this->level->entities[$this->id] = $this;
if($this instanceof Player){
$this->chunksLoaded = array();
$pk = new SetTimePacket;
$pk->time = $this->level->getTime();
$this->dataPacket($pk);
}
$this->spawnToAll();
$this->chunkIndex = false;
}
public function getPosition(){
return new Position($this->x, $this->y, $this->z, $this->level);
}
public function setPosition(Vector3 $pos){
if($pos instanceof Position and $pos->level instanceof Level and $pos->level !== $this->level){
if($this->switchLevel($pos->level) === false){
return false;
}
}
if(EventHandler::callEvent(new EntityMoveEvent($this, $pos)) === BaseEvent::DENY){
return false;
}
$this->x = $pos->x;
$this->y = $pos->y;
$this->z = $pos->z;
$radius = $this->width / 2;
if(($index = PMFLevel::getIndex($this->x >> 4, $this->z >> 4)) !== $this->chunkIndex){
if($this->chunkIndex !== false){
unset($this->level->chunkEntities[$this->chunkIndex][$this->id]);
}
$this->chunkIndex = $index;
$this->level->loadChunk($this->x >> 4, $this->z >> 4);
$this->level->chunkEntities[$this->chunkIndex][$this->id] = $this;
}
$this->boundingBox->setBounds($pos->x - $radius, $pos->y, $pos->z - $radius, $pos->x + $radius, $pos->y + $this->height, $pos->z + $radius);
return true;
}
public function setVelocity(Vector3 $velocity){
$this->velocity = clone $velocity;
public function getMotion(){
return new Vector3($this->motionX, $this->motionY, $this->motionZ);
}
public function getVelocity(){
return clone $this->velocity;
public function setMotion(Vector3 $motion){
if(EventHandler::callEvent(new EntityMotionEvent($this, $motion)) === BaseEvent::DENY){
return false;
}
$this->motionX = $motion->x;
$this->motionY = $motion->y;
$this->motionZ = $motion->z;
}
public function isOnGround(){
@ -251,10 +336,31 @@ abstract class Entity extends Position{
return $this->level;
}
public function teleport(Position $pos){
public function teleport(Position $pos, $yaw = false, $pitch = false){
$this->setMotion(new Vector3(0, 0, 0));
if($this->setPositionAndRotation($pos, $yaw === false ? $this->yaw : $yaw, $pitch === false ? $this->pitch : $pitch) !== false){
if($this instanceof Player){
$this->airTicks = 300;
$this->fallDistance = 0;
$this->orderChunks();
$this->getNextChunk(true);
$this->forceMovement = $pos;
$pk = new MovePlayerPacket;
$pk->eid = 0;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->bodyYaw = $this->yaw;
$pk->pitch = $this->pitch;
$pk->yaw = $this->yaw;
$this->dataPacket($pk);
}
return true;
}
return false;
}
public function getID(){
return $this->id;
}
@ -267,23 +373,22 @@ abstract class Entity extends Position{
}
}
public function despawnFromAll(){
foreach($this->level->getPlayers() as $player){
if($player->eid !== false or $player->spawned !== true){
$this->despawnFrom($player);
}
}
}
public function close(){
if($this->closed === false){
$this->closed = true;
unset(Entity::$needUpdate[$this->id]);
unset($this->level->entities[$this->id]);
unset($this->level->entities[$this->id]);
unset($this->level->chunkEntities[$this->chunkIndex][$this->id]);
unset(Entity::$list[$this->id]);
if($this instanceof HumanEntity){
$pk = new RemovePlayerPacket;
$pk->eid = $this->id;
$pk->clientID = 0;
$this->server->api->player->broadcastPacket($this->level->getPlayers(), $pk);
}else{
$pk = new RemoveEntityPacket;
$pk->eid = $this->id;
$this->server->api->player->broadcastPacket($this->level->getPlayers(), $pk);
}
$this->despawnFromAll();
$this->server->api->dhandle("entity.remove", $this);
}
}

View File

@ -577,7 +577,7 @@ class EntityOLD extends Position{
}
}else{
$this->updateLast();
$players = $this->server->api->player->getAll($this->level);
$players = $this->level->getPlayers();
if($this->player instanceof Player){
unset($players[$this->player->CID]);
$pk = new MovePlayerPacket;
@ -659,7 +659,7 @@ class EntityOLD extends Position{
public function spawn($player){
if(!($player instanceof Player)){
$player = $this->server->api->player->get($player);
$player = Player::get($player);
}
if($player->eid === $this->eid or $this->closed !== false or ($player->level !== $this->level and $this->class !== ENTITY_PLAYER)){
return false;

View File

@ -21,7 +21,7 @@
class MainServer{
public $tCnt;
public $serverID, $interface, $database, $version, $invisible, $tickMeasure, $preparedSQL, $spawn, $whitelist, $seed, $stop, $gamemode, $difficulty, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $port, $saveEnabled;
public $serverID, $interface, $database, $version, $invisible, $tickMeasure, $preparedSQL, $spawn, $whitelist, $seed, $stop, $gamemode, $difficulty, $name, $maxClients, $eidCnt, $custom, $description, $motd, $port, $saveEnabled;
private $serverip, $evCnt, $handCnt, $events, $eventsID, $handlers, $serverType, $lastTick, $doTick, $ticks, $memoryStats, $schedule, $asyncThread, $async = array(), $asyncID = 0;
/**
@ -55,7 +55,6 @@ class MainServer{
$this->scheduleCnt = 1;
$this->description = "";
$this->memoryStats = array();
$this->clients = array();
$this->spawn = false;
$this->saveEnabled = true;
$this->whitelist = false;
@ -93,7 +92,7 @@ class MainServer{
public function titleTick(){
$time = microtime(true);
if(defined("DEBUG") and DEBUG >= 0 and ENABLE_ANSI === true){
echo "\x1b]0;PocketMine-MP ".MAJOR_VERSION." | Online ". count($this->clients)."/".$this->maxClients." | RAM ".round((memory_get_usage() / 1024) / 1024, 2)."MB | U ".round(($this->interface->bandwidth[1] / max(1, $time - $this->interface->bandwidth[2])) / 1024, 2)." D ".round(($this->interface->bandwidth[0] / max(1, $time - $this->interface->bandwidth[2])) / 1024, 2)." kB/s | TPS ".$this->getTPS()."\x07";
echo "\x1b]0;PocketMine-MP ".MAJOR_VERSION." | Online ". count(Player::$list)."/".$this->maxClients." | RAM ".round((memory_get_usage() / 1024) / 1024, 2)."MB | U ".round(($this->interface->bandwidth[1] / max(1, $time - $this->interface->bandwidth[2])) / 1024, 2)." D ".round(($this->interface->bandwidth[0] / max(1, $time - $this->interface->bandwidth[2])) / 1024, 2)." kB/s | TPS ".$this->getTPS()."\x07";
}
$this->interface->bandwidth = array(0, 0, $time);
}
@ -492,12 +491,9 @@ class MainServer{
public function packetHandler(Packet $packet){
$data =& $packet;
$CID = MainServer::clientID($packet->ip, $packet->port);
if(isset($this->clients[$CID])){
$this->clients[$CID]->handlePacket($packet);
if(isset(Player::$list[$CID])){
Player::$list[$CID]->handlePacket($packet);
}else{
if($this->handle("server.noauthpacket.".$packet->pid(), $packet) === false){
return;
}
switch($packet->pid()){
case RakNetInfo::UNCONNECTED_PING:
case RakNetInfo::UNCONNECTED_PING_OPEN_CONNECTIONS:
@ -523,7 +519,7 @@ class MainServer{
$pk = new RakNetPacket(RakNetInfo::UNCONNECTED_PONG);
$pk->pingID = $packet->pingID;
$pk->serverID = $this->serverID;
$pk->serverType = $this->serverType . $this->name . " [".count($this->clients)."/".$this->maxClients."] ".$txt;
$pk->serverType = $this->serverType . $this->name . " [".count(Player::$list)."/".$this->maxClients."] ".$txt;
$pk->ip = $packet->ip;
$pk->port = $packet->port;
$this->send($pk);
@ -551,7 +547,7 @@ class MainServer{
break;
}
$this->clients[$CID] = new Player($packet->clientID, $packet->ip, $packet->port, $packet->mtuSize); //New Session!
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->port = $this->port;

View File

@ -24,6 +24,8 @@ require_once("Entity.php");
/***REM_END***/
class Player extends PlayerEntity{
public static $list = array();
private $recoveryQueue = array();
private $receiveQueue = array();
private $resendQueue = array();
@ -33,18 +35,18 @@ class Player extends PlayerEntity{
private $bufferLen = 0;
private $nextBuffer = 0;
private $evid = array();
private $lastMovement = 0;
private $forceMovement = false;
protected $lastMovement = 0;
protected $forceMovement = false;
private $timeout;
private $connected = true;
private $clientID;
private $ip;
private $port;
protected $connected = true;
protected $clientID;
protected $ip;
protected $port;
private $counter = array(0, 0, 0, 0);
private $username;
private $iusername;
private $startAction = false;
private $isSleeping = false;
protected $isSleeping = false;
public $auth = false;
public $CID;
public $MTU;
@ -71,6 +73,7 @@ class Player extends PlayerEntity{
private $spawnPosition;
private $packetLoss = 0;
private $lastChunk = false;
private $hunkScheduled = 0;
public $lastCorrect;
private $bigCnt;
private $packetStats;
@ -87,6 +90,35 @@ class Player extends PlayerEntity{
}
return null;
}
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;
}
}
public static function getAll(){
return Player::$list;
}
/**
* @param integer $clientID
@ -101,6 +133,7 @@ class Player extends PlayerEntity{
$this->lastBreak = microtime(true);
$this->clientID = $clientID;
$this->CID = MainServer::clientID($ip, $port);
Player::$list[$this->CID] = $this;
$this->ip = $ip;
$this->port = $port;
$this->spawnPosition = $this->server->spawn;
@ -177,14 +210,24 @@ class Player extends PlayerEntity{
}
}
public function getNextChunk(){
public function getNextChunk($force = false, $ev = null){
if($this->connected === false){
return false;
}
if($ev === "server.schedule"){
--$this->chunkScheduled;
if($this->chunkScheduled < 0){
$this->chunkScheduled = 0;
}
}
foreach($this->chunkCount as $count => $t){
if(isset($this->recoveryQueue[$count]) or isset($this->resendQueue[$count])){
$this->server->schedule(MAX_CHUNK_RATE, array($this, "getNextChunk"));
if($this->chunkScheduled === 0){
$this->server->schedule(MAX_CHUNK_RATE, array($this, "getNextChunk"));
++$this->chunkScheduled;
}
return;
}else{
unset($this->chunkCount[$count]);
@ -203,7 +246,9 @@ class Player extends PlayerEntity{
$c = key($this->chunksOrder);
$d = @$this->chunksOrder[$c];
if($c === null or $d === null){
$this->server->schedule(40, array($this, "getNextChunk"));
if($this->chunkScheduled === 0){
$this->server->schedule(40, array($this, "getNextChunk"));
}
return false;
}
unset($this->chunksOrder[$c]);
@ -236,7 +281,10 @@ class Player extends PlayerEntity{
$this->lastChunk = array($X, $Z);
$this->server->schedule(MAX_CHUNK_RATE, array($this, "getNextChunk"));
if($this->chunkScheduled === 0 or $force === true){
$this->server->schedule(MAX_CHUNK_RATE, array($this, "getNextChunk"));
++$this->chunkScheduled;
}
}
public function save(){
@ -296,6 +344,7 @@ class Player extends PlayerEntity{
$this->sendChat("You have been kicked. Reason: ".$reason."\n");
$this->sendBuffer();
$this->directDataPacket(new DisconnectPacket);
unset(Player::$list[$this->CID]);
$this->connected = false;
$this->level->freeAllChunks($this);
$this->loggedIn = false;
@ -305,7 +354,6 @@ class Player extends PlayerEntity{
$this->receiveQueue = array();
$this->resendQueue = array();
$this->ackQueue = array();
unset($this->server->clients[$this->CID]);
if($this->username != "" and ($this->data instanceof Config)){
//TODO
//$this->saveOffline($player->data);
@ -333,7 +381,7 @@ class Player extends PlayerEntity{
* @return boolean
*/
public function sleepOn(Vector3 $pos){
foreach($this->server->api->player->getAll($this->level) as $p){
foreach($this->level->getPlayers() as $p){
if($p->isSleeping instanceof Vector3){
if($pos->distance($p->isSleeping) <= 0.1){
return false;
@ -341,7 +389,7 @@ class Player extends PlayerEntity{
}
}
$this->isSleeping = $pos;
$this->teleport(new Position($pos->x + 0.5, $pos->y + 1, $pos->z + 0.5, $this->level), false, false, false, false);
$this->teleport(new Position($pos->x + 0.5, $pos->y + 1, $pos->z + 0.5, $this->level));
if($this->entity instanceof Entity){
$this->entity->updateMetadata();
}
@ -360,13 +408,13 @@ class Player extends PlayerEntity{
public function checkSleep(){
if($this->isSleeping !== false){
if($this->server->api->time->getPhase($this->level) === "night"){
foreach($this->server->api->player->getAll($this->level) as $p){
foreach($this->level->getPlayers() as $p){
if($p->isSleeping === false){
return false;
}
}
$this->server->api->time->set("day", $this->level);
foreach($this->server->api->player->getAll($this->level) as $p){
foreach($this->level->getPlayers() as $p){
$p->stopSleep();
}
}
@ -899,121 +947,6 @@ class Player extends PlayerEntity{
*
* @return boolean
*/
public function teleport(Vector3 $pos, $yaw = false, $pitch = false, $terrain = true, $force = true){
if($this->level instanceof Level){
if($yaw === false){
$yaw = $this->yaw;
}
if($pitch === false){
$pitch = $this->pitch;
}
if($this->server->api->dhandle("player.teleport", array("player" => $this, "target" => $pos)) === false){
return false;
}
/*if($pos instanceof Position and $pos->level instanceof Level and $pos->level !== $this->level){
if($this->server->api->dhandle("player.teleport.level", array("player" => $this, "origin" => $this->level, "target" => $pos->level)) === false){
return false;
}
foreach($this->level->getEntities() as $e){
if($e !== $this->entity){
if($e->player instanceof Player){
$pk = new MoveEntityPacket_PosRot;
$pk->eid = $this->entity->eid;
$pk->x = -256;
$pk->y = 128;
$pk->z = -256;
$pk->yaw = 0;
$pk->pitch = 0;
$e->player->dataPacket($pk);
$pk = new MoveEntityPacket_PosRot;
$pk->eid = $e->eid;
$pk->x = -256;
$pk->y = 128;
$pk->z = -256;
$pk->yaw = 0;
$pk->pitch = 0;
$this->dataPacket($pk);
}else{
$pk = new RemoveEntityPacket;
$pk->eid = $e->eid;
$this->dataPacket($pk);
}
}
}
$this->level->freeAllChunks($this);
$this->level = $pos->level;
$this->chunksLoaded = array();
$this->entity->spawnToAll();
//TODO
$this->server->api->entity->spawnAll($this);
$pk = new SetTimePacket;
$pk->time = $this->level->getTime();
$this->dataPacket($pk);
$terrain = true;
foreach($this->level->getPlayers() as $player){
if($player !== $this and $player->entity instanceof Entity){
$pk = new MoveEntityPacket_PosRot;
$pk->eid = $player->entity->eid;
$pk->x = $player->entity->x;
$pk->y = $player->entity->y;
$pk->z = $player->entity->z;
$pk->yaw = $player->entity->yaw;
$pk->pitch = $player->entity->pitch;
$this->dataPacket($pk);
$pk = new PlayerEquipmentPacket;
$pk->eid = $this->eid;
$pk->item = $this->getSlot($this->slot)->getID();
$pk->meta = $this->getSlot($this->slot)->getMetadata();
$pk->slot = 0;
$player->dataPacket($pk);
$this->sendArmor($player);
$pk = new PlayerEquipmentPacket;
$pk->eid = $player->eid;
$pk->item = $player->getSlot($player->slot)->getID();
$pk->meta = $player->getSlot($player->slot)->getMetadata();
$pk->slot = 0;
$this->dataPacket($pk);
$player->sendArmor($this);
}
}
}*/
$this->lastCorrect = $pos;
/*$this->entity->fallY = false;
$this->entity->fallStart = false;*/
$this->setPosition($pos, $yaw, $pitch);
/*$this->entity->resetSpeed();
$this->entity->updateLast();
$this->entity->calculateVelocity();*/
if($terrain === true){
$this->orderChunks();
$this->getNextChunk();
}
//$this->entity->check = true;
if($force === true){
$this->forceMovement = $pos;
}
}
$pk = new MovePlayerPacket;
$pk->eid = 0;
$pk->x = $pos->x;
$pk->y = $pos->y;
$pk->z = $pos->z;
$pk->bodyYaw = $yaw;
$pk->pitch = $pitch;
$pk->yaw = $yaw;
$this->dataPacket($pk);
}
public function getGamemode(){
switch($this->gamemode){
@ -1300,7 +1233,7 @@ class Player extends PlayerEntity{
$this->username = $packet->username;
$this->iusername = strtolower($this->username);
$this->loginData = array("clientId" => $packet->clientId, "loginData" => $packet->loginData);
if(count($this->server->clients) > $this->server->maxClients and !$this->server->api->ban->isOp($this->iusername)){
if(count(Player::$list) > $this->server->maxClients and !$this->server->api->ban->isOp($this->iusername)){
$this->close("server is full!", false);
return;
}
@ -1335,13 +1268,13 @@ class Player extends PlayerEntity{
}
$this->loggedIn = true;
$u = $this->server->api->player->get($this->iusername, false);
if($u !== false){
$u->close("logged in from another location");
}
if(!isset($this->CID) or $this->CID == null){
console("[DEBUG] Player ".$this->username." does not have a CID", true, true, 2);
$this->CID = Utils::readLong(Utils::getRandomBytes(8, false));
$u = Player::get($this->iusername, false, true);
if(count($u) > 0){
foreach($u as $p){
if($p !== $this){
$p->close("logged in from another location");
}
}
}
$this->server->api->player->add($this->CID);
@ -1423,9 +1356,26 @@ class Player extends PlayerEntity{
1 => new NBTTag_Double(1, $this->data->get("position")["y"]),
2 => new NBTTag_Double(2, $this->data->get("position")["z"])
)),
"NameTag" => new NBTTag_String("NameTag", $this->username),
"Motion" => new NBTTag_List("Motion", array(
0 => new NBTTag_Double(0, 0.0),
1 => new NBTTag_Double(1, 0.0),
2 => new NBTTag_Double(2, 0.0)
)),
"Rotation" => new NBTTag_List("Rotation", array(
0 => new NBTTag_Float(0, 0.0),
1 => new NBTTag_Float(1, 0.0)
)),
"FallDistance" => new NBTTag_Float("FallDistance", 0.0),
"Fire" => new NBTTag_Short("Fire", 0),
"Air" => new NBTTag_Short("Air", 0),
"OnGround" => new NBTTag_Byte("OnGround", 1),
"Invulnerable" => new NBTTag_Byte("Invulnerable", 0),
"NameTag" => new NBTTag_String("NameTag", $this->username),
)));
$this->namedtag->Pos->setTagType(NBTTag::TAG_Double);
$this->namedtag->Motion->setTagType(NBTTag::TAG_Double);
$this->namedtag->Rotation->setTagType(NBTTag::TAG_Float);
if(($level = $this->server->api->level->get($this->data->get("spawn")["level"])) !== false){
$this->spawnPosition = new Position($this->data->get("spawn")["x"], $this->data->get("spawn")["y"], $this->data->get("spawn")["z"], $level);
@ -1513,13 +1463,13 @@ class Player extends PlayerEntity{
if($packet->messageIndex > $this->lastMovement){
$this->lastMovement = $packet->messageIndex;
$newPos = new Vector3($packet->x, $packet->y, $packet->z);
/*if($this->forceMovement instanceof Vector3){
if($this->forceMovement instanceof Vector3){
if($this->forceMovement->distance($newPos) <= 0.7){
$this->forceMovement = false;
}else{
$this->teleport($this->forceMovement, $this->entity->yaw, $this->entity->pitch, false);
$this->setPosition($this->forceMovement);
}
}*/
}
/*$speed = $this->entity->getSpeedMeasure();
if($this->blocked === true or ($this->server->api->getProperty("allow-flight") !== true and (($speed > 9 and ($this->gamemode & 0x01) === 0x00) or $speed > 20 or $this->entity->distance($newPos) > 7)) or $this->server->api->handle("player.move", $this->entity) === false){
if($this->lastCorrect instanceof Vector3){
@ -1529,7 +1479,7 @@ class Player extends PlayerEntity{
console("[WARNING] ".$this->username." moved too quickly!");
}
}else{*/
$this->setPosition($newPos, $packet->yaw, $packet->pitch);
$this->setPositionAndRotation($newPos, $packet->yaw, $packet->pitch);
//}
}
break;
@ -2427,14 +2377,4 @@ class Player extends PlayerEntity{
return array();
}
/**
* @return string
*/
function __toString(){
if($this->username != ""){
return $this->username;
}
return $this->clientID;
}
}

View File

@ -27,6 +27,8 @@ class HumanEntity extends CreatureEntity implements ProjectileSourceEntity{
if(isset($this->namedtag->NameTag)){
$this->nameTag = $this->namedtag->NameTag;
}
$this->height = 1.8; //Or 1.62?
$this->width = 0.6;
}
public function spawnTo(Player $player){
@ -67,6 +69,13 @@ class HumanEntity extends CreatureEntity implements ProjectileSourceEntity{
$this->sendArmor($player);
}
public function despawnTo(Player $player){
$pk = new RemovePlayerPacket;
$pk->eid = $this->id;
$pk->clientID = 0;
$player->dataPacket($pk);
}
public function getMetadata(){
return array();
}

32
src/event/EntityEvent.php Normal file
View File

@ -0,0 +1,32 @@
<?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/
*
*
*/
abstract class EntityEvent extends BaseEvent{
protected $entity;
public function __construct(Entity $entity){
$this->entity = $entity;
}
public function getEntity(){
return $this->entity;
}
}

View File

@ -0,0 +1,42 @@
<?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/
*
*
*/
class EntityLevelChangeEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
private $originLevel;
private $targetLevel;
public function __construct(Entity $entity, Level $originLevel, Level $targetLevel){
$this->entity = $entity;
$this->originLevel = $originLevel;
$this->targetLevel = $targetLevel;
}
public function getOrigin(){
return $this->originLevel;
}
public function getTarget(){
return $this->targetLevel;
}
}

View File

@ -0,0 +1,38 @@
<?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/
*
*
*/
class EntityMotionEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
private $mot;
public function __construct(Entity $entity, Vector3 $mot){
$this->entity = $entity;
$this->mot = $mot;
}
public function getVector(){
return $this->mot;
}
}

View File

@ -0,0 +1,38 @@
<?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/
*
*
*/
class EntityMoveEvent extends EntityEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
private $pos;
public function __construct(Entity $entity, Vector3 $pos){
$this->entity = $entity;
$this->pos = $pos;
}
public function getVector(){
return $this->pos;
}
}

View File

@ -138,11 +138,11 @@ class NBT implements ArrayAccess{
}
public function getByte(){
return Utils::readByte($this->get(1), true);
return ord($this->get(1));
}
public function putByte($v){
$this->buffer .= Utils::writeByte($v);
$this->buffer .= chr($v);
}
public function getShort(){

View File

@ -69,7 +69,7 @@ class QueryHandler{
"server_engine" => "PocketMine-MP ".MAJOR_VERSION,
"plugins" => $plist,
"map" => $this->server->api->level->getDefault()->getName(),
"numplayers" => count($this->server->clients),
"numplayers" => count(Player::$list),
"maxplayers" => $this->server->maxClients,
"whitelist" => $this->server->api->getProperty("white-list") === true ? "on":"off",
"hostport" => $this->server->api->getProperty("server-port"),
@ -79,7 +79,7 @@ class QueryHandler{
$str .= $key."\x00".$value."\x00";
}
$str .= "\x00\x01player_\x00\x00";
foreach($this->server->clients as $player){
foreach(Player::$list as $player){
if($player->username != ""){
$str .= $player->username."\x00";
}
@ -127,7 +127,7 @@ class QueryHandler{
}
$pk->payload = $this->longData;
}else{
$pk->payload = $this->server->name."\x00".(($this->server->gamemode & 0x01) === 0 ? "SMP":"CMP")."\x00".$this->server->api->level->getDefault()->getName()."\x00".count($this->server->clients)."\x00".$this->server->maxClients."\x00".Utils::writeLShort($this->server->api->getProperty("server-port")).$this->server->api->getProperty("server-ip", "0.0.0.0")."\x00";
$pk->payload = $this->server->name."\x00".(($this->server->gamemode & 0x01) === 0 ? "SMP":"CMP")."\x00".$this->server->api->level->getDefault()->getName()."\x00".count(Player::$list)."\x00".$this->server->maxClients."\x00".Utils::writeLShort($this->server->api->getProperty("server-port")).$this->server->api->getProperty("server-ip", "0.0.0.0")."\x00";
}
$pk->encode();
$this->server->send($pk);

View File

@ -51,7 +51,7 @@ trait ContainerTileTrait{
$slots = array();
if(is_array($player->windows[$id])){
$all = $this->server->api->player->getAll($this->level);
$all = $this->level->getPlayers();
foreach($player->windows[$id] as $ob){
$pk = new TileEventPacket;
$pk->x = $ob->x;
@ -76,7 +76,7 @@ trait ContainerTileTrait{
$pk->z = $this->z;
$pk->case1 = 1;
$pk->case2 = 2;
$this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), $pk);
$this->server->api->player->broadcastPacket($this->level->getPlayers(), $pk);
for($s = 0; $s < ChestTile::SLOTS; ++$s){
$slot = $this->getSlot($s);
if($slot->getID() > AIR and $slot->count > 0){