diff --git a/src/API/BanAPI.php b/src/API/BanAPI.php index d03075062..7e830643a 100644 --- a/src/API/BanAPI.php +++ b/src/API/BanAPI.php @@ -48,7 +48,7 @@ class BanAPI{ $this->server->api->console->register("whitelist", " [username]", array($this, "commandHandler")); $this->server->api->console->register("op", "", array($this, "commandHandler")); $this->server->api->console->register("deop", "", array($this, "commandHandler")); - $this->server->api->console->register("sudo", "", array($this, "commandHandler")); + $this->server->api->console->register("sudo", " ", array($this, "commandHandler")); $this->server->api->console->alias("ban-ip", "banip add"); $this->server->api->console->alias("banlist", "ban list"); $this->server->api->console->alias("pardon", "ban remove"); diff --git a/src/API/ConsoleAPI.php b/src/API/ConsoleAPI.php index 0dfb688f3..8e8dec58e 100644 --- a/src/API/ConsoleAPI.php +++ b/src/API/ConsoleAPI.php @@ -249,7 +249,7 @@ class ConsoleAPI{ if(($d1 = $this->server->api->dhandle("console.command.".$cmd, array("cmd" => $cmd, "parameters" => $params, "issuer" => $issuer, "alias" => $alias))) === false or ($d2 = $this->server->api->dhandle("console.command", array("cmd" => $cmd, "parameters" => $params, "issuer" => $issuer, "alias" => $alias))) === false){ $output = "You don't have permissions to use this command.\n"; - }elseif($d1 !== true and (isset($d2) and $d2 !== true)){ + }elseif($d1 !== true and (!isset($d2) or $d2 !== true)){ if(isset($this->cmds[$cmd]) and is_callable($this->cmds[$cmd])){ $output = @call_user_func($this->cmds[$cmd], $cmd, $params, $issuer, $alias); }elseif($this->server->api->dhandle("console.command.unknown", array("cmd" => $cmd, "params" => $params, "issuer" => $issuer, "alias" => $alias)) !== false){ diff --git a/src/API/PlayerAPI.php b/src/API/PlayerAPI.php index a590c5466..7be632c17 100644 --- a/src/API/PlayerAPI.php +++ b/src/API/PlayerAPI.php @@ -337,7 +337,7 @@ class PlayerAPI{ $players = array(); if($query !== false and $query !== true){ while(($d = $query->fetchArray(SQLITE3_ASSOC)) !== false){ - $CID = PocketMinecraftServer::clientID($d["ip"], $d["port"]); + $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){ @@ -384,7 +384,7 @@ class PlayerAPI{ public function getByEID($eid){ $eid = (int) $eid; $CID = $this->server->query("SELECT ip,port FROM players WHERE EID = '".$eid."';", true); - $CID = PocketMinecraftServer::clientID($CID["ip"], $CID["port"]); + $CID = MainServer::clientID($CID["ip"], $CID["port"]); if(isset($this->server->clients[$CID])){ return $this->server->clients[$CID]; } diff --git a/src/API/ServerAPI.php b/src/API/ServerAPI.php index fecf022d2..f0aa5afcd 100644 --- a/src/API/ServerAPI.php +++ b/src/API/ServerAPI.php @@ -79,7 +79,7 @@ class ServerAPI{ public $tile; /** - * @return PocketMinecraftServer + * @return MainServer */ public static function request(){ return self::$serverRequest; @@ -138,7 +138,6 @@ class ServerAPI{ "enable-query" => true, "enable-rcon" => false, "rcon.password" => substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10), - "send-usage" => true, "auto-save" => true, )); @@ -156,7 +155,7 @@ class ServerAPI{ UPnP_PortForward($this->getProperty("server-port")); } - $this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), ($seed = $this->getProperty("level-seed")) != "" ? (int) $seed:false, $this->getProperty("server-port"), ($ip = $this->getProperty("server-ip")) != "" ? $ip:"0.0.0.0"); + $this->server = new MainServer($this->getProperty("server-name"), $this->getProperty("gamemode"), ($seed = $this->getProperty("level-seed")) != "" ? (int) $seed:false, $this->getProperty("server-port"), ($ip = $this->getProperty("server-ip")) != "" ? $ip:"0.0.0.0"); $this->server->api = $this; self::$serverRequest = $this->server; console("[INFO] This server is running PocketMine-MP version ".($version->isDev() ? FORMAT_YELLOW:"").MAJOR_VERSION.FORMAT_RESET." \"".CODENAME."\" (MCPE: ".CURRENT_MINECRAFT_VERSION.") (API ".CURRENT_API_VERSION.")", true, true, 0); @@ -293,7 +292,7 @@ class ServerAPI{ $this->setProperty("memory-limit", "128M"); } - if($this->server instanceof PocketMinecraftServer){ + if($this->server instanceof MainServer){ $this->server->setType($this->getProperty("server-type")); $this->server->maxClients = $this->getProperty("max-players"); $this->server->description = $this->getProperty("description"); @@ -339,11 +338,11 @@ class ServerAPI{ } public function init(){ - if(!(self::$serverRequest instanceof PocketMinecraftServer)){ + if(!(self::$serverRequest instanceof MainServer)){ self::$serverRequest = $this->server; } - if($this->getProperty("send-usage") !== false){ + if($this->getProperty("send-usage", true) !== false){ $this->server->schedule(6000, array($this, "sendUsage"), array(), true); //Send the info after 5 minutes have passed $this->sendUsage(); } diff --git a/src/PocketMinecraftServer.php b/src/MainServer.php similarity index 97% rename from src/PocketMinecraftServer.php rename to src/MainServer.php index 3c6b29a28..9be40b243 100644 --- a/src/PocketMinecraftServer.php +++ b/src/MainServer.php @@ -19,7 +19,7 @@ * */ -class PocketMinecraftServer{ +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; private $serverip, $evCnt, $handCnt, $events, $eventsID, $handlers, $serverType, $lastTick, $doTick, $ticks, $memoryStats, $schedule, $asyncThread, $async = array(), $asyncID = 0; @@ -228,6 +228,10 @@ class PocketMinecraftServer{ $d .= Utils::writeShort(strlen($key)).$key . Utils::writeInt(strlen($value)).$value; } break; + case ASYNC_FUNCTION: + $params = serialize($data["arguments"]); + $d .= Utils::writeShort(strlen($data["function"])).$data["function"] . Utils::writeInt(strlen($params)) . $params; + break; default: return false; } @@ -256,6 +260,12 @@ class PocketMinecraftServer{ $data["result"] = substr($this->asyncThread->output, $offset, $len); $offset += $len; break; + case ASYNC_FUNCTION: + $len = Utils::readInt(substr($this->asyncThread->output, $offset, 4)); + $offset += 4; + $data["result"] = unserialize(substr($this->asyncThread->output, $offset, $len)); + $offset += $len; + break; } $this->asyncThread->output = substr($this->asyncThread->output, $offset); if(isset($this->async[$ID]) and $this->async[$ID] !== null and is_callable($this->async[$ID])){ @@ -384,6 +394,7 @@ class PocketMinecraftServer{ if($this->stop === true){ return; } + ini_set("memory_limit", "-1"); //Fix error dump not dumped on memory problems console("[SEVERE] An unrecovereable has ocurred and the server has crashed. Creating an error dump"); $dump = "```\r\n# PocketMine-MP Error Dump ".date("D M j H:i:s T Y")."\r\n"; $er = error_get_last(); @@ -452,6 +463,7 @@ class PocketMinecraftServer{ } $dump .= "Loaded Modules: ".var_export($extensions, true)."\r\n"; + $this->checkMemory(); $dump .= "Memory Usage Tracking: \r\n".chunk_split(base64_encode(gzdeflate(implode(";", $this->memoryStats), 9)))."\r\n"; ob_start(); phpinfo(); @@ -480,7 +492,7 @@ class PocketMinecraftServer{ public function packetHandler(Packet $packet){ $data =& $packet; - $CID = PocketMinecraftServer::clientID($packet->ip, $packet->port); + $CID = MainServer::clientID($packet->ip, $packet->port); if(isset($this->clients[$CID])){ $this->clients[$CID]->handlePacket($packet); }else{ diff --git a/src/Player.php b/src/Player.php index 40ede5726..67ce4d822 100644 --- a/src/Player.php +++ b/src/Player.php @@ -104,7 +104,7 @@ class Player{ $this->server = ServerAPI::request(); $this->lastBreak = microtime(true); $this->clientID = $clientID; - $this->CID = PocketMinecraftServer::clientID($ip, $port); + $this->CID = MainServer::clientID($ip, $port); $this->ip = $ip; $this->port = $port; $this->spawnPosition = $this->server->spawn; @@ -2250,12 +2250,11 @@ class Player{ $t->spawn($this); }else{ $nbt = new NBT(); - $nbt->load($packet->namedtag); - $d = array_shift($nbt->tree); - if($d["id"] !== TILE_SIGN){ + $nbt->read($packet->namedtag); + if($nbt->id !== TILE_SIGN){ $t->spawn($this); }else{ - $t->setText($d["Text1"], $d["Text2"], $d["Text3"], $d["Text4"]); + $t->setText($nbt->Text1, $nbt->Text2, $nbt->Text3, $nbt->Text4); } } } diff --git a/src/nbt/NBT.php b/src/nbt/NBT.php index edc1d1d2b..82710b952 100644 --- a/src/nbt/NBT.php +++ b/src/nbt/NBT.php @@ -19,18 +19,207 @@ * */ -class NBT{ - const MODE_WRITE = 0; - const MODE_OVERWRITE = 1; - +class NBT{ const LITTLE_ENDIAN = 0; const BIG_ENDIAN = 1; private $buffer; private $offset; - private $mode = NBT::MODE_WRITE; - - public function __construct($buffer, $endianness = NBT::BIG_ENDIAN){ + private $endianness; + private $data; + public function get($len){ + if($len < 0){ + $this->offset = strlen($this->buffer) - 1; + return ""; + } + if($len === true){ + return substr($this->buffer, $this->offset); + } + $this->offset += $len; + return substr($this->buffer, $this->offset - $len, $len); } -} \ No newline at end of file + + public function put($v){ + $this->buffer .= $v; + } + + public function feof(){ + return !isset($this->buffer{$this->offset}); + } + + public function __construct($endianness = NBT::LITTLE_ENDIAN){ + $this->offset = 0; + $this->endianness = $endianness & 0x01; + } + + public function read($buffer){ + $this->offset = 0; + $this->buffer = $buffer; + $this->data = $this->readTag(); + } + + public function write(){ + $this->offset = 0; + if($this->data instanceof NBTTag_Compound){ + $this->writeTag($this->data); + return $this->buffer; + }else{ + return false; + } + } + + public function readTag(){ + switch($this->getByte()){ + case NBTTag::TAG_Byte: + $tag = new NBTTag_Byte($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Byte: + $tag = new NBTTag_Byte($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Short: + $tag = new NBTTag_Short($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Int: + $tag = new NBTTag_Int($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Long: + $tag = new NBTTag_Long($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Float: + $tag = new NBTTag_Float($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Double: + $tag = new NBTTag_Double($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Byte_Array: + $tag = new NBTTag_Byte_Array($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_String: + $tag = new NBTTag_String($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_List: + $tag = new NBTTag_List($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Compound: + $tag = new NBTTag_Compound($this->getString()); + $tag->read($this); + break; + case NBTTag::TAG_Int_Array: + $tag = new NBTTag_Int_Array($this->getString()); + $tag->read($this); + break; + + case NBTTag::TAG_End: //No named tag + default: + $tag = new NBTTag_End; + break; + } + return $tag; + } + + public function writeTag(NBTTag $tag){ + $this->putByte($tag->getType()); + if($tag instanceof NamedNBTTag and $tag->getName() !== false){ + $this->putString($tag->getName()); + } + $tag->write($this); + } + + public function getByte(){ + return Utils::readByte($this->get(1), true); + } + + public function putByte($v){ + $this->buffer .= Utils::writeByte($v); + } + + public function getShort(){ + return $this->endianness === self::BIG_ENDIAN ? Utils::readShort($this->get(2)) : Utils::readLShort($this->get(2)); + } + + public function putShort($v){ + $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Utils::writeShort($v) : Utils::writeLShort($v); + } + + public function getInt(){ + return $this->endianness === self::BIG_ENDIAN ? Utils::readInt($this->get(4)) : Utils::readLInt($this->get(4)); + } + + public function putInt($v){ + $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Utils::writeInt($v) : Utils::writeLInt($v); + } + + public function getLong(){ + return $this->endianness === self::BIG_ENDIAN ? Utils::readLong($this->get(8)) : Utils::readLLong($this->get(8)); + } + + public function putLong($v){ + $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Utils::writeLong($v) : Utils::writeLLong($v); + } + + public function getFloat(){ + return $this->endianness === self::BIG_ENDIAN ? Utils::readFloat($this->get(4)) : Utils::readLFloat($this->get(4)); + } + + public function putFloat($v){ + $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Utils::writeFloat($v) : Utils::writeLFloat($v); + } + + public function getDouble(){ + return $this->endianness === self::BIG_ENDIAN ? Utils::readDouble($this->get(8)) : Utils::readLDouble($this->get(8)); + } + + public function putDouble($v){ + $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Utils::writeDouble($v) : Utils::writeLDouble($v); + } + + public function getString(){ + return $this->get($this->getShort()); + } + + public function putString($v){ + $this->putShort(strlen($v)); + $this->buffer .= $v; + } + + public function __get($name){ + return $this->data instanceof NBTTag_Compound ? $this->data->{$name} : false; + } + + public function __set($name, $value){ + if($this->data instanceof NBTTag_Compound){ + $this->data->{$name} = $value; + } + } + + public function __isset($name){ + return $this->data instanceof NBTTag_Compound ? isset($this->data->{$name}) : false; + } + + public function __unset($name){ + if($this->data instanceof NBTTag_Compound){ + unset($this->data->{$name}); + } + } + + public function getData(){ + return $this->data; + } + + public function setData(NBTTag_Compound $data){ + $this->data = $data; + } + +} +>>>>>>> origin/master diff --git a/src/nbt/NBTTag.php b/src/nbt/NBTTag.php new file mode 100644 index 000000000..55acec543 --- /dev/null +++ b/src/nbt/NBTTag.php @@ -0,0 +1,55 @@ +value; + } + + public abstract function getType(); + + public function setValue($value){ + $this->value = $value; + } + + abstract public function write(NBT $nbt); + + abstract public function read(NBT $nbt); + + public final function __toString(){ + return $this->value; + } +} diff --git a/src/nbt/NamedNBTTag.php b/src/nbt/NamedNBTTag.php new file mode 100644 index 000000000..7c27b7aa6 --- /dev/null +++ b/src/nbt/NamedNBTTag.php @@ -0,0 +1,43 @@ +name = $name; + if($value !== false){ + $this->value = $value; + } + } + + public function getName(){ + return $this->name; + } + + public function setName($name){ + $this->name = $name; + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Byte.php b/src/nbt/tags/TAG_Byte.php new file mode 100644 index 000000000..ede91b995 --- /dev/null +++ b/src/nbt/tags/TAG_Byte.php @@ -0,0 +1,35 @@ +value = $nbt->getByte(); + } + + public function write(NBT $nbt){ + $nbt->putByte($this->value); + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Byte_Array.php b/src/nbt/tags/TAG_Byte_Array.php new file mode 100644 index 000000000..6b155f45a --- /dev/null +++ b/src/nbt/tags/TAG_Byte_Array.php @@ -0,0 +1,36 @@ +value = $nbt->get($this->getInt()); + } + + public function write(NBT $nbt){ + $nbt->putInt(strlen($this->value)); + $nbt->put($this->value); + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Compound.php b/src/nbt/tags/TAG_Compound.php new file mode 100644 index 000000000..d69c67937 --- /dev/null +++ b/src/nbt/tags/TAG_Compound.php @@ -0,0 +1,63 @@ +value[$name]) ? $this->value[$name]->getValue() : false; + } + + public function __set($name, $value){ + if(isset($this->value[$name])){ + $this->value[$name]->setValue($value); + } + } + + public function __isset($name){ + return isset($this->value[$name]); + } + + public function __unset($name){ + unset($this->value[$name]); + } + + public function read(NBT $nbt){ + $this->value = array(); + do{ + $tag = $nbt->readTag(); + if($tag instanceof NamedNBTTag and $tag->getName() !== ""){ + $this->value[$tag->getName()] = $tag; + }else{ + $this->value[] = $tag; + } + }while(!($tag instanceof NBTTag_End) and !$nbt->feof()); + } + + public function write(NBT $nbt){ + foreach($this->value as $tag){ + $nbt->writeTag($tag); + } + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Double.php b/src/nbt/tags/TAG_Double.php new file mode 100644 index 000000000..f1ee58b2b --- /dev/null +++ b/src/nbt/tags/TAG_Double.php @@ -0,0 +1,35 @@ +value = $nbt->getDouble(); + } + + public function write(NBT $nbt){ + $nbt->putDouble($this->value); + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_End.php b/src/nbt/tags/TAG_End.php new file mode 100644 index 000000000..535fed402 --- /dev/null +++ b/src/nbt/tags/TAG_End.php @@ -0,0 +1,35 @@ +value = $nbt->getFloat(); + } + + public function write(NBT $nbt){ + $nbt->putFloat($this->value); + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Int.php b/src/nbt/tags/TAG_Int.php new file mode 100644 index 000000000..cfbb3d8bf --- /dev/null +++ b/src/nbt/tags/TAG_Int.php @@ -0,0 +1,35 @@ +value = $nbt->getInt(); + } + + public function write(NBT $nbt){ + $nbt->putInt($this->value); + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Int_Array.php b/src/nbt/tags/TAG_Int_Array.php new file mode 100644 index 000000000..352cca275 --- /dev/null +++ b/src/nbt/tags/TAG_Int_Array.php @@ -0,0 +1,42 @@ +value = array(); + $size = $nbt->getInt(); + for($i = 0; $i < $size and !$nbt->feof(); ++$i){ + $this->value[] = $nbt->getInt(); + } + } + + public function write(NBT $nbt){ + $nbt->putInt(count($this->value)); + foreach($this->value as $v){ + $nbt->putInt($v); + } + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_List.php b/src/nbt/tags/TAG_List.php new file mode 100644 index 000000000..bc431b784 --- /dev/null +++ b/src/nbt/tags/TAG_List.php @@ -0,0 +1,126 @@ +value[$name]) ? $this->value[$name]->getValue() : false; + } + + public function __set($name, $value){ + if(isset($this->value[$name])){ + $this->value[$name]->setValue($value); + } + } + + public function __isset($name){ + return isset($this->value[$name]); + } + + public function __unset($name){ + unset($this->value[$name]); + } + + public function read(NBT $nbt){ + $this->value = array(); + $tagId = $nbt->getByte(); + $this->value[-1] = $tagId; + $size = $nbt->getInt(); + for($i = 0; $i < $size and !$nbt->feof(); ++$i){ + switch($tagId){ + case NBTTag::TAG_Byte: + $tag = new NBTTag_Byte(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Byte: + $tag = new NBTTag_Byte(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Short: + $tag = new NBTTag_Short(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Int: + $tag = new NBTTag_Int(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Long: + $tag = new NBTTag_Long(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Float: + $tag = new NBTTag_Float(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Double: + $tag = new NBTTag_Double(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Byte_Array: + $tag = new NBTTag_Byte_Array(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_String: + $tag = new NBTTag_String(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_List: + $tag = new NBTTag_List(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Compound: + $tag = new NBTTag_Compound(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + case NBTTag::TAG_Int_Array: + $tag = new NBTTag_Int_Array(false); + $tag->read($nbt); + $this->value[] = $tag; + break; + } + } + } + + public function write(NBT $nbt){ + $nbt->putByte($this->value[-1]); + $nbt->putInt(count($this->value) - 1); + foreach($this->value as $tag){ + if($tag instanceof NBTTag){ + $nbt->writeTag($tag); + } + } + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Long.php b/src/nbt/tags/TAG_Long.php new file mode 100644 index 000000000..d4f27dcf8 --- /dev/null +++ b/src/nbt/tags/TAG_Long.php @@ -0,0 +1,35 @@ +value = $nbt->getLong(); + } + + public function write(NBT $nbt){ + $nbt->putLong($this->value); + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_Short.php b/src/nbt/tags/TAG_Short.php new file mode 100644 index 000000000..465d989cd --- /dev/null +++ b/src/nbt/tags/TAG_Short.php @@ -0,0 +1,35 @@ +value = $nbt->getShort(); + } + + public function write(NBT $nbt){ + $nbt->putShort($this->value); + } +} \ No newline at end of file diff --git a/src/nbt/tags/TAG_String.php b/src/nbt/tags/TAG_String.php new file mode 100644 index 000000000..deee590e3 --- /dev/null +++ b/src/nbt/tags/TAG_String.php @@ -0,0 +1,36 @@ +value = $nbt->get($nbt->getShort()); + } + + public function write(NBT $nbt){ + $nbt->putShort(strlen($this->value)); + $nbt->put($this->value); + } +} \ No newline at end of file diff --git a/src/network/MinecraftInterface.php b/src/network/MinecraftInterface.php index 7a4266266..37a0862b7 100644 --- a/src/network/MinecraftInterface.php +++ b/src/network/MinecraftInterface.php @@ -38,12 +38,9 @@ class MinecraftInterface{ } public function readPacket(){ - if($this->socket->connected === false){ - return false; - } - $buf = ""; - $source = false; - $port = 1; + $buf = null; + $source = null; + $port = null; $len = $this->socket->read($buf, $source, $port); if($len === false or $len === 0){ return false; diff --git a/src/network/RCON.php b/src/network/RCON.php index c46ca8e5f..ca41f4d9d 100644 --- a/src/network/RCON.php +++ b/src/network/RCON.php @@ -104,7 +104,11 @@ class RCONInstance extends Thread{ } private function writePacket($client, $requestID, $packetType, $payload){ - return socket_write($client, Utils::writeLInt(strlen($payload)).Utils::writeLInt((int) $requestID).Utils::writeLInt((int) $packetType).($payload === "" ? "\x00":$payload)."\x00"); + $pk = Utils::writeLInt((int) $requestID) + . Utils::writeLInt((int) $packetType) + . $payload + . "\x00\x00"; //Terminate payload and packet + return socket_write($client, Utils::writeLInt(strlen($pk)).$pk); } private function readPacket($client, &$size, &$requestID, &$packetType, &$payload){ diff --git a/src/network/UDPSocket.php b/src/network/UDPSocket.php index 8dc30c717..81a305881 100644 --- a/src/network/UDPSocket.php +++ b/src/network/UDPSocket.php @@ -45,7 +45,6 @@ class UDPSocket{ } public function close($error = 125){ - $this->connected = false; return @socket_close($this->sock); } @@ -58,16 +57,10 @@ class UDPSocket{ } public function read(&$buf, &$source, &$port){ - if($this->connected === false){ - return false; - } return @socket_recvfrom($this->sock, $buf, 65535, 0, $source, $port); } public function write($data, $dest, $port){ - if($this->connected === false){ - return false; - } return @socket_sendto($this->sock, $data, strlen($data), 0, $dest, $port); } diff --git a/src/network/query/QueryHandler.php b/src/network/query/QueryHandler.php index f300695bb..bc7286443 100644 --- a/src/network/query/QueryHandler.php +++ b/src/network/query/QueryHandler.php @@ -91,7 +91,11 @@ class QueryHandler{ public function regenerateToken(){ $this->lastToken = $this->token; - $this->token = Utils::readInt("\x00".Utils::getRandomBytes(3, false)); + $this->token = Utils::getRandomBytes(16, false); + } + + public static function getTokenString($token, $salt){ + return Utils::readInt(substr(hash("sha512", $salt . ":". $token, true), 7, 4)); } public function handle(QueryPacket $packet){ @@ -103,13 +107,13 @@ class QueryHandler{ $pk->port = $packet->port; $pk->packetType = QueryPacket::HANDSHAKE; $pk->sessionID = $packet->sessionID; - $pk->payload = $this->token."\x00"; + $pk->payload = self::getTokenString($this->token, $packet->ip)."\x00"; $pk->encode(); $this->server->send($pk); break; case QueryPacket::STATISTICS: //Stat $token = Utils::readInt(substr($packet->payload, 0, 4)); - if($token !== $this->token and $token !== $this->lastToken){ + if($token !== self::getTokenString($this->token, $packet->ip) and $token !== self::getTokenString($this->lastToken, $packet->ip)){ break; } $pk = new QueryPacket; @@ -131,4 +135,4 @@ class QueryHandler{ } } -} \ No newline at end of file +} diff --git a/src/tests/ServerSuiteTest.php b/src/tests/ServerSuiteTest.php index 4ef030f75..b46cb0c61 100644 --- a/src/tests/ServerSuiteTest.php +++ b/src/tests/ServerSuiteTest.php @@ -12,7 +12,7 @@ } } - if(!class_exists("PocketMinecraftServer", false)){ + if(!class_exists("MainServer", false)){ define("NO_THREADS", true); require_once(dirname(__FILE__)."/../dependencies.php"); require_once(FILE_PATH."/src/functions.php"); diff --git a/src/utils/NBT.php b/src/utils/NBT.php deleted file mode 100644 index dcbb11017..000000000 --- a/src/utils/NBT.php +++ /dev/null @@ -1,213 +0,0 @@ -offset += $n; - return substr($this->binary, $this->offset - $n, $n); - } - - private function feof(){ - return !isset($this->binary{$this->offset}); - } - - public function write($bin){ - $this->binary .= $bin; - } - - public function load($str){ - $this->offset = 0; - $this->binary = (string) $str; - $this->parseTree($this->tree); - } - - public function readTAG_BYTE(){ - return Utils::readByte($this->read(1)); - } - - public function readTAG_SHORT(){ - return Utils::readLShort($this->read(2)); - } - - public function readTAG_INT(){ - return Utils::readLInt($this->read(4)); - } - - public function readTAG_LONG(){ - return Utils::readLLong($this->read(8)); - } - - public function readTAG_FLOAT(){ - return Utils::readLFloat($this->read(4)); - } - - public function readTAG_DOUBLE(){ - return Utils::readLDouble($this->read(8)); - } - - public function readTAG_BYTE_ARRAY(){ - return $this->read($this->readTAG_INT()); - } - - public function readTAG_STRING(){ - return $this->read(Utils::readLShort($this->read(2), false)); - } - - public function writeTAG_BYTE($v){ - $this->binary .= chr($v); - } - - public function writeTAG_SHORT($v){ - $this->binary .= Utils::writeLShort($v); - } - - public function writeTAG_INT($v){ - $this->binary .= Utils::writeLInt($v); - } - - public function writeTAG_LONG($v){ - $this->binary .= Utils::writeLLong($v); - } - - public function writeTAG_FLOAT($v){ - $this->binary .= Utils::writeLFloat($v); - } - - public function writeTAG_DOUBLE($v){ - $this->binary .= Utils::writeLDouble($v); - } - - public function writeTAG_BYTE_ARRAY($v){ - $this->binary .= $this->writeTAG_INT(strlen($v)).$v; - } - - public function writeTAG_STRING($v){ - $this->binary .= $this->writeTAG_SHORT(strlen($v)).$v; - } - - private function parseList(&$node, $tag, $cnt){ - for($i = 0; $i < $cnt and !$this->feof(); ++$i){ - switch($tag){ - case self::TAG_BYTE: - $value = $this->readTAG_BYTE(); - break; - case self::TAG_SHORT: - $value = $this->readTAG_SHORT(); - break; - case self::TAG_INT: - $value = $this->readTAG_INT(); - break; - case self::TAG_LONG: - $value = $this->readTAG_LONG(); - break; - case self::TAG_FLOAT: - $value = $this->readTAG_FLOAT(); - break; - case self::TAG_DOUBLE: - $value = $this->readTAG_DOUBLE(); - break; - case self::TAG_BYTE_ARRAY: - $value = $this->readTAG_BYTE_ARRAY(); - break; - case self::TAG_STRING: - $value = $this->readTAG_STRING(); - break; - case self::TAG_LIST: - $value = array(); - $this->parseList($value, ord($this->read(1)), Utils::readLInt($this->read(4))); - break; - case self::TAG_COMPOUND: - $value = array(); - $this->parseTree($value); - break; - default: - echo bin2hex(substr($this->binary, $this->offset - 1)).PHP_EOL.PHP_EOL; - die("Invalid NBT Tag $tag"); - break; - } - $node[] = $value; - } - } - - private function parseTree(&$node){ - while(($tag = ord($this->read(1))) !== self::TAG_END and !$this->feof()){ - $name = $this->readTAG_STRING(); - switch($tag){ - case self::TAG_BYTE: - $value = $this->readTAG_BYTE(); - break; - case self::TAG_SHORT: - $value = $this->readTAG_SHORT(); - break; - case self::TAG_INT: - $value = $this->readTAG_INT(); - break; - case self::TAG_LONG: - $value = $this->readTAG_LONG(); - break; - case self::TAG_FLOAT: - $value = $this->readTAG_FLOAT(); - break; - case self::TAG_DOUBLE: - $value = $this->readTAG_DOUBLE(); - break; - case self::TAG_BYTE_ARRAY: - $value = $this->readTAG_BYTE_ARRAY(); - break; - case self::TAG_STRING: - $value = $this->readTAG_STRING(); - break; - case self::TAG_LIST: - $value = array(); - $this->parseList($value, ord($this->read(1)), Utils::readLInt($this->read(4))); - break; - case self::TAG_COMPOUND: - $value = array(); - $this->parseTree($value); - break; - default: - echo bin2hex(substr($this->binary, $this->offset - 1)).PHP_EOL.PHP_EOL; - die("Invalid NBT Tag $tag"); - break; - } - $node[$name] = $value; - } - } -} \ No newline at end of file diff --git a/src/utils/pthreads.php b/src/utils/pthreads.php index d4a3faaf0..38a8d6619 100644 --- a/src/utils/pthreads.php +++ b/src/utils/pthreads.php @@ -21,6 +21,7 @@ define("ASYNC_CURL_GET", 1); define("ASYNC_CURL_POST", 2); +define("ASYNC_FUNCTION", 3); class StackableArray extends Stackable{ public function __construct(){ @@ -94,6 +95,12 @@ class AsyncMultipleQueue extends Thread{ $this->output .= Utils::writeInt($rID).Utils::writeShort(ASYNC_CURL_POST).Utils::writeInt(strlen($res)).$res; $this->unlock(); break; + case ASYNC_FUNCTION: + $function = $this->get(Utils::readShort($this->get(2), false)); + $params = unserialize($this->get(Utils::readInt($this->get(4)))); + $res = serialize(@call_user_func_array($function, $params)); + $this->output .= Utils::writeInt($rID).Utils::writeShort(ASYNC_FUNCTION).Utils::writeInt(strlen($res)).$res; + break; } } usleep(10000); diff --git a/src/world/Level.php b/src/world/Level.php index fb49ef32f..56948cfe8 100644 --- a/src/world/Level.php +++ b/src/world/Level.php @@ -43,7 +43,7 @@ class Level{ $this->nextSave = $this->startCheck = microtime(true); $this->nextSave += 90; $this->stopTime = false; - $this->server->schedule(15, array($this, "checkThings"), array(), true); + $this->server->schedule(2, array($this, "checkThings"), array(), true); $this->server->schedule(20 * 13, array($this, "checkTime"), array(), true); $this->name = $name; $this->usedChunks = array(); diff --git a/src/world/LevelImport.php b/src/world/LevelImport.php index 7d2ecf491..e22640103 100644 --- a/src/world/LevelImport.php +++ b/src/world/LevelImport.php @@ -34,22 +34,22 @@ class LevelImport{ $tiles = new Config($this->path."tiles.yml", Config::YAML, unserialize(file_get_contents($this->path."tileEntities.dat"))); $tiles->save(); }elseif(file_exists($this->path."chunks.dat") and file_exists($this->path."level.dat")){ //Pocket - $nbt = new NBT(); - $nbt->load(substr(file_get_contents($this->path."level.dat"), 8)); - $level = array_shift($nbt->tree); - if($level["LevelName"] == ""){ - $level["LevelName"] = "world".time(); + $nbt = new NBT(NBT::LITTLE_ENDIAN); + $nbt->read(substr(file_get_contents($this->path."level.dat"), 8)); + $level = $nbt->getData(); + if($level->LevelName == ""){ + $level->LevelName = "world".time(); } - console("[INFO] Importing Pocket level \"".$level["LevelName"]."\" to PMF format"); - unset($level["Player"]); - $nbt->load(substr(file_get_contents($this->path."entities.dat"), 12)); - $entities = array_shift($nbt->tree); - if(!isset($entities["TileEntities"])){ - $entities["TileEntities"] = array(); + console("[INFO] Importing Pocket level \"".$level->LevelName."\" to PMF format"); + unset($level->Player); + $nbt->read(substr(file_get_contents($this->path."entities.dat"), 12)); + $entities = $nbt->getData(); + if(!isset($entities->TileEntities)){ + $entities->TileEntities = array(); } - $tiles = $entities["TileEntities"]; - $entities = $entities["Entities"]; - $entities = new Config($this->path."entities.yml", Config::YAML, $entities); + $tiles = $entities->TileEntities; + $entities = $entities->Entities; + $entities = new Config($this->path."entities.yml", CONFIG_YAML, $entities); $entities->save(); $tiles = new Config($this->path."tiles.yml", Config::YAML, $tiles); $tiles->save(); diff --git a/src/world/Tile.php b/src/world/Tile.php index c2b89fbef..7a05c7052 100644 --- a/src/world/Tile.php +++ b/src/world/Tile.php @@ -356,87 +356,52 @@ class Tile extends Position{ } switch($this->class){ case TILE_CHEST: - $nbt = new NBT(); - $nbt->write(chr(NBT::TAG_COMPOUND)."\x00\x00"); - - $nbt->write(chr(NBT::TAG_STRING)); - $nbt->writeTAG_String("id"); - $nbt->writeTAG_String($this->class); - - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("x"); - $nbt->writeTAG_Int((int) $this->x); - - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("y"); - $nbt->writeTAG_Int((int) $this->y); - - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("z"); - $nbt->writeTAG_Int((int) $this->z); - + $nbt = new NBT(NBT::LITTLE_ENDIAN); if($this->isPaired()){ - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("pairx"); - $nbt->writeTAG_Int((int) $this->data["pairx"]); - - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("pairz"); - $nbt->writeTAG_Int((int) $this->data["pairz"]); + $nbt->setData(new NBTTag_Compound("", array( + new NBTTag_String("id", $this->class), + new NBTTag_Int("x", (int) $this->x), + new NBTTag_Int("y", (int) $this->y), + new NBTTag_Int("z", (int) $this->z), + new NBTTag_Int("pairx", (int) $this->data["pairx"]), + new NBTTag_Int("pairz", (int) $this->data["pairz"]), + new NBTTag_End + ))); + }else{ + $nbt->setData(new NBTTag_Compound("", array( + new NBTTag_String("id", $this->class), + new NBTTag_Int("x", (int) $this->x), + new NBTTag_Int("y", (int) $this->y), + new NBTTag_Int("z", (int) $this->z), + new NBTTag_End + ))); } - $nbt->write(chr(NBT::TAG_END)); - $pk = new EntityDataPacket; $pk->x = $this->x; $pk->y = $this->y; $pk->z = $this->z; - $pk->namedtag = $nbt->binary; + $pk->namedtag = $nbt->write(); $player->dataPacket($pk); break; case TILE_SIGN: - $nbt = new NBT(); - $nbt->write(chr(NBT::TAG_COMPOUND)."\x00\x00"); - - $nbt->write(chr(NBT::TAG_STRING)); - $nbt->writeTAG_String("Text1"); - $nbt->writeTAG_String($this->data["Text1"]); - - $nbt->write(chr(NBT::TAG_STRING)); - $nbt->writeTAG_String("Text2"); - $nbt->writeTAG_String($this->data["Text2"]); - - $nbt->write(chr(NBT::TAG_STRING)); - $nbt->writeTAG_String("Text3"); - $nbt->writeTAG_String($this->data["Text3"]); - - $nbt->write(chr(NBT::TAG_STRING)); - $nbt->writeTAG_String("Text4"); - $nbt->writeTAG_String($this->data["Text4"]); - - $nbt->write(chr(NBT::TAG_STRING)); - $nbt->writeTAG_String("id"); - $nbt->writeTAG_String($this->class); - - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("x"); - $nbt->writeTAG_Int((int) $this->x); - - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("y"); - $nbt->writeTAG_Int((int) $this->y); - - $nbt->write(chr(NBT::TAG_INT)); - $nbt->writeTAG_String("z"); - $nbt->writeTAG_Int((int) $this->z); - - $nbt->write(chr(NBT::TAG_END)); - + $nbt = new NBT(NBT::LITTLE_ENDIAN); + $nbt->setData(new NBTTag_Compound("", array( + new NBTTag_String("Text1", $this->data["Text1"]), + new NBTTag_String("Text2", $this->data["Text2"]), + new NBTTag_String("Text3", $this->data["Text3"]), + new NBTTag_String("Text4", $this->data["Text4"]), + new NBTTag_String("id", $this->class), + new NBTTag_Int("x", (int) $this->x), + new NBTTag_Int("y", (int) $this->y), + new NBTTag_Int("z", (int) $this->z), + new NBTTag_End + ))); $pk = new EntityDataPacket; $pk->x = $this->x; $pk->y = $this->y; $pk->z = $this->z; - $pk->namedtag = $nbt->binary; + $pk->namedtag = $nbt->write(); $player->dataPacket($pk); break; }