From 4d9d50ed0c1c64b81ce0612c7c148df6830fa9bb Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Pueyo Date: Sat, 8 Dec 2012 13:23:04 +0100 Subject: [PATCH] Player Entities!! --- README | 5 +- classes/CustomPacketHandler.class.php | 12 ++-- classes/Session.class.php | 8 +-- classes/Utils.class.php | 98 +++++++++++++++++++++++++++ server.php | 41 +++++++---- 5 files changed, 139 insertions(+), 25 deletions(-) diff --git a/README b/README index 5d6a38ab8..ccbbe7338 100644 --- a/README +++ b/README @@ -31,6 +31,9 @@ along with this program. If not, see . Server (and client) Minecraft Pocket Edition library written in PHP. Currently a work in progress, and used to document http://www.wiki.vg/Pocket_Minecraft_Protocol +How to conect to internet servers: http://www.minecraftforum.net/topic/1256915-legit-minecraftpe-online-multiplayer/ + + Current features of the server: - Players can connect and move around the world - Online list broadcast @@ -40,5 +43,5 @@ Current features of the server: - Whitelist and IP Ban files - Survival & Creative - Awesome features in server list! - - Entities and player spawn as Dropped items + - Players spawn and see each other moving! - Multiple worlds and importing! diff --git a/classes/CustomPacketHandler.class.php b/classes/CustomPacketHandler.class.php index 37266ff94..02ed7014d 100644 --- a/classes/CustomPacketHandler.class.php +++ b/classes/CustomPacketHandler.class.php @@ -192,9 +192,7 @@ class CustomPacketHandler{ $this->data["x"] = Utils::readFloat($this->get(4)); $this->data["y"] = Utils::readFloat($this->get(4)); $this->data["z"] = Utils::readFloat($this->get(4)); - $this->data["yaw"] = Utils::readFloat($this->get(4)); - $this->data["pitch"] = Utils::readFloat($this->get(4)); - $this->data["metadata"] = $this->get(true); + $this->data["metadata"] = Utils::readMetadata($this->get(true)); }else{ $this->raw .= Utils::writeLong($this->data["clientID"]); $this->raw .= Utils::writeShort(strlen($this->data["username"])).$this->data["username"]; @@ -202,9 +200,11 @@ class CustomPacketHandler{ $this->raw .= Utils::writeFloat($this->data["x"]); $this->raw .= Utils::writeFloat($this->data["y"]); $this->raw .= Utils::writeFloat($this->data["z"]); - $this->raw .= Utils::writeFloat($this->data["yaw"]); - $this->raw .= Utils::writeFloat($this->data["pitch"]); - $this->raw .= "\x21\x2c\x01\x10"."\x7f"; + $this->raw .= Utils::writeMetadata(array( + 1 => array("type" => 1, "value" => 300), + 16 => array("type" => 0, "value" => 0), + 17 => array("type" => 6, "value" => array(0, 0, 0)), + )); } break; case MC_REMOVE_ENTITY: diff --git a/classes/Session.class.php b/classes/Session.class.php index 6ec7defd1..218bcf759 100644 --- a/classes/Session.class.php +++ b/classes/Session.class.php @@ -27,8 +27,8 @@ the Free Software Foundation, either version 3 of the License, or class Session{ - protected $server, $serverID, $timeout, $connected, $evid; - var $clientID, $ip, $port, $counter, $username, $eid, $data; + private $server, $serverID, $timeout, $connected, $evid; + var $clientID, $ip, $port, $counter, $username, $eid, $data, $entity; function __construct($server, $clientID, $eid, $ip, $port){ $this->server = $server; $this->clientID = $clientID; @@ -140,8 +140,6 @@ class Session{ "x" => $data["x"], "y" => $data["y"], "z" => $data["z"], - "yaw" => $data["yaw"], - "pitch" => $data["pitch"], ), )); ++$this->counter[0]; @@ -303,8 +301,6 @@ class Session{ "x" => $this->data["spawn"]["x"], "y" => $this->data["spawn"]["y"], "z" => $this->data["spawn"]["z"], - "yaw" => $this->data["spawn"]["yaw"], - "pitch" => $this->data["spawn"]["pitch"], )); foreach($this->server->entities as $entity){ if($entity->eid !== $this->eid){ diff --git a/classes/Utils.class.php b/classes/Utils.class.php index ce13bcd98..eafe8b4c2 100644 --- a/classes/Utils.class.php +++ b/classes/Utils.class.php @@ -78,6 +78,104 @@ class Utils{ public static function writeTriad($value){ return substr(pack("N", $value), 1); } + + public static function writeMetadata($data){ + $m = ""; + foreach($data as $bottom => $d){ + $m .= chr(($d["type"] << 5) & (0xE0 | $bottom)); + switch($d["type"]){ + case 0: + $m .= Utils::writeByte($data["value"]); + break; + case 1: + $m .= Utils::writeLShort($data["value"]); + break; + case 2: + $m .= Utils::writeLInt($data["value"]); + break; + case 3: + $m .= Utils::writeLFloat($data["value"]); + break; + case 4: + $m .= Utils::writeLShort(strlen($data["value"])); + $m .= $data["value"]; + break; + case 5: + $m .= Utils::writeLShort($data["value"][0]); + $m .= Utils::writeByte($data["value"][1]); + $m .= Utils::writeLShort($data["value"][2]); + break; + case 6: + for($i=0; $i < 3; ++$i){ + $m .= Utils::writeLInt($data["value"][$i]); + } + break; + + } + } + $m .= "\x7f"; + return $m; + } + + public static function readMetadata($value, $types = false){ + $offset = 0; + $m = array(); + $b = ord($value{$offset}); + ++$offset; + while($b !== 127){ + $bottom = $b & 0x1F; + $type = $b >> 5; + switch($type){ + case 0: + $r = Utils::readByte($value{$offset}); + ++$offset; + break; + case 1: + $r = Utils::readLShort(substr($value, $offset, 2)); + $offset += 2; + break; + case 2: + $r = Utils::readLInt(substr($value, $offset, 4)); + $offset += 4; + break; + case 3: + $r = Utils::readLFloat(substr($value, $offset, 4)); + $offset += 4; + break; + case 4: + $len = Utils::readLShort(substr($value, $offset, 2)); + $offset += 2; + $r = substr($value, $offset, $len); + $offset += $len; + break; + case 5: + $r = array(); + $r[] = Utils::readLShort(substr($value, $offset, 2)); + $offset += 2; + $r[] = Utils::readByte($value{$offset}); + ++$offset; + $r[] = Utils::readLShort(substr($value, $offset, 2)); + $offset += 2; + break; + case 6: + $r = array(); + for($i=0; $i < 3; ++$i){ + $r[] = Utils::readLInt(substr($value, $offset, 4)); + $offset += 4; + } + break; + + } + if($types === true){ + $m[$bottom] = array($r, $type); + }else{ + $m[$bottom] = $r; + } + $b = ord($value{$offset}); + ++$offset; + } + return $m; + } public static function readDataArray($str, $len = 10, &$offset = null){ $data = array(); diff --git a/server.php b/server.php index fe6ee365f..9c123fec8 100644 --- a/server.php +++ b/server.php @@ -212,13 +212,13 @@ function serverCommands(){ $p = strtolower(array_shift($params)); switch($p){ case "check": - $time = abs($server->time) % 14400; - $hour = str_pad(strval((floor($time / 600) + 6) % 24), 2, "0", STR_PAD_LEFT).":".str_pad(strval(floor(($time % 600) / 10)), 2, "0", STR_PAD_LEFT); - if($time < 7200){ + $time = abs($server->time) % 19200; + $hour = str_pad(strval((floor($time /800) + 6) % 24), 2, "0", STR_PAD_LEFT).":".str_pad(strval(floor(($time % 800) / 13.33)), 2, "0", STR_PAD_LEFT); + if($time < 9500){ $time = "daytime"; - }elseif($time < 8280){ + }elseif($time < 10900){ $time = "sunset"; - }elseif($time < 13320){ + }elseif($time < 17800){ $time = "night"; }else{ $time = "sunrise"; @@ -234,16 +234,16 @@ function serverCommands(){ $server->time = $t; break; case "sunrise": - $server->time = 13320; + $server->time = 17800; break; case "day": $server->time = 0; break; case "sunset": - $server->time = 7200; + $server->time = 9500; break; case "night": - $server->time = 8280; + $server->time = 10900; break; default: console("[INFO] Usage: /time [time]"); @@ -284,25 +284,42 @@ function serverCommands(){ break; } break; + case "save-all": + $server->save(); + break; + case "spawnplayer": + foreach($server->clients as $client){ + $entity = $client->entity; + $server->trigger("onPlayerAdd", array( + "clientID" => Utils::readLong(Utils::getRandomBytes(8)), + "username" => Utils::strToHex(Utils::getRandomBytes(6)), + "eid" => $server->eidCnt++, + "x" => $entity->position["x"], + "y" => $entity->position["y"], + "z" => $entity->position["z"], + )); + } + break; case "list": - $list = ""; + console("[INFO] Player list:"); foreach($server->clients as $c){ - $list .= ", ".$c->username; + console("[INFO] ".$c->username." (".$c->ip.":".$c->port."), ClientID ".$c->clientID); } - console("[INFO] Online: ".substr($list, 2)); break; case "help": + case "?": console("[INFO] /help: Show available commands"); console("[INFO] /gamemode: Changes default gamemode"); console("[INFO] /say: Broadcasts mesages"); console("[INFO] /time: Manages time"); console("[INFO] /list: Lists online users"); + console("[INFO] /save-all: Saves pending changes"); console("[INFO] /whitelist: Manages whitelisting"); console("[INFO] /banip: Bans an IP"); console("[INFO] /stop: Stops the server"); break; default: - console("[ERROR] Command doesn't exist!"); + console("[ERROR] Command doesn't exist! Use /help"); break; } }