mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-10-16 03:51:37 +00:00
Changes made to be compatible with the DevTools plugin
This commit is contained in:
701
src/network/CustomPacketHandler.php
Normal file
701
src/network/CustomPacketHandler.php
Normal file
@@ -0,0 +1,701 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ PocketMine \
|
||||
/ MP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class CustomPacketHandler{
|
||||
var $offset, $raw, $c, $data, $name = "";
|
||||
|
||||
private function get($len = true, $check = true){
|
||||
if($len === true){
|
||||
$data = substr($this->raw, $this->offset);
|
||||
if($check === true){
|
||||
$this->offset = strlen($this->raw);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
$data = substr($this->raw, $this->offset, $len);
|
||||
if($check === true){
|
||||
$this->offset += $len;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function __construct($pid, $raw = "", $data = array(), $create = false){
|
||||
$this->raw = $raw;
|
||||
$this->data = $data;
|
||||
$this->offset = 0;
|
||||
$this->c = (bool) $create;
|
||||
switch($pid){
|
||||
case MC_KEEP_ALIVE:
|
||||
if($this->c === false){
|
||||
$this->data["payload"] = Utils::readLong($this->get(8));
|
||||
}else{
|
||||
$this->raw .= Utils::writeLong($this->data["payload"]);
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
if($this->c === false){
|
||||
$this->data["unknown1"] = Utils::readLong($this->get(8));
|
||||
$this->data["unknown2"] = Utils::readLong($this->get(8));
|
||||
}else{
|
||||
$this->raw .= Utils::writeLong($this->data["unknown1"]);
|
||||
$this->raw .= Utils::writeLong($this->data["unknown2"]);
|
||||
}
|
||||
break;
|
||||
case MC_CLIENT_CONNECT:
|
||||
if($this->c === false){
|
||||
$this->data["clientID"] = Utils::readLong($this->get(8));
|
||||
$this->data["session"] = Utils::readLong($this->get(8));
|
||||
$this->data["unknown2"] = $this->get(1);
|
||||
}else{
|
||||
$this->raw .= Utils::writeLong($this->data["clientID"]);
|
||||
$this->raw .= Utils::writeLong($this->data["session"]);
|
||||
$this->raw .= "\x00";
|
||||
}
|
||||
break;
|
||||
case MC_SERVER_HANDSHAKE:
|
||||
if($this->c === false){
|
||||
$this->data["cookie"] = $this->get(4); // 043f57fe
|
||||
$this->data["security"] = $this->get(1);
|
||||
$this->data["port"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["dataArray"] = Utils::readDataArray($this->get(true, false), 10, $offset);
|
||||
$this->get($offset);
|
||||
$this->data["unknown1"] = $this->get(2);
|
||||
$this->data["session"] = Utils::readLong($this->get(8));
|
||||
$this->data["session2"] = Utils::readLong($this->get(8));
|
||||
}else{
|
||||
$this->raw .= "\x04\x3f\x57\xfe";
|
||||
$this->raw .= "\xcd";
|
||||
$this->raw .= Utils::writeShort($this->data["port"]);
|
||||
$this->raw .= Utils::writeDataArray(array(
|
||||
"\xf5\xff\xff\xf5",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
"\xff\xff\xff\xff",
|
||||
));
|
||||
$this->raw .= "\x00\x00";
|
||||
$this->raw .= Utils::writeLong($this->data["session"]);
|
||||
$this->raw .= Utils::writeLong($this->data["session2"]);
|
||||
}
|
||||
break;
|
||||
case MC_CLIENT_HANDSHAKE:
|
||||
if($this->c === false){
|
||||
$this->data["cookie"] = $this->get(4); // 043f57fe
|
||||
$this->data["security"] = $this->get(1);
|
||||
$this->data["port"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["dataArray0"] = $this->get(ord($this->get(1)));
|
||||
$this->data["dataArray"] = Utils::readDataArray($this->get(true, false), 9, $offset);
|
||||
$this->get($offset);
|
||||
$this->data["unknown1"] = $this->get(2);
|
||||
$this->data["session2"] = Utils::readLong($this->get(8));
|
||||
$this->data["session"] = Utils::readLong($this->get(8));
|
||||
}else{
|
||||
$this->raw .= "\x04\x3f\x57\xfe";
|
||||
$this->raw .= "\xed";
|
||||
$this->raw .= Utils::writeShort($this->data["port"]);
|
||||
$w = array_shift($this->data["dataArray"]);
|
||||
$this->raw .= chr(strlen($w)).$w;
|
||||
$this->raw .= Utils::writeDataArray($this->data["dataArray"]);
|
||||
$this->raw .= "\x00\x00";
|
||||
$this->raw .= Utils::writeLong($this->data["session2"]);
|
||||
$this->raw .= Utils::writeLong($this->data["session"]);
|
||||
}
|
||||
break;
|
||||
case MC_DISCONNECT:
|
||||
//null
|
||||
break;
|
||||
case MC_LOGIN:
|
||||
if($this->c === false){
|
||||
$this->data["username"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
$this->data["protocol1"] = Utils::readInt($this->get(4));
|
||||
$this->data["protocol2"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["username"])).$this->data["username"];
|
||||
$this->raw .= Utils::writeInt(CURRENT_PROTOCOL).Utils::writeInt(CURRENT_PROTOCOL);
|
||||
}
|
||||
break;
|
||||
case MC_LOGIN_STATUS:
|
||||
if($this->c === false){
|
||||
$this->data["status"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["status"]);
|
||||
}
|
||||
break;
|
||||
case MC_READY:
|
||||
if($this->c === false){
|
||||
$this->data["status"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= chr($this->data["status"]);
|
||||
}
|
||||
break;
|
||||
case MC_CHAT:
|
||||
if($this->c === false){
|
||||
$this->data["message"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
}else{
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["message"])).$this->data["message"];
|
||||
}
|
||||
break;
|
||||
case MC_SET_TIME:
|
||||
if($this->c === false){
|
||||
$this->data["time"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["time"]);
|
||||
}
|
||||
break;
|
||||
case MC_START_GAME:
|
||||
if($this->c === false){
|
||||
$this->data["seed"] = Utils::readInt($this->get(4));
|
||||
$this->data["unknown1"] = Utils::readInt($this->get(4));
|
||||
$this->data["gamemode"] = Utils::readInt($this->get(4));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
$this->data["z"] = Utils::readFloat($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["seed"]);
|
||||
$this->raw .= Utils::writeInt($this->data["unknown1"]);
|
||||
$this->raw .= Utils::writeInt($this->data["gamemode"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
}
|
||||
break;
|
||||
case MC_ADD_MOB:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["type"] = Utils::readInt($this->get(4));
|
||||
$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["metadata"] = Utils::readMetadata($this->get(true));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["type"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
$this->raw .= Utils::writeMetadata($this->data["metadata"]);
|
||||
}
|
||||
break;
|
||||
case MC_ADD_PLAYER:
|
||||
if($this->c === false){
|
||||
$this->data["clientID"] = Utils::readLong($this->get(8));
|
||||
$this->data["username"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$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["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"];
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
$this->raw .= Utils::writeMetadata($this->data["metadata"]);
|
||||
}
|
||||
break;
|
||||
case MC_ADD_ENTITY: //Not used?
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["type"] = ord($this->get(1));
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
$this->data["z"] = Utils::readFloat($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= chr($this->data["type"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
$this->raw .= Utils::hexToStr("000000020000ffd30000");//Utils::writeInt(0);
|
||||
}
|
||||
break;
|
||||
case MC_REMOVE_ENTITY:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
}
|
||||
break;
|
||||
case MC_ADD_ITEM_ENTITY:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["block"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["stack"] = ord($this->get(1));
|
||||
$this->data["meta"] = Utils::readShort($this->get(2), false);
|
||||
$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::readByte($this->get(1));
|
||||
$this->data["pitch"] = Utils::readByte($this->get(1));
|
||||
$this->data["roll"] = Utils::readByte($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeShort($this->data["block"]);
|
||||
$this->raw .= chr($this->data["stack"]);
|
||||
$this->raw .= Utils::writeShort($this->data["meta"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
$this->raw .= Utils::writeByte($this->data["yaw"]);
|
||||
$this->raw .= Utils::writeByte($this->data["pitch"]);
|
||||
$this->raw .= Utils::writeByte($this->data["roll"]);
|
||||
}
|
||||
break;
|
||||
case MC_TAKE_ITEM_ENTITY:
|
||||
if($this->c === false){
|
||||
$this->data["target"] = Utils::readInt($this->get(4));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["target"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_ENTITY:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
$this->data["z"] = Utils::readFloat($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_ENTITY_POSROT:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$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));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$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"]);
|
||||
}
|
||||
break;
|
||||
case MC_MOVE_PLAYER:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$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));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$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"]);
|
||||
}
|
||||
break;
|
||||
case MC_PLACE_BLOCK:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["y"] = ord($this->get(1));
|
||||
$this->data["block"] = ord($this->get(1));
|
||||
$this->data["meta"] = ord($this->get(1));
|
||||
$this->data["face"] = Utils::readByte($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
$this->raw .= chr($this->data["y"]);
|
||||
$this->raw .= chr($this->data["block"]);
|
||||
$this->raw .= chr($this->data["meta"]);
|
||||
$this->raw .= chr($this->data["face"]);
|
||||
}
|
||||
break;
|
||||
case MC_REMOVE_BLOCK:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["y"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
$this->raw .= chr($this->data["y"]);
|
||||
}
|
||||
break;
|
||||
case MC_UPDATE_BLOCK:
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["y"] = ord($this->get(1));
|
||||
$this->data["block"] = ord($this->get(1));
|
||||
$this->data["meta"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
$this->raw .= chr($this->data["y"]);
|
||||
$this->raw .= chr($this->data["block"]);
|
||||
$this->raw .= chr($this->data["meta"]);
|
||||
}
|
||||
break;
|
||||
case MC_ADD_PAINTING:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["y"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["direction"] = Utils::readInt($this->get(4));
|
||||
$this->data["title"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["y"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
$this->raw .= Utils::writeInt($this->data["direction"]);
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["title"])).$this->data["title"];
|
||||
}
|
||||
break;
|
||||
case MC_EXPLOSION:
|
||||
if($this->c === false){
|
||||
$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["radius"] = Utils::readFloat($this->get(4));
|
||||
$this->data["count"] = Utils::readInt($this->get(4));
|
||||
$this->data["records"] = array();
|
||||
for($r = 0; $r < $this->data["count"]; ++$r){
|
||||
$this->data["records"][] = array(Utils::readByte($this->get(1)), Utils::readByte($this->get(1)), Utils::readByte($this->get(1)));
|
||||
}
|
||||
}else{
|
||||
$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["radius"]);
|
||||
$this->data["records"] = (array) $this->data["records"];
|
||||
$this->raw .= Utils::writeInt(count($this->data["records"]));
|
||||
if(count($this->data["records"]) > 0){
|
||||
foreach($this->data["records"] as $record){
|
||||
$this->raw .= Utils::writeByte($record[0]) . Utils::writeByte($record[1]) . Utils::writeByte($record[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_ENTITY_EVENT:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["event"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= chr($this->data["event"]);
|
||||
}
|
||||
break;
|
||||
case MC_REQUEST_CHUNK:
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
}
|
||||
break;
|
||||
case MC_CHUNK_DATA:
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["data"] = $this->get(true);
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
$this->raw .= $this->data["data"];
|
||||
}
|
||||
break;
|
||||
case MC_PLAYER_EQUIPMENT:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["block"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["meta"] = Utils::readShort($this->get(2), false);
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeShort($this->data["block"]);
|
||||
$this->raw .= Utils::writeShort($this->data["meta"]);
|
||||
}
|
||||
break;
|
||||
case MC_PLAYER_ARMOR_EQUIPMENT:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["slot0"] = ord($this->get(1));
|
||||
$this->data["slot1"] = ord($this->get(1));
|
||||
$this->data["slot2"] = ord($this->get(1));
|
||||
$this->data["slot3"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= chr($this->data["slot0"]);
|
||||
$this->raw .= chr($this->data["slot1"]);
|
||||
$this->raw .= chr($this->data["slot2"]);
|
||||
$this->raw .= chr($this->data["slot3"]);
|
||||
}
|
||||
break;
|
||||
case MC_INTERACT:
|
||||
if($this->c === false){
|
||||
$this->data["action"] = Utils::readByte($this->get(1));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["target"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeByte($this->data["action"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["target"]);
|
||||
}
|
||||
break;
|
||||
case MC_USE_ITEM:
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["y"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["face"] = Utils::readInt($this->get(4));
|
||||
$this->data["block"] = Utils::readShort($this->get(2));
|
||||
$this->data["meta"] = Utils::readByte($this->get(1));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["fx"] = Utils::readFloat($this->get(4));
|
||||
$this->data["fy"] = Utils::readFloat($this->get(4));
|
||||
$this->data["fz"] = Utils::readFloat($this->get(4));
|
||||
}else{
|
||||
/*$this->raw .= Utils::writeByte($this->data["action"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeInt($this->data["target"]);*/
|
||||
}
|
||||
break;
|
||||
case MC_PLAYER_ACTION:
|
||||
//TODO
|
||||
break;
|
||||
case MC_SET_ENTITY_DATA:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["metadata"] = Utils::readMetadata($this->get(true));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeMetadata($this->data["metadata"]);
|
||||
}
|
||||
break;
|
||||
case MC_SET_ENTITY_MOTION:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["speedX"] = Utils::readShort($this->get(2));
|
||||
$this->data["speedY"] = Utils::readShort($this->get(2));
|
||||
$this->data["speedZ"] = Utils::readShort($this->get(2));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeShort($this->data["speedX"]);
|
||||
$this->raw .= Utils::writeShort($this->data["speedY"]);
|
||||
$this->raw .= Utils::writeShort($this->data["speedZ"]);
|
||||
}
|
||||
break;
|
||||
case MC_HURT_ARMOR:
|
||||
if($this->c === false){
|
||||
$this->data["health"] = Utils::readByte($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeByte($this->data["health"]);
|
||||
}
|
||||
break;
|
||||
case MC_SET_HEALTH:
|
||||
if($this->c === false){
|
||||
$this->data["health"] = Utils::readByte($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeByte($this->data["health"]);
|
||||
}
|
||||
break;
|
||||
case MC_SET_SPAWN_POSITION:
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readInt($this->get(4));
|
||||
$this->data["z"] = Utils::readInt($this->get(4));
|
||||
$this->data["y"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["x"]);
|
||||
$this->raw .= Utils::writeInt($this->data["z"]);
|
||||
$this->raw .= chr($this->data["y"]);
|
||||
}
|
||||
break;
|
||||
case MC_ANIMATE:
|
||||
if($this->c === false){
|
||||
$this->data["action"] = Utils::readByte($this->get(1));
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeByte($this->data["action"]);
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
}
|
||||
break;
|
||||
case MC_RESPAWN:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["x"] = Utils::readFloat($this->get(4));
|
||||
$this->data["y"] = Utils::readFloat($this->get(4));
|
||||
$this->data["z"] = Utils::readFloat($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["x"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["y"]);
|
||||
$this->raw .= Utils::writeFloat($this->data["z"]);
|
||||
}
|
||||
break;
|
||||
case MC_SEND_INVENTORY:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["windowid"] = ord($this->get(1));
|
||||
$this->data["count"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["slots"] = array();
|
||||
for($s = 0; $s < $this->data["count"]; ++$s){
|
||||
$this->data["slots"][$s] = Utils::readSlot($this->get(5));
|
||||
}
|
||||
if($this->data["windowid"] === 1){ //Armor is also sent
|
||||
$this->data["armor"] = array(
|
||||
Utils::readSlot($this->get(5)),
|
||||
Utils::readSlot($this->get(5)),
|
||||
Utils::readSlot($this->get(5)),
|
||||
Utils::readSlot($this->get(5))
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= chr($this->data["windowid"]);
|
||||
$this->raw .= Utils::writeShort(count($this->data["slots"]));
|
||||
foreach($this->data["slots"] as $slot){
|
||||
$this->raw .= Utils::writeSlot($slot);
|
||||
}
|
||||
if($this->data["windowid"] === 1 and isset($this->data["armor"])){
|
||||
$this->raw .= Utils::writeSlot($this->data["armor"][0]);
|
||||
$this->raw .= Utils::writeSlot($this->data["armor"][1]);
|
||||
$this->raw .= Utils::writeSlot($this->data["armor"][2]);
|
||||
$this->raw .= Utils::writeSlot($this->data["armor"][3]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_DROP_ITEM:
|
||||
if($this->c === false){
|
||||
$this->data["eid"] = Utils::readInt($this->get(4));
|
||||
$this->data["unknown1"] = ord($this->get(1));
|
||||
$this->data["block"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["stack"] = ord($this->get(1));
|
||||
$this->data["meta"] = Utils::readShort($this->get(2), false);
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["eid"]);
|
||||
$this->raw .= chr($this->data["unknown1"]);
|
||||
$this->raw .= Utils::writeShort($this->data["block"]);
|
||||
$this->raw .= chr($this->data["stack"]);
|
||||
$this->raw .= Utils::writeShort($this->data["meta"]);
|
||||
}
|
||||
break;
|
||||
case MC_CONTAINER_OPEN:
|
||||
if($this->c === false){
|
||||
$this->data["windowid"] = ord($this->get(1));
|
||||
$this->data["type"] = ord($this->get(1));
|
||||
$this->data["slots"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["title"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
}else{
|
||||
$this->raw .= chr($this->data["windowid"]);
|
||||
$this->raw .= chr($this->data["type"]);
|
||||
$this->raw .= Utils::writeShort($this->data["slots"]);
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["title"])).$this->data["title"];
|
||||
}
|
||||
break;
|
||||
case MC_CONTAINER_CLOSE:
|
||||
if($this->c === false){
|
||||
$this->data["windowid"] = ord($this->get(1));
|
||||
}else{
|
||||
$this->raw .= chr($this->data["windowid"]);
|
||||
}
|
||||
break;
|
||||
case MC_CONTAINER_SET_SLOT:
|
||||
if($this->c === false){
|
||||
$this->data["windowid"] = ord($this->get(1));
|
||||
$this->data["slot"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["block"] = Utils::readShort($this->get(2), false);
|
||||
$this->data["stack"] = ord($this->get(1));
|
||||
$this->data["meta"] = Utils::readShort($this->get(2), false);
|
||||
}else{
|
||||
$this->raw .= chr($this->data["windowid"]);
|
||||
$this->raw .= Utils::writeShort($this->data["slot"]);
|
||||
$this->raw .= Utils::writeShort($this->data["block"]);
|
||||
$this->raw .= chr($this->data["stack"]);
|
||||
$this->raw .= Utils::writeShort($this->data["meta"]);
|
||||
}
|
||||
break;
|
||||
case MC_CLIENT_MESSAGE:
|
||||
if($this->c === false){
|
||||
$this->data["message"] = $this->get(Utils::readShort($this->get(2), false));
|
||||
}else{
|
||||
$this->raw .= Utils::writeShort(strlen($this->data["message"])).$this->data["message"];
|
||||
}
|
||||
break;
|
||||
case MC_SIGN_UPDATE:
|
||||
if($this->c === false){
|
||||
$this->data["x"] = Utils::readShort($this->get(2));
|
||||
$this->data["y"] = ord($this->get(1));
|
||||
$this->data["z"] = Utils::readShort($this->get(2));
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
$this->data["line$i"] = $this->get(Utils::readLShort($this->get(2), false));
|
||||
}
|
||||
}else{
|
||||
$this->raw .= Utils::writeShort($this->data["x"]);
|
||||
$this->raw .= chr($this->data["y"]);
|
||||
$this->raw .= Utils::writeShort($this->data["z"]);
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
$this->raw .= Utils::writeLShort(strlen($this->data["line$i"])).$this->data["line$i"];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MC_ADVENTURE_SETTINGS:
|
||||
if($this->c === false){
|
||||
$this->data["flags"] = Utils::readInt($this->get(4));
|
||||
}else{
|
||||
$this->raw .= Utils::writeInt($this->data["flags"]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if($this->c === false){
|
||||
console("[DEBUG] Received unknown Data Packet ID 0x".dechex($pid), true, true, 2);
|
||||
}else{
|
||||
console("[DEBUG] Sent unknown Data Packet ID 0x".dechex($pid), true, true, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
126
src/network/MinecraftInterface.php
Normal file
126
src/network/MinecraftInterface.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ PocketMine \
|
||||
/ MP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class MinecraftInterface{
|
||||
public $client;
|
||||
private $socket;
|
||||
private $data;
|
||||
function __construct($server, $port = 25565, $listen = false, $client = false, $serverip = "0.0.0.0"){
|
||||
$this->socket = new UDPSocket($server, $port, (bool) $listen, $serverip);
|
||||
$this->client = (bool) $client;
|
||||
$this->start = microtime(true);
|
||||
}
|
||||
|
||||
public function close(){
|
||||
return $this->socket->close(false);
|
||||
}
|
||||
|
||||
protected function getStruct($pid){
|
||||
if(isset(Protocol::$raknet[$pid])){
|
||||
return Protocol::$raknet[$pid];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function writeDump($pid, $raw, $data, $origin = "client", $ip = "", $port = 0){
|
||||
if(LOG === true and DEBUG >= 3){
|
||||
$p = "[".(microtime(true) - $this->start)."] [".((($origin === "client" and $this->client === true) or ($origin === "server" and $this->client === false)) ? "CLIENT->SERVER":"SERVER->CLIENT")." ".$ip.":".$port."]: ".(isset($data["id"]) ? "MC Packet ".Protocol::$dataName[$pid]:Protocol::$packetName[$pid])." (0x".Utils::strTohex(chr($pid)).") [length ".strlen($raw)."]".PHP_EOL;
|
||||
$p .= Utils::hexdump($raw);
|
||||
if(is_array($data)){
|
||||
foreach($data as $i => $d){
|
||||
$p .= $i ." => ".(!is_array($d) ? Protocol::$raknet[$pid][$i]."(".((Protocol::$raknet[$pid][$i] === "magic" or substr(Protocol::$raknet[$pid][$i], 0, 7) === "special" or is_int(Protocol::$raknet[$pid][$i])) ? Utils::strToHex($d):Utils::printable($d)).")":Protocol::$raknet[$pid][$i]."(\"".serialize(array_map("Utils::printable", $d))."\")").PHP_EOL;
|
||||
}
|
||||
}
|
||||
$p .= PHP_EOL;
|
||||
logg($p, "packets", false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function readPacket(){
|
||||
$p = $this->popPacket();
|
||||
if($p !== false){
|
||||
return $p;
|
||||
}
|
||||
if($this->socket->connected === false){
|
||||
return false;
|
||||
}
|
||||
$data = $this->socket->read();
|
||||
if($data[3] === false){
|
||||
return false;
|
||||
}
|
||||
$pid = ord($data[0]);
|
||||
$struct = $this->getStruct($pid);
|
||||
if($struct === false){
|
||||
console("[ERROR] Unknown Packet ID 0x".Utils::strToHex(chr($pid)), true, true, 0);
|
||||
$p = "[".(microtime(true) - $this->start)."] [".((($origin === "client" and $this->client === true) or ($origin === "server" and $this->client === false)) ? "CLIENT->SERVER":"SERVER->CLIENT")." ".$ip.":".$port."]: Error, bad packet id 0x".Utils::strTohex(chr($pid))." [length ".strlen($raw)."]".PHP_EOL;
|
||||
$p .= Utils::hexdump($data[0]);
|
||||
$p .= PHP_EOL;
|
||||
logg($p, "packets", true, 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
$packet = new Packet($pid, $struct, $data[0]);
|
||||
@$packet->parse();
|
||||
$this->data[] = array($pid, $packet->data, $data[0], $data[1], $data[2]);
|
||||
return $this->popPacket();
|
||||
}
|
||||
|
||||
public function popPacket(){
|
||||
if(count($this->data) > 0){
|
||||
$p = array_shift($this->data);
|
||||
if(isset($p[1]["packets"]) and is_array($p[1]["packets"])){
|
||||
foreach($p[1]["packets"] as $d){
|
||||
$this->data[] = array($p[0], $d[1], $d[2], $p[3], $p[4]);
|
||||
}
|
||||
}
|
||||
$c = (isset($p[1]["id"]) ? true:false);
|
||||
$p[2] = $c ? chr($p[1]["id"]).$p[2]:$p[2];
|
||||
$this->writeDump(($c ? $p[1]["id"]:$p[0]), $p[2], $p[1], "server", $p[3], $p[4]);
|
||||
return array("pid" => $p[0], "data" => $p[1], "raw" => $p[2], "ip" => $p[3], "port" => $p[4]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function writePacket($pid, $data = array(), $raw = false, $dest = false, $port = false){
|
||||
$struct = $this->getStruct($pid);
|
||||
if($raw === false){
|
||||
$packet = new Packet($pid, $struct);
|
||||
$packet->data = $data;
|
||||
@$packet->create();
|
||||
$write = $this->socket->write($packet->raw, $dest, $port);
|
||||
$this->writeDump($pid, $packet->raw, $data, "client", $dest, $port);
|
||||
}else{
|
||||
$write = $this->socket->write($data, $dest, $port);
|
||||
$this->writeDump($pid, $data, false, "client", $dest, $port);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
238
src/network/Packet.php
Normal file
238
src/network/Packet.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ PocketMine \
|
||||
/ MP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class Packet{
|
||||
private $struct, $sock;
|
||||
protected $pid, $packet;
|
||||
public $data, $raw;
|
||||
|
||||
function __construct($pid, $struct, $data = ""){
|
||||
$this->pid = $pid;
|
||||
$this->offset = 1;
|
||||
$this->raw = $data;
|
||||
$this->data = array();
|
||||
if($data === ""){
|
||||
$this->addRaw(chr($pid));
|
||||
}
|
||||
$this->struct = $struct;
|
||||
$this->sock = $sock;
|
||||
}
|
||||
|
||||
public function create($raw = false){
|
||||
foreach($this->struct as $field => $type){
|
||||
if(!isset($this->data[$field])){
|
||||
$this->data[$field] = "";
|
||||
}
|
||||
if($raw === true){
|
||||
$this->addRaw($this->data[$field]);
|
||||
continue;
|
||||
}
|
||||
if(is_int($type)){
|
||||
$this->addRaw($this->data[$field]);
|
||||
continue;
|
||||
}
|
||||
switch($type){
|
||||
case "special1":
|
||||
switch($this->pid){
|
||||
case 0xc0:
|
||||
case 0xa0:
|
||||
if($this->data[1] === false){
|
||||
$this->addRaw($this->data[$field]);
|
||||
}
|
||||
break;
|
||||
case 0x05:
|
||||
$this->addRaw($this->data[$field]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "customData":
|
||||
switch($this->data[1]){
|
||||
case 0x40:
|
||||
$reply = new CustomPacketHandler($this->data[$field]["id"], "", $this->data[$field], true);
|
||||
$this->addRaw(Utils::writeShort((strlen($reply->raw) + 1) << 3));
|
||||
$this->addRaw(Utils::writeTriad(strrev($this->data[$field]["count"])));
|
||||
$this->addRaw(chr($this->data[$field]["id"]));
|
||||
$this->addRaw($reply->raw);
|
||||
break;
|
||||
case 0x00:
|
||||
$reply = new CustomPacketHandler($this->data[$field]["id"], "", $this->data[$field], true);
|
||||
$this->addRaw(Utils::writeShort((strlen($reply->raw) + 1) << 3));
|
||||
$this->addRaw(chr($this->data[$field]["id"]));
|
||||
$this->addRaw($reply->raw);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "magic":
|
||||
$this->addRaw(MAGIC);
|
||||
break;
|
||||
case "float":
|
||||
$this->addRaw(Utils::writeFloat($this->data[$field]));
|
||||
break;
|
||||
case "triad":
|
||||
$this->addRaw(Utils::writeTriad($this->data[$field]));
|
||||
break;
|
||||
case "itriad":
|
||||
$this->addRaw(strrev(Utils::writeTriad($this->data[$field])));
|
||||
break;
|
||||
case "int":
|
||||
$this->addRaw(Utils::writeInt($this->data[$field]));
|
||||
break;
|
||||
case "double":
|
||||
$this->addRaw(Utils::writeDouble($this->data[$field]));
|
||||
break;
|
||||
case "long":
|
||||
$this->addRaw(Utils::writeLong($this->data[$field]));
|
||||
break;
|
||||
case "bool":
|
||||
case "boolean":
|
||||
$this->addRaw(Utils::writeBool($this->data[$field]));
|
||||
break;
|
||||
case "ubyte":
|
||||
case "byte":
|
||||
$this->addRaw(Utils::writeByte($this->data[$field]));
|
||||
break;
|
||||
case "short":
|
||||
$this->addRaw(Utils::writeShort($this->data[$field]));
|
||||
break;
|
||||
case "byteArray":
|
||||
$this->addRaw($this->data[$field]);
|
||||
break;
|
||||
case "string":
|
||||
$this->addRaw(Utils::writeShort(strlen($this->data[$field])));
|
||||
$this->addRaw($this->data[$field]);
|
||||
break;
|
||||
case "slotData":
|
||||
$this->addRaw(Utils::writeShort($this->data[$field][0]));
|
||||
if($this->data[$field][0]!=-1){
|
||||
$this->addRaw(Utils::writeByte($this->data[$field][1]));
|
||||
$this->addRaw(Utils::writeShort($this->data[$field][2]));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->addRaw(Utils::writeByte($this->data[$field]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function get($len = true){
|
||||
if($len === true){
|
||||
$data = substr($this->raw, $this->offset);
|
||||
$this->offset = strlen($this->raw);
|
||||
return $data;
|
||||
}
|
||||
$data = substr($this->raw, $this->offset, $len);
|
||||
$this->offset += $len;
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function addRaw($str){
|
||||
$this->raw .= $str;
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function parse(){
|
||||
$continue = true;
|
||||
foreach($this->struct as $field => $type){
|
||||
if(is_int($type)){
|
||||
$this->data[] = $this->get($type);
|
||||
continue;
|
||||
}
|
||||
switch($type){
|
||||
case "special1":
|
||||
switch($this->pid){
|
||||
case 0xc0:
|
||||
case 0xa0:
|
||||
if($this->data[1] === false){
|
||||
$this->data[] = $this->get(3);
|
||||
}
|
||||
break;
|
||||
case 0x05:
|
||||
$this->data[] = $this->get(true);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "customData":
|
||||
$d = new SerializedPacketHandler($this->data[1], $this->get(true));
|
||||
if(isset($d->data["packets"])){
|
||||
$this->data["packets"] = $d->data["packets"];
|
||||
}else{
|
||||
$this->data[] = $d->data;
|
||||
}
|
||||
break;
|
||||
case "magic":
|
||||
$this->data[] = $this->get(16);
|
||||
break;
|
||||
case "triad":
|
||||
$this->data[] = Utils::readTriad($this->get(3));
|
||||
break;
|
||||
case "itriad":
|
||||
$this->data[] = Utils::readTriad(strrev($this->get(3)));
|
||||
break;
|
||||
case "int":
|
||||
$this->data[] = Utils::readInt($this->get(4));
|
||||
break;
|
||||
case "string":
|
||||
$this->data[] = $this->get(Utils::readShort($this->get(2)));
|
||||
break;
|
||||
case "long":
|
||||
$this->data[] = Utils::readLong($this->get(8));
|
||||
break;
|
||||
case "byte":
|
||||
$this->data[] = Utils::readByte($this->get(1));
|
||||
break;
|
||||
case "ubyte":
|
||||
$this->data[] = ord($this->get(1));
|
||||
break;
|
||||
case "float":
|
||||
$this->data[] = Utils::readFloat($this->get(4));
|
||||
break;
|
||||
case "double":
|
||||
$this->data[] = Utils::readDouble($this->get(8));
|
||||
break;
|
||||
case "ushort":
|
||||
$this->data[] = Utils::readShort($this->get(2), false);
|
||||
break;
|
||||
case "short":
|
||||
$this->data[] = Utils::readShort($this->get(2));
|
||||
break;
|
||||
case "bool":
|
||||
case "boolean":
|
||||
$this->data[] = Utils::readBool($this->get(1));
|
||||
break;
|
||||
}
|
||||
if($continue === false){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
87
src/network/SerializedPacketHandler.php
Normal file
87
src/network/SerializedPacketHandler.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ PocketMine \
|
||||
/ MP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class SerializedPacketHandler{
|
||||
var $offset, $raw, $c, $data, $name = "";
|
||||
|
||||
private function get($len = true, $check = true){
|
||||
if($len === true){
|
||||
$data = substr($this->raw, $this->offset);
|
||||
if($check === true){
|
||||
$this->offset = strlen($this->raw);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
$data = substr($this->raw, $this->offset, $len);
|
||||
if($check === true){
|
||||
$this->offset += $len;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function __construct($pid, $raw = "", $data = array(), $create = false){
|
||||
$this->raw = $raw;
|
||||
$this->data = $data;
|
||||
$this->offset = 0;
|
||||
$this->c = (bool) $create;
|
||||
switch($pid){
|
||||
case 0x60:
|
||||
case 0x40:
|
||||
case 0x00:
|
||||
if($this->c === false){
|
||||
$this->data["packets"] = array();
|
||||
$i = 0;
|
||||
while($this->offset < strlen($this->raw)){
|
||||
if($i > 0){
|
||||
$pid = ord($this->get(1));
|
||||
}
|
||||
|
||||
$len = ceil(Utils::readShort($this->get(2), false) / 8); //Utils::readShort($this->get(2), false) >> 3;
|
||||
if($pid !== 0x00){
|
||||
$c = Utils::readTriad(strrev($this->get(3)));
|
||||
}
|
||||
if($pid === 0x60 and $i === 0){
|
||||
$this->data["unknown1"] = $this->get(4);
|
||||
}
|
||||
$id = ord($this->get(1));
|
||||
$raw = $this->get($len - 1);
|
||||
$pk = new CustomPacketHandler($id, $raw);
|
||||
$pk->data["length"] = $len;
|
||||
$pk->data["id"] = $id;
|
||||
if($pid !== 0x00){
|
||||
$pk->data["counter"] = $c;
|
||||
}
|
||||
$pk->data["packetName"] = $pk->name;
|
||||
$this->data["packets"][] = array($pid, $pk->data, $raw);
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
92
src/network/UDPSocket.php
Normal file
92
src/network/UDPSocket.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ PocketMine \
|
||||
/ MP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class UDPSocket{
|
||||
private $encrypt;
|
||||
var $buffer, $connected, $errors, $sock, $server;
|
||||
function __construct($server, $port, $listen = false, $serverip = "0.0.0.0"){
|
||||
$this->errors = array_fill(88,(125 - 88) + 1, true);
|
||||
$this->server = $server;
|
||||
$this->port = $port;
|
||||
$this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||
socket_set_option($this->sock, SOL_SOCKET, SO_BROADCAST, 1); //Allow sending broadcast messages
|
||||
if($listen !== true){
|
||||
$this->connected = true;
|
||||
$this->buffer = array();
|
||||
$this->unblock();
|
||||
}else{
|
||||
if(socket_bind($this->sock, $serverip, $port) === true){
|
||||
$this->unblock();
|
||||
}else{
|
||||
console("[ERROR] Couldn't bind to $serverip:".$port, true, true, 0);
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function listenSocket(){
|
||||
$sock = @socket_accept($this->sock);
|
||||
if($sock !== false){
|
||||
$sock = new Socket(false, false, false, $sock);
|
||||
$sock->unblock();
|
||||
return $sock;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function close($error = 125){
|
||||
$this->connected = false;
|
||||
if($error !== false){
|
||||
console("[ERROR] [Socket] Socket closed, Error $error: ".socket_strerror($error));
|
||||
}
|
||||
return @socket_close($this->sock);
|
||||
}
|
||||
|
||||
public function block(){
|
||||
socket_set_block($this->sock);
|
||||
}
|
||||
|
||||
public function unblock(){
|
||||
socket_set_nonblock($this->sock);
|
||||
}
|
||||
|
||||
public function read(){
|
||||
$source = false;
|
||||
$port = 1;
|
||||
$len = @socket_recvfrom($this->sock, $buf, 65536, 0, $source, $port);
|
||||
return array($buf, $source, $port, $len);
|
||||
}
|
||||
|
||||
public function write($data, $dest = false, $port = false){
|
||||
return @socket_sendto($this->sock, $data, strlen($data), 0, ($dest === false ? $this->server:$dest), ($port === false ? $this->port:$port));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
Reference in New Issue
Block a user