Merge pull request #1188 from PocketMine/Faster-Network

Merge Faster-Network into master. Added new Networking system, new Event system
This commit is contained in:
Shoghi Cervantes 2014-02-10 19:07:12 +01:00
commit 5bdb61117f
93 changed files with 4848 additions and 2866 deletions

View File

@ -317,13 +317,13 @@ class BlockAPI{
} }
private function cancelAction(Block $block, Player $player, $send = true){ private function cancelAction(Block $block, Player $player, $send = true){
$player->dataPacket(MC_UPDATE_BLOCK, array( $pk = new UpdateBlockPacket;
"x" => $block->x, $pk->x = $block->x;
"y" => $block->y, $pk->y = $block->y;
"z" => $block->z, $pk->z = $block->z;
"block" => $block->getID(), $pk->block = $block->getID();
"meta" => $block->getMetadata() $pk->meta = $block->getMetadata();
)); $player->dataPacket($pk);
if($send === true){ if($send === true){
$player->sendInventorySlot($player->slot); $player->sendInventorySlot($player->slot);
} }
@ -459,363 +459,6 @@ class BlockAPI{
return false; return false;
} }
/*
public function flowLavaOn($source, $face){
$down = 0;
if($face === BlockFace::BOTTOM){
$level = 0;
$down = 1;
}else{
$level = ($source[1] & 0x07) + 2;
if($level > 0x07){
return false;
}
}
$spread = $this->server->api->level->getBlockFace($source, $face);
if(($source[0] === 10 or $source[0] === 11) and $spread[0] === 10){
if($level < ($spread[1] & 0x07)){
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $spread[2][0],
"y" => $spread[2][1],
"z" => $spread[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $spread[0], $level | $down, false);
return true;
}
}elseif($spread[0] === 9 or $spread[0] === 8){
if($source[0] === 11){
$this->server->api->level->setBlock($source[2][0], $source[2][1], $source[2][2], 49, 0);
}elseif($face === 0){
$this->server->api->level->setBlock($source[2][0], $source[2][1], $source[2][2], 1, 0);
}else{
$this->server->api->level->setBlock($source[2][0], $source[2][1], $source[2][2], 4, 0);
}
return true;
}elseif(isset(Material::$flowable[$spread[0]])){
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $spread[2][0],
"y" => $spread[2][1],
"z" => $spread[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 10, $level | $down, false);
return true;
}elseif(($source[1] & 0x08) === 0x08){
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $source[0], $source[1] & 0x07, false);
return true;
}
return false;
}
public function flowWaterOn($source, $face, &$spread = null){
$down = 0;
if($face === BlockFace::BOTTOM){
$level = 0;
$down = 1;
}else{
$level = ($source[1] & 0x07) + 1;
if($level > 0x07){
return false;
}
}
$spread = $this->server->api->level->getBlockFace($source, $face);
if(($source[0] === 8 or $source[0] === 9) and $spread[0] === 8){
if($level < ($spread[1] & 0x07)){
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $spread[2][0],
"y" => $spread[2][1],
"z" => $spread[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $spread[0], $level | $down, false);
return true;
}
}elseif($spread[0] === 11){
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 49, 0, true);
return true;
}elseif($spread[0] === 10){
if($face === 0 or ($spread[1] & 0x08) === 0){
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 4, 0, true);
return true;
}
}elseif(isset(Material::$flowable[$spread[0]])){
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $spread[2][0],
"y" => $spread[2][1],
"z" => $spread[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 8, $level | $down, false);
return true;
}elseif(($source[1] & 0x08) === 0x08){
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $source[0], $source[1] & 0x07, false);
return true;
}
return false;
}
public function updateBlock($x, $y, $z, $type = BLOCK_UPDATE_NORMAL){
$block = $this->server->api->level->getBlock($x, $y, $z);
$changed = false;
switch($block[0]){
case 8:
case 9:
$faces = array();
if(!$this->flowWaterOn($block, 0, $floor) or $block[0] === 9){
$this->flowWaterOn($block, 2, $faces[0]);
$this->flowWaterOn($block, 3, $faces[1]);
$this->flowWaterOn($block, 4, $faces[2]);
$this->flowWaterOn($block, 5, $faces[3]);
}
if($block[0] === 8){
//Source creation
if(!isset(Material::$flowable[$floor[0]])){
$sources = 0;
foreach($faces as $i => $b){
if($b[0] === 9){
++$sources;
}
}
if($sources >= 2){
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 9, 0, false);
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
break;
}
}
$drained = true;
$level = $block[1] & 0x07;
$up = $this->server->api->level->getBlockFace($block, BlockFace::UP);
if($up[0] === 8 or $up[0] === 9){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::NORTH);
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::SOUTH);
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::EAST);
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::WEST);
if($b[0] === 9 or ($b[0] === 8 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}
}
}
}
}
if($drained === true){
++$level;
if($level > 0x07){
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0] + 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0] - 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] + 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] - 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1] - 1,
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0, false);
}else{
$block[1] = ($block[1] & 0x08) | $level;
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0] + 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0] - 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] + 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] - 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1] - 1,
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], $block[0], $block[1], false);
}
}
}
break;
case 10:
case 11:
if(!$this->flowLavaOn($block, 0) or $block[0] === 11){
$this->flowLavaOn($block, 2);
$this->flowLavaOn($block, 3);
$this->flowLavaOn($block, 4);
$this->flowLavaOn($block, 5);
}
if($block[0] === 10){
$drained = true;
$level = $block[1] & 0x07;
$up = $this->server->api->level->getBlockFace($block, BlockFace::UP);
if($up[0] === 10 or $up[0] === 11){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::NORTH);
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::SOUTH);
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::EAST);
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}else{
$b = $this->server->api->level->getBlockFace($block, BlockFace::WEST);
if($b[0] === 11 or ($b[0] === 10 and ($b[1] & 0x08) === 0 and ($b[1] & 0x07) < $level)){
$drained = false;
}
}
}
}
}
if($drained === true){
++$level;
if($level > 0x07){
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0] + 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0] - 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] + 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] - 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1] - 1,
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 0, 0, false);
}else{
$block[1] = ($block[1] & 0x08) | $level;
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0] + 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0] - 1,
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] + 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2] - 1,
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1] - 1,
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], $block[0], $block[1], false);
}
}
}
break;
}
if($type === BLOCK_TYPE_SCHEDULED){
$type = BLOCK_UPDATE_WEAK;
}
if($changed === true){
$this->updateBlocksAround($x, $y, $z, $type);
}
}*/
public function blockUpdateAround(Position $pos, $type = BLOCK_UPDATE_NORMAL, $delay = false){ public function blockUpdateAround(Position $pos, $type = BLOCK_UPDATE_NORMAL, $delay = false){
if($delay !== false){ if($delay !== false){
$this->scheduleBlockUpdate($pos->getSide(0), $delay, $type); $this->scheduleBlockUpdate($pos->getSide(0), $delay, $type);

View File

@ -157,14 +157,14 @@ class EntityAPI{
$entity->closed = true; $entity->closed = true;
$this->server->query("DELETE FROM entities WHERE EID = ".$eid.";"); $this->server->query("DELETE FROM entities WHERE EID = ".$eid.";");
if($entity->class === ENTITY_PLAYER){ if($entity->class === ENTITY_PLAYER){
$this->server->api->player->broadcastPacket($this->server->api->player->getAll(), MC_REMOVE_PLAYER, array( $pk = new RemovePlayerPacket;
"clientID" => 0, $pk->eid = $entity->eid;
"eid" => $entity->eid, $pk->clientID = 0;
)); $this->server->api->player->broadcastPacket($this->server->api->player->getAll(), $pk);
}else{ }else{
$this->server->api->player->broadcastPacket($this->server->api->player->getAll($entity->level), MC_REMOVE_ENTITY, array( $pk = new RemoveEntityPacket;
"eid" => $entity->eid, $pk->eid = $entity->eid;
)); $this->server->api->player->broadcastPacket($this->server->api->player->getAll($entity->level), $pk);
} }
$this->server->api->dhandle("entity.remove", $entity); $this->server->api->dhandle("entity.remove", $entity);
$entity = null; $entity = null;

View File

@ -353,11 +353,9 @@ class PlayerAPI{
return $this->server->clients; return $this->server->clients;
} }
public function broadcastPacket(array $players, $id, $data = array()){ public function broadcastPacket(array $players, RakNetDataPacket $packet){
$data = new CustomPacketHandler($id, "", $data, true);
$packet = array("raw" => chr($id).$data->raw);
foreach($players as $p){ foreach($players as $p){
$p->dataPacket(false, $packet); $p->dataPacket(clone $packet);
} }
} }
@ -404,14 +402,14 @@ class PlayerAPI{
if($p !== $player and ($p->entity instanceof Entity)){ if($p !== $player and ($p->entity instanceof Entity)){
$p->entity->spawn($player); $p->entity->spawn($player);
if($p->level !== $player->level){ if($p->level !== $player->level){
$player->dataPacket(MC_MOVE_ENTITY_POSROT, array( $pk = new MoveEntityPacket_PosRot;
"eid" => $p->entity->eid, $pk->eid = $p->entity->eid;
"x" => -256, $pk->x = -256;
"y" => 128, $pk->y = 128;
"z" => -256, $pk->z = -256;
"yaw" => 0, $pk->yaw = 0;
"pitch" => 0, $pk->pitch = 0;
)); $player->dataPacket($pk);
} }
} }
} }
@ -422,14 +420,14 @@ class PlayerAPI{
if($p !== $player and ($p->entity instanceof Entity) and ($player->entity instanceof Entity)){ if($p !== $player and ($p->entity instanceof Entity) and ($player->entity instanceof Entity)){
$player->entity->spawn($p); $player->entity->spawn($p);
if($p->level !== $player->level){ if($p->level !== $player->level){
$p->dataPacket(MC_MOVE_ENTITY_POSROT, array( $pk = new MoveEntityPacket_PosRot;
"eid" => $player->entity->eid, $pk->eid = $player->entity->eid;
"x" => -256, $pk->x = -256;
"y" => 128, $pk->y = 128;
"z" => -256, $pk->z = -256;
"yaw" => 0, $pk->yaw = 0;
"pitch" => 0, $pk->pitch = 0;
)); $p->dataPacket($pk);
} }
} }
} }

View File

@ -28,7 +28,8 @@ class ServerAPI{
private $apiList = array(); private $apiList = array();
private $asyncCnt = 0; private $asyncCnt = 0;
private $rcon; private $rcon;
private $query;
public $query;
//TODO: Instead of hard-coding functions, use PHPDoc-compatible methods to load APIs. //TODO: Instead of hard-coding functions, use PHPDoc-compatible methods to load APIs.
@ -97,6 +98,14 @@ class ServerAPI{
@mkdir(DATA_PATH."players/", 0755); @mkdir(DATA_PATH."players/", 0755);
@mkdir(DATA_PATH."worlds/", 0755); @mkdir(DATA_PATH."worlds/", 0755);
@mkdir(DATA_PATH."plugins/", 0755); @mkdir(DATA_PATH."plugins/", 0755);
//Init all the events
foreach(get_declared_classes() as $class){
if(is_subclass_of($class, "BaseEvent") and property_exists($class, "handlers") and property_exists($class, "handlerPriority")){
$class::unregisterAll();
}
}
$version = new VersionString(); $version = new VersionString();
console("[INFO] Starting Minecraft PE server version ".FORMAT_AQUA.CURRENT_MINECRAFT_VERSION); console("[INFO] Starting Minecraft PE server version ".FORMAT_AQUA.CURRENT_MINECRAFT_VERSION);
@ -134,28 +143,25 @@ class ServerAPI{
)); ));
$this->parseProperties(); $this->parseProperties();
//Load advanced properties
define("DEBUG", $this->getProperty("debug", 1)); define("DEBUG", $this->getProperty("debug", 1));
define("ADVANCED_CACHE", $this->getProperty("enable-advanced-cache", false)); define("ADVANCED_CACHE", $this->getProperty("enable-advanced-cache", false));
if($this->getProperty("port") !== false){ define("MAX_CHUNK_RATE", 20 / $this->getProperty("max-chunks-per-second", 8)); //Default rate ~512 kB/s
$this->setProperty("server-port", $this->getProperty("port")); if(ADVANCED_CACHE == true){
$this->config->remove("port"); console("[INFO] Advanced cache enabled");
$this->config->remove("invisible");
} }
if($this->getProperty("upnp-forwarding") == true){
console("[INFO] [UPnP] Trying to port forward...");
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 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->api = $this; $this->server->api = $this;
self::$serverRequest = $this->server; 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); 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);
console("[INFO] PocketMine-MP is distributed under the LGPL License", true, true, 0); console("[INFO] PocketMine-MP is distributed under the LGPL License", true, true, 0);
if(ADVANCED_CACHE == true){
console("[INFO] Advanced cache enabled");
}
if($this->getProperty("upnp-forwarding") === true){
console("[INFO] [UPnP] Trying to port forward...");
UPnP_PortForward($this->getProperty("server-port"));
}
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){ if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){
console("[INFO] Checking for new server version"); console("[INFO] Checking for new server version");
console("[INFO] Last check: ".FORMAT_AQUA.date("Y-m-d H:i:s", $this->getProperty("last-update"))."\x1b[0m"); console("[INFO] Last check: ".FORMAT_AQUA.date("Y-m-d H:i:s", $this->getProperty("last-update"))."\x1b[0m");
@ -257,7 +263,7 @@ class ServerAPI{
"php_version" => PHP_VERSION, "php_version" => PHP_VERSION,
"version" => MAJOR_VERSION, "version" => MAJOR_VERSION,
"mc_version" => CURRENT_MINECRAFT_VERSION, "mc_version" => CURRENT_MINECRAFT_VERSION,
"protocol" => CURRENT_PROTOCOL, "protocol" => ProtocolInfo::CURRENT_PROTOCOL,
"online" => count($this->server->clients), "online" => count($this->server->clients),
"max" => $this->server->maxClients, "max" => $this->server->maxClients,
"plugins" => $plist, "plugins" => $plist,
@ -349,7 +355,7 @@ class ServerAPI{
} }
if($this->getProperty("enable-query") === true){ if($this->getProperty("enable-query") === true){
$this->query = new Query(); $this->query = new QueryHandler();
} }
CraftingRecipes::init(); CraftingRecipes::init();
$this->server->init(); $this->server->init();

135
src/BaseEvent.php Normal file
View File

@ -0,0 +1,135 @@
<?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 BaseEvent{
const ALLOW = 0;
const DENY = 1;
const NORMAL = 2;
const FORCE = 0x80000000;
/**
* Any callable event must declare the static variables
*
* public static $handlers;
* public static $handlerPriority;
*
* Not doing so will deny the proper event initialization
*/
protected $eventName = null;
private $status = BaseEvent::NORMAL;
private $prioritySlot;
final public function getEventName(){
return $this->eventName !== null ? get_class($this) : $this->eventName;
}
final public function setPrioritySlot($slot){
$this->prioritySlot = (int) $slot;
}
final public function getPrioritySlot(){
return (int) $this->prioritySlot;
}
public function isAllowed(){
return ($this->status & 0x7FFFFFFF) === BaseEvent::ALLOW;
}
public function setAllowed($forceAllow = false){
$this->status = BaseEvent::ALLOW & ($forceAllow === true ? BaseEvent::FORCE : 0);
}
public function isCancelled(){
return ($this->status & 0x7FFFFFFF) === BaseEvent::DENY;
}
public function setCancelled($forceCancel = false){
if($this instanceof CancellableEvent){
$this->status = BaseEvent::DENY & ($forceCancel === true ? BaseEvent::FORCE : 0);
}
return false;
}
public function isNormal(){
return $this->status === BaseEvent::NORMAL;
}
public function setNormal(){
$this->status = BaseEvent::NORMAL;
}
public function isForced(){
return ($this->status & BaseEvent::FORCE) > 0;
}
public static function getHandlerList(){
return static::$handlers;
}
public static function getPriorityList(){
return static::$handlerPriority;
}
public static function unregisterAll(){
static::$handlers = array();
static::$handlerPriority = array();
}
public function register(callable $handler, $priority = EventPriority::NORMAL){
if($priority < EventPriority::MONITOR or $priority > EventPriority::LOWEST){
return false;
}
$identifier = Utils::getCallableIdentifier($handler);
if(isset(static::$handlers[$identifier])){ //Already registered
return false;
}else{
static::$handlers[$identifier] = $handler;
if(!isset(static::$handlerPriority[(int) $priority])){
static::$handlerPriority[(int) $priority] = array();
}
static::$handlerPriority[(int) $priority][$identifier] = $handler;
return true;
}
}
public function unregister(callable $handler, $priority = EventPriority::NORMAL){
$identifier = Utils::getCallableIdentifier($handler);
if(isset(static::$handlers[$identifier])){
if(isset(static::$handlerPriority[(int) $priority][$identifier])){
unset(static::$handlerPriority[(int) $priority][$identifier]);
}else{
for($priority = EventPriority::MONITOR; $priority <= EventPriority::LOWEST; ++$priority){
unset(static::$handlerPriority[$priority][$identifier]);
if(count(static::$handlerPriority[$priority]) === 0){
unset(static::$handlerPriority[$priority]);
}
}
}
unset(static::$handlers[$identifier]);
return true;
}else{
return false;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,7 @@ class PocketMinecraftServer{
$this->saveEnabled = true; $this->saveEnabled = true;
$this->tickMeasure = array_fill(0, 40, 0); $this->tickMeasure = array_fill(0, 40, 0);
$this->setType("normal"); $this->setType("normal");
$this->interface = new MinecraftInterface($this, "255.255.255.255", $this->port, true, false, $this->serverip); $this->interface = new MinecraftInterface("255.255.255.255", $this->port, $this->serverip);
$this->stop = false; $this->stop = false;
$this->ticks = 0; $this->ticks = 0;
if(!defined("NO_THREADS")){ if(!defined("NO_THREADS")){
@ -421,7 +421,7 @@ class PocketMinecraftServer{
} }
$dump .= "\r\n\r\n"; $dump .= "\r\n\r\n";
$version = new VersionString(); $version = new VersionString();
$dump .= "PocketMine-MP version: ".$version." #".$version->getNumber()." [Protocol ".CURRENT_PROTOCOL."; API ".CURRENT_API_VERSION."]\r\n"; $dump .= "PocketMine-MP version: ".$version." #".$version->getNumber()." [Protocol ".ProtocolInfo::CURRENT_PROTOCOL."; API ".CURRENT_API_VERSION."]\r\n";
$dump .= "Git commit: ".GIT_COMMIT."\r\n"; $dump .= "Git commit: ".GIT_COMMIT."\r\n";
$dump .= "Source SHA1 sum: ".SOURCE_SHA1SUM."\r\n"; $dump .= "Source SHA1 sum: ".SOURCE_SHA1SUM."\r\n";
$dump .= "uname -a: ".php_uname("a")."\r\n"; $dump .= "uname -a: ".php_uname("a")."\r\n";
@ -473,29 +473,30 @@ class PocketMinecraftServer{
} }
public static function clientID($ip, $port){ public static function clientID($ip, $port){
//faster than string indexes in PHP
return crc32($ip . $port) ^ crc32($port . $ip . BOOTUP_RANDOM); return crc32($ip . $port) ^ crc32($port . $ip . BOOTUP_RANDOM);
//return $ip . ":" . $port;
} }
public function packetHandler($packet){ public function packetHandler(Packet $packet){
$data =& $packet["data"]; $data =& $packet;
$CID = PocketMinecraftServer::clientID($packet["ip"], $packet["port"]); $CID = PocketMinecraftServer::clientID($packet->ip, $packet->port);
if(isset($this->clients[$CID])){ if(isset($this->clients[$CID])){
$this->clients[$CID]->handlePacket($packet["pid"], $data); $this->clients[$CID]->handlePacket($packet);
}else{ }else{
if($this->handle("server.noauthpacket", $packet) === false){ if($this->handle("server.noauthpacket.".$packet->pid(), $packet) === false){
return; return;
} }
switch($packet["pid"]){ switch($packet->pid()){
case 0x01: case RakNetInfo::UNCONNECTED_PING:
case 0x02: case RakNetInfo::UNCONNECTED_PING_OPEN_CONNECTIONS:
if($this->invisible === true){ if($this->invisible === true){
$this->send(0x1c, array( $pk = new RakNetPacket(RakNetInfo::UNCONNECTED_PONG);
$data[0], $pk->pingID = $packet->pingID;
$this->serverID, $pk->serverID = $this->serverID;
RAKNET_MAGIC, $pk->serverType = $this->serverType;
$this->serverType, $pk->ip = $packet->ip;
), false, $packet["ip"], $packet["port"]); $pk->port = $packet->port;
$this->send($pk);
break; break;
} }
if(!isset($this->custom["times_".$CID])){ if(!isset($this->custom["times_".$CID])){
@ -507,64 +508,59 @@ class PocketMinecraftServer{
} }
$txt = substr($this->description, $this->custom["times_".$CID], $ln); $txt = substr($this->description, $this->custom["times_".$CID], $ln);
$txt .= substr($this->description, 0, $ln - strlen($txt)); $txt .= substr($this->description, 0, $ln - strlen($txt));
$this->send(0x1c, array( $pk = new RakNetPacket(RakNetInfo::UNCONNECTED_PONG);
$data[0], $pk->pingID = $packet->pingID;
$this->serverID, $pk->serverID = $this->serverID;
RAKNET_MAGIC, $pk->serverType = $this->serverType . $this->name . " [".count($this->clients)."/".$this->maxClients."] ".$txt;
$this->serverType. $this->name . " [".count($this->clients)."/".$this->maxClients."] ".$txt, $pk->ip = $packet->ip;
), false, $packet["ip"], $packet["port"]); $pk->port = $packet->port;
$this->send($pk);
$this->custom["times_".$CID] = ($this->custom["times_".$CID] + 1) % strlen($this->description); $this->custom["times_".$CID] = ($this->custom["times_".$CID] + 1) % strlen($this->description);
break; break;
case 0x05: case RakNetInfo::OPEN_CONNECTION_REQUEST_1:
$version = $data[1]; if($packet->structure !== RakNetInfo::STRUCTURE){
$size = strlen($data[2]); console("[DEBUG] Incorrect structure #".$packet->structure." from ".$packet->ip.":".$packet->port, true, true, 2);
if($version !== CURRENT_STRUCTURE){ $pk = new RakNetPacket(RakNetInfo::INCOMPATIBLE_PROTOCOL_VERSION);
console("[DEBUG] Incorrect structure #$version from ".$packet["ip"].":".$packet["port"], true, true, 2); $pk->serverID = $this->serverID;
$this->send(0x1a, array( $pk->ip = $packet->ip;
CURRENT_STRUCTURE, $pk->port = $packet->port;
RAKNET_MAGIC, $this->send($pk);
$this->serverID,
), false, $packet["ip"], $packet["port"]);
}else{ }else{
$this->send(0x06, array( $pk = new RakNetPacket(RakNetInfo::OPEN_CONNECTION_REPLY_1);
RAKNET_MAGIC, $pk->serverID = $this->serverID;
$this->serverID, $pk->mtuSize = strlen($packet->buffer);
0, $pk->ip = $packet->ip;
strlen($packet["raw"]), $pk->port = $packet->port;
), false, $packet["ip"], $packet["port"]); $this->send($pk);
} }
break; break;
case 0x07: case RakNetInfo::OPEN_CONNECTION_REQUEST_2:
if($this->invisible === true){ if($this->invisible === true){
break; break;
} }
$port = $data[2];
$MTU = $data[3]; $this->clients[$CID] = new Player($packet->clientID, $packet->ip, $packet->port, $packet->mtuSize); //New Session!
$clientID = $data[4]; $pk = new RakNetPacket(RakNetInfo::OPEN_CONNECTION_REPLY_2);
if(count($this->clients) < $this->maxClients){ $pk->serverID = $this->serverID;
$this->clients[$CID] = new Player($clientID, $packet["ip"], $packet["port"], $MTU); //New Session! $pk->port = $this->port;
$this->send(0x08, array( $pk->mtuSize = $packet->mtuSize;
RAKNET_MAGIC, $pk->ip = $packet->ip;
$this->serverID, $pk->port = $packet->port;
$this->port, $this->send($pk);
$data[3],
0,
), false, $packet["ip"], $packet["port"]);
}
break; break;
} }
} }
} }
public function send($pid, $data = array(), $raw = false, $dest = false, $port = false){ public function send(Packet $packet){
return $this->interface->writePacket($pid, $data, $raw, $dest, $port); return $this->interface->writePacket($packet);
} }
public function process(){ public function process(){
$lastLoop = 0; $lastLoop = 0;
while($this->stop === false){ while($this->stop === false){
$packet = $this->interface->readPacket(); $packet = $this->interface->readPacket();
if($packet !== false){ if($packet instanceof Packet){
$this->packetHandler($packet); $this->packetHandler($packet);
$lastLoop = 0; $lastLoop = 0;
}else{ }else{

View File

@ -31,7 +31,6 @@ define("VIEWER", 3);
//Players //Players
define("MAX_CHUNK_RATE", 20 / arg("max-chunks-per-second", 4)); //Default rate ~256 kB/s
define("PLAYER_MAX_QUEUE", 1024); define("PLAYER_MAX_QUEUE", 1024);
define("PLAYER_SURVIVAL_SLOTS", 36); define("PLAYER_SURVIVAL_SLOTS", 36);

View File

@ -0,0 +1,28 @@
<?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/
*
*
*/
/**
* Events that can be cancelled must use the interface CancellableEvent
*/
interface CancellableEvent{
}

View File

@ -0,0 +1,52 @@
<?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 EventHandler{
public static function callEvent(BaseEvent $event){
$status = BaseEvent::NORMAL;
foreach($event::$handlerPriority as $priority => $handlerList){
if(count($handlerList) > 0){
$event->setPrioritySlot($priority);
foreach($handlerList as $handler){
call_user_func($handler, $event);
}
if($event->isForced()){
if($event instanceof CancellableEvent and $event->isCancelled()){
return BaseEvent::DENY;
}else{
return BaseEvent::ALLOW;
}
}
}
}
if($event instanceof CancellableEvent and $event->isCancelled()){
return BaseEvent::DENY;
}elseif($event->isAllowed()){
return BaseEvent::ALLOW;
}else{
return BaseEvent::NORMAL;
}
}
}

View File

@ -0,0 +1,52 @@
<?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 EventPriority{
/**
* Event call is of very low importance and should be ran first, to allow
* other plugins to further customise the outcome
*/
const LOWEST = 5;
/**
* Event call is of low importance
*/
const LOW = 4;
/**
* Event call is neither important or unimportant, and may be ran normally
*/
const NORMAL = 3;
/**
* Event call is of high importance
*/
const HIGH = 2;
/**
* Event call is critical and must have the final say in what happens
* to the event
*/
const HIGHEST = 1;
/**
* Event is listened to purely for monitoring the outcome of an event.
*
* No modifications to the event should be made under this priority
*/
const MONITOR = 0;
}

29
src/event/PluginEvent.php Normal file
View File

@ -0,0 +1,29 @@
<?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/
*
*
*/
/**
* Plugins that create events must use this class as the base
*/
abstract class PluginEvent extends BaseEvent{
}

24
src/event/ServerEvent.php Normal file
View File

@ -0,0 +1,24 @@
<?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 ServerEvent extends BaseEvent{
}

View File

@ -0,0 +1,40 @@
<?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 DataPacketReceiveEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
private $packet;
private $player;
public function __construct(Player $player, RakNetDataPacket $packet){
$this->packet = $packet;
}
public function getPacket(){
return $this->packet;
}
public function getPlayer(){
return $this->player;
}
}

View File

@ -0,0 +1,40 @@
<?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 DataPacketSendEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
private $packet;
private $player;
public function __construct(Player $player, RakNetDataPacket $packet){
$this->packet = $packet;
}
public function getPacket(){
return $this->packet;
}
public function getPlayer(){
return $this->player;
}
}

View File

@ -0,0 +1,36 @@
<?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 PacketReceiveEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
private $packet;
public function __construct(Packet $packet){
$this->packet = $packet;
}
public function getPacket(){
return $this->packet;
}
}

View File

@ -0,0 +1,36 @@
<?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 PacketSendEvent extends ServerEvent implements CancellableEvent{
public static $handlers;
public static $handlerPriority;
private $packet;
public function __construct(Packet $packet){
$this->packet = $packet;
}
public function getPacket(){
return $this->packet;
}
}

View File

@ -125,13 +125,13 @@ class DoorBlock extends TransparentBlock{
$this->level->setBlock($down, BlockAPI::get($this->id, $meta), true, false, true); $this->level->setBlock($down, BlockAPI::get($this->id, $meta), true, false, true);
$players = ServerAPI::request()->api->player->getAll($this->level); $players = ServerAPI::request()->api->player->getAll($this->level);
unset($players[$player->CID]); unset($players[$player->CID]);
ServerAPI::request()->api->player->broadcastPacket($players, MC_LEVEL_EVENT, array( $pk = new LevelEventPacket;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"evid" => 1003, $pk->evid = 1003;
"data" => 0 $pk->data = 0;
)); ServerAPI::request()->api->player->broadcastPacket($players, $pk);
return true; return true;
} }
return false; return false;
@ -140,13 +140,13 @@ class DoorBlock extends TransparentBlock{
$this->level->setBlock($this, $this, true, false, true); $this->level->setBlock($this, $this, true, false, true);
$players = ServerAPI::request()->api->player->getAll($this->level); $players = ServerAPI::request()->api->player->getAll($this->level);
unset($players[$player->CID]); unset($players[$player->CID]);
ServerAPI::request()->api->player->broadcastPacket($players, MC_LEVEL_EVENT, array( $pk = new LevelEventPacket;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"evid" => 1003, $pk->evid = 1003;
"data" => 0 $pk->data = 0;
)); ServerAPI::request()->api->player->broadcastPacket($players, $pk);
} }
return true; return true;
} }

View File

@ -29,9 +29,9 @@ class BedBlock extends TransparentBlock{
public function onActivate(Item $item, Player $player){ public function onActivate(Item $item, Player $player){
if(ServerAPI::request()->api->time->getPhase($player->level) !== "night"){ if(ServerAPI::request()->api->time->getPhase($player->level) !== "night"){
$player->dataPacket(MC_CLIENT_MESSAGE, array( $pk = new ChatPacket;
"message" => "You can only sleep at night" $pk->message = "You can only sleep at night";
)); $player->dataPacket($pk);
return true; return true;
} }
@ -51,17 +51,17 @@ class BedBlock extends TransparentBlock{
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){ }elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$b = $blockWest; $b = $blockWest;
}else{ }else{
$player->dataPacket(MC_CLIENT_MESSAGE, array( $pk = new ChatPacket;
"message" => "The bed is incomplete" $pk->message = "This bed is incomplete";
)); $player->dataPacket($pk);
return true; return true;
} }
} }
if($player->sleepOn($b) === false){ if($player->sleepOn($b) === false){
$player->dataPacket(MC_CLIENT_MESSAGE, array( $pk = new ChatPacket;
"message" => "This bed is occupied" $pk->message = "This bed is occupied";
)); $player->dataPacket($pk);
} }
return true; return true;
} }

View File

@ -1,876 +0,0 @@
<?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 CustomPacketHandler{
public $offset;
public $raw;
public $c;
public $data;
public $name = "";
public 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;
}
private function feof(){
return !isset($this->raw{$this->offset});
}
public function __construct($pid, $raw = "", $data = array(), $create = false){
$this->raw = $raw;
$this->data = $data;
$this->offset = 0;
$this->c = (bool) $create;
if($pid === false){
return;
}
switch($pid){
case MC_PING:
if($this->c === false){
$this->data["time"] = Utils::readLong($this->get(8));
}else{
$this->raw .= Utils::writeLong($this->data["time"]);
}
break;
case MC_PONG:
if($this->c === false){
$this->data["ptime"] = Utils::readLong($this->get(8));
$this->data["time"] = Utils::readLong($this->get(8));
}else{
$this->raw .= Utils::writeLong($this->data["ptime"]);
$this->raw .= Utils::writeLong($this->data["time"]);
}
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["timestamp"] = $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["timestamp"] = $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_SERVER_FULL:
if($this->c === false){
}else{
$this->raw .= RAKNET_MAGIC;
$this->raw .= Utils::writeLong($this->data["serverID"]);
}
break;
case MC_DISCONNECT:
//null
break;
case MC_BANNED:
if($this->c === false){
}else{
$this->raw .= RAKNET_MAGIC;
$this->raw .= Utils::writeLong($this->data["serverID"]);
}
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));
$this->data["clientId"] = Utils::readInt($this->get(4));
$this->data["realms_data"] = $this->get(Utils::readShort($this->get(2), false));
}else{
$this->raw .= Utils::writeShort(strlen($this->data["username"])).$this->data["username"];
$this->raw .= Utils::writeInt(CURRENT_PROTOCOL).
Utils::writeInt(CURRENT_PROTOCOL).
Utils::writeInt($this->data["clientId"]);
$this->raw .= Utils::writeShort(strlen($this->data["realms_data"])).$this->data["realms_data"];
}
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["player"] = $this->get(Utils::readShort($this->get(2), false));
$this->data["message"] = $this->get(Utils::readShort($this->get(2), false));
}else{
$this->raw .= Utils::writeShort(strlen($this->data["player"])).$this->data["player"];
$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));
$this->data["started"] = ord($this->get(1)) & 0x80 > 0;
}else{
$this->raw .= Utils::writeInt($this->data["time"])."\x80";
$this->raw .= chr((isset($this->data["started"]) and $this->data["started"] == true) ? 0x80:0x00);
}
break;
case MC_START_GAME:
if($this->c === false){
$this->data["seed"] = Utils::readInt($this->get(4));
$this->data["generator"] = 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["generator"]);
$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["pitch"] = Utils::readByte($this->get(1));
$this->data["yaw"] = Utils::readByte($this->get(1));
$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::writeByte($this->data["pitch"]);
$this->raw .= Utils::writeByte($this->data["yaw"]);
$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["pitch"] = Utils::readByte($this->get(1));
$this->data["yaw"] = Utils::readByte($this->get(1));
$this->data["unknown1"] = Utils::readShort($this->get(2));
$this->data["unknown2"] = Utils::readShort($this->get(2));
$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::writeByte($this->data["pitch"]);
$this->raw .= Utils::writeByte($this->data["yaw"]);
$this->raw .= Utils::writeShort($this->data["unknown1"]);
$this->raw .= Utils::writeShort($this->data["unknown2"]);
$this->raw .= Utils::writeMetadata($this->data["metadata"]);
}
break;
case MC_REMOVE_PLAYER:
if($this->c === false){
$this->data["eid"] = Utils::readInt($this->get(4));
$this->data["clientID"] = Utils::readLong($this->get(8));
}else{
$this->raw .= Utils::writeInt($this->data["eid"]);
$this->raw .= Utils::writeLong($this->data["clientID"]);
}
break;
case MC_ADD_ENTITY:
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));
$this->data["did"] = Utils::readInt($this->get(4));
if($this->data["did"] > 0){
$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 .= 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::writeInt($this->data["did"]);
if($this->data["did"] > 0){
$this->raw .= Utils::writeShort($this->data["speedX"]);
$this->raw .= Utils::writeShort($this->data["speedY"]);
$this->raw .= Utils::writeShort($this->data["speedZ"]);
}
}
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_ROTATE_HEAD:
if($this->c === false){
$this->data["eid"] = Utils::readInt($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["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));
$this->data["bodyYaw"] = 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"]);
$this->raw .= Utils::writeFloat($this->data["bodyYaw"]);
}
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: //Sent when a player removes a block, not used
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"] and !$this->feof(); ++$r){
$this->data["records"][] = new Vector3(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->x) . Utils::writeByte($record->y) . Utils::writeByte($record->z);
}
}
}
break;
case MC_LEVEL_EVENT:
if($this->c === false){
$this->data["evid"] = Utils::readShort($this->get(2));
$this->data["x"] = Utils::readShort($this->get(2));
$this->data["y"] = Utils::readShort($this->get(2));
$this->data["z"] = Utils::readShort($this->get(2));
$this->data["data"] = Utils::readInt($this->get(4));
}else{
$this->raw .= Utils::writeShort($this->data["evid"]);
$this->raw .= Utils::writeShort($this->data["x"]);
$this->raw .= Utils::writeShort($this->data["y"]);
$this->raw .= Utils::writeShort($this->data["z"]);
$this->raw .= Utils::writeInt($this->data["data"]);
}
break;
case MC_TILE_EVENT:
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["case1"] = Utils::readInt($this->get(4));
$this->data["case2"] = Utils::readInt($this->get(4));
}else{
$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["case1"]);
$this->raw .= Utils::writeInt($this->data["case2"]);
}
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);
$this->data["slot"] = ord($this->get(1));
}else{
$this->raw .= Utils::writeInt($this->data["eid"]);
$this->raw .= Utils::writeShort($this->data["block"]);
$this->raw .= Utils::writeShort($this->data["meta"]);
$this->raw .= chr($this->data["slot"]);
}
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));
$this->data["posX"] = Utils::readFloat($this->get(4));
$this->data["posY"] = Utils::readFloat($this->get(4));
$this->data["posZ"] = Utils::readFloat($this->get(4));
}else{
$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["face"]);
$this->raw .= Utils::writeShort($this->data["block"]);
$this->raw .= Utils::writeByte($this->data["meta"]);
$this->raw .= Utils::writeInt($this->data["eid"]);
$this->raw .= Utils::writeFloat($this->data["fx"]);
$this->raw .= Utils::writeFloat($this->data["fy"]);
$this->raw .= Utils::writeFloat($this->data["fz"]);
$this->raw .= Utils::writeFloat($this->data["posX"]);
$this->raw .= Utils::writeFloat($this->data["posY"]);
$this->raw .= Utils::writeFloat($this->data["posZ"]);
}
break;
case MC_PLAYER_ACTION:
if($this->c === false){
$this->data["action"] = 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["face"] = Utils::readInt($this->get(4));
$this->data["eid"] = Utils::readInt($this->get(4));
}else{
$this->raw .= Utils::writeInt($this->data["action"]);
$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["face"]);
$this->raw .= Utils::writeInt($this->data["eid"]);
}
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"] and !$this->feof(); ++$s){
$this->data["slots"][$s] = Utils::readSlot($this);
}
if($this->data["windowid"] === 1){ //Armor is also sent
$this->data["armor"] = array(
Utils::readSlot($this),
Utils::readSlot($this),
Utils::readSlot($this),
Utils::readSlot($this)
);
}
}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"] = ord($this->get(1));
//$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 .= chr($this->data["slots"]);
$this->raw .= Utils::writeInt($this->data["x"]);
$this->raw .= Utils::writeInt($this->data["y"]);
$this->raw .= Utils::writeInt($this->data["z"]);
}
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_CONTAINER_SET_CONTENT:
if($this->c === false){
$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"] and !$this->feof(); ++$s){
$this->data["slots"][$s] = Utils::readSlot($this);
}
if($this->data["windowid"] == 0){
$slots = min(9, Utils::readShort($this->get(2), false));
$this->data["hotbar"] = array();
if($slots > 0){
for($s = 0; $s < $slots; ++$s){
$this->data["hotbar"][$s] = Utils::readInt($this->get(4));
}
}
}
}else{
$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"] == 0 and isset($this->data["hotbar"])){
if(count($this->data["hotbar"]) > 0){
$this->raw .= Utils::writeShort(count($this->data["hotbar"]));
foreach($this->data["hotbar"] as $slot){
$this->raw .= Utils::writeInt($slot);
}
}
}
}
break;
case MC_CONTAINER_SET_DATA:
if($this->c === false){
$this->data["windowid"] = ord($this->get(1));
$this->data["property"] = Utils::readShort($this->get(2));
$this->data["value"] = Utils::readShort($this->get(2));
}else{
$this->raw .= chr($this->data["windowid"]);
$this->raw .= Utils::writeShort($this->data["property"]);
$this->raw .= Utils::writeShort($this->data["value"]);
}
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_ADVENTURE_SETTINGS:
if($this->c === false){
$this->data["flags"] = Utils::readInt($this->get(4));
}else{
$this->raw .= Utils::writeInt($this->data["flags"]);
}
break;
case MC_ENTITY_DATA:
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));
$this->data["namedtag"] = $this->get(true);
}else{
$this->raw .= Utils::writeShort($this->data["x"]);
$this->raw .= chr($this->data["y"]);
$this->raw .= Utils::writeShort($this->data["z"]);
$this->raw .= $this->data["namedtag"];
}
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;
}
}
}

View File

@ -20,241 +20,80 @@
*/ */
class MinecraftInterface{ class MinecraftInterface{
public $client;
public $bandwidth; public $bandwidth;
private $socket; private $socket;
private $data; private $packets;
private $chunked; function __construct($server, $port = 25565, $serverip = "0.0.0.0"){
private $toChunk; $this->socket = new UDPSocket($server, $port, true, $serverip);
private $needCheck;
function __construct($object, $server, $port = 25565, $listen = false, $client = false, $serverip = "0.0.0.0"){
$this->socket = new UDPSocket($server, $port, (bool) $listen, $serverip);
if($this->socket->connected === false){ if($this->socket->connected === false){
console("[ERROR] Couldn't bind to $serverip:".$port, true, true, 0); console("[SEVERE] Couldn't bind to $serverip:".$port, true, true, 0);
exit(1); exit(1);
} }
$this->bandwidth = array(0, 0, microtime(true)); $this->bandwidth = array(0, 0, microtime(true));
$this->client = (bool) $client;
$this->start = microtime(true); $this->start = microtime(true);
$this->chunked = array(); $this->packets = array();
$this->toChunk = array();
$this->needCheck = array();
$object->schedule(1, array($this, "checkChunked"), array(), true);
} }
public function close(){ public function close(){
return $this->socket->close(false); return $this->socket->close(false);
} }
protected function getStruct($pid){
if(isset(Protocol::$raknet[$pid])){
return Protocol::$raknet[$pid];
}
return false;
}
public function readPacket(){ public function readPacket(){
$pk = $this->popPacket();
if($this->socket->connected === false){ if($this->socket->connected === false){
return $pk; return false;
} }
$buf = ""; $buf = "";
$source = false; $source = false;
$port = 1; $port = 1;
$len = $this->socket->read($buf, $source, $port); $len = $this->socket->read($buf, $source, $port);
if($len === false or $len === 0){ if($len === false or $len === 0){
return $pk; return false;
} }
$this->bandwidth[0] += $len; $this->bandwidth[0] += $len;
$this->parsePacket($buf, $source, $port); return $this->parsePacket($buf, $source, $port);
return ($pk !== false ? $pk : $this->popPacket());
} }
private function parsePacket($buf, $source, $port){ private function parsePacket($buffer, $source, $port){
$pid = ord($buf{0}); $pid = ord($buffer{0});
$struct = $this->getStruct($pid);
if($struct === false){ if(RakNetInfo::isValid($pid)){
if(ServerAPI::request()->api->dhandle("server.unknownpacket", array( $parser = new RakNetParser($buffer);
"pid" => $pid, if($parser->packet !== false){
"data" => array(), $parser->packet->ip = $source;
"raw" => $buf, $parser->packet->port = $port;
"ip" => $source, if(EventHandler::callEvent(new PacketReceiveEvent($parser->packet)) === BaseEvent::DENY){
"port" => $port return false;
)) !== true){ }
console("[ERROR] Unknown Packet ID 0x".Utils::strToHex(chr($pid)), true, true, 2); return $parser->packet;
} }
return false; return false;
} }elseif($pid === 0xfe and $buffer{1} === "\xfd" and ServerAPI::request()->api->query instanceof QueryHandler){
$packet = new QueryPacket;
$packet = new Packet($pid, $struct, $buf); $packet->ip = $source;
@$packet->parse(); $packet->port = $port;
if($pid === 0x99){ $packet->buffer = $buffer;
$CID = PocketMinecraftServer::clientID($source, $port); if(EventHandler::callEvent(new PacketReceiveEvent($packet)) === BaseEvent::DENY){
if(!isset($this->chunked[$CID]) and $packet->data[0] !== 0){ //Drop packet
return false; return false;
} }
switch($packet->data[0]){ ServerAPI::request()->api->query->handle($packet);
case 0: }else{
$this->initChunked($CID, $source, $port); $packet = new Packet();
return false; $packet->ip = $source;
case 1: $packet->port = $port;
$this->stopChunked($CID); $packet->buffer = $buffer;
return false; EventHandler::callEvent(new PacketReceiveEvent($packet));
case 3:
$this->ackChunked($CID, $data[1]["id"], $data[1]["index"]);
return false;
case 4:
$this->receiveChunked($CID, $data[1]["id"], $data[1]["index"], $data[1]["count"], $data[1]["data"]);
return true;
}
}
$this->data[] = array($pid, $packet->data, $buf, $source, $port);
return true;
}
public function checkChunked($CID){
$time = microtime(true);
foreach($this->needCheck as $CID => $packets){
if($packets[-1] < $time){
$d = $this->chunked[$CID];
unset($packets[-1]);
foreach($packets as $packet){
$this->writePacket(0x99, $packet, true, $d[1], $d[2], true);
}
$this->needCheck[$CID][-1] = $time + 5;
}
}
foreach($this->toChunk as $CID => $packets){
$d = $this->chunked[$CID];
$raw = "";
$MTU = 512;
foreach($packets as $packet){
$raw .= $packet;
if(($len = strlen($packet)) > $MTU){
$MTU = $len;
}
}
if($MTU > $d[0][2]){
$this->chunked[$CID][0][2] = $MTU;
}else{
$MTU = $d[0][2];
}
$raw = str_split(gzdeflate($raw, DEFLATEPACKET_LEVEL), $MTU - 9); // - 1 - 2 - 2 - 2 - 2
$count = count($raw);
$messageID = $this->chunked[$CID][0][0]++;
$this->chunked[$CID][0][0] &= 0xFFFF;
if(!isset($this->needCheck[$CID])){
$this->needCheck[$CID] = array();
}
$this->needCheck[$CID][$messageID] = array(-1 => $time + 1);
foreach($raw as $index => $r){
$p = "\x99\x02".Utils::writeShort($messageID).Utils::writeShort($index).Utils::writeShort($count).Utils::writeShort(strlen($r)).$r;
$this->needCheck[$CID][$messageID][$index] = $p;
$this->writePacket(0x99, $p, true, $d[1], $d[2], true);
}
unset($this->toChunk[$CID]);
}
}
public function isChunked($CID){
return isset($this->chunked[$CID]);
}
private function initChunked($CID, $source, $port){
console("[DEBUG] Starting DEFLATEPacket for $source:$port", true, true, 2);
$this->chunked[$CID] = array(
0 => array(0, 0, 0), //index, sent/received; MTU
1 => $source,
2 => $port,
3 => array(), //Received packets
);
$this->writePacket(0x99, array(
0 => 0, //start
), false, $source, $port, true);
}
public function stopChunked($CID){
if(!isset($this->chunked[$CID])){
return false; return false;
} }
$this->writePacket(0x99, array(
0 => 1, //stop
), false, $this->chunked[$CID][1], $this->chunked[$CID][2], true);
console("[DEBUG] Stopping DEFLATEPacket for ".$this->chunked[$CID][1].":".$this->chunked[$CID][2], true, true, 2);
$this->chunked[$CID][3] = null;
$this->chunked[$CID][4] = null;
unset($this->chunked[$CID]);
unset($this->toChunk[$CID]);
unset($this->needCheck[$CID]);
} }
private function ackChunked($CID, $ID, $index){ public function writePacket(Packet $packet){
unset($this->needCheck[$CID][$ID][$index]); if(EventHandler::callEvent(new PacketSendEvent($packet)) === BaseEvent::DENY){
if(count($this->needCheck[$CID][$ID]) <= 1){ return 0;
unset($this->needCheck[$CID][$ID]); }elseif($packet instanceof RakNetPacket){
} $codec = new RakNetCodec($packet);
}
private function receiveChunked($CID, $ID, $index, $count, $data){
if(!isset($this->chunked[$CID][3][$ID])){
$this->chunked[$CID][3][$ID] = array();
}
$this->chunked[$CID][3][$ID][$index] = $data;
if(count($this->chunked[$CID][3][$ID]) === $count){
ksort($this->chunked[$CID][3][$ID]);
$data = gzinflate(implode($this->chunked[$CID][3][$ID]), 524280);
unset($this->chunked[$CID][3][$ID]);
if($data === false or strlen($data) === 0){
console("[ERROR] Invalid DEFLATEPacket for ".$this->chunked[$CID][1].":".$this->chunked[$CID][2], true, true, 2);
}
$offset = 0;
while(($plen = Utils::readShort(substr($data, $offset, 2), false)) !== 0xFFFF or $offset >= $len){
$offset += 2;
$packet = substr($data, $offset, $plen);
$this->parsePacket($packet, $this->chunked[$CID][1], $this->chunked[$CID][2]);
}
}
}
public function popPacket(){
if(count($this->data) > 0){
$p = each($this->data);
unset($this->data[$p[0]]);
$p = $p[1];
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, $force = false){
$CID = PocketMinecraftServer::clientID($dest, $port);
if($raw === false){
$packet = new Packet($pid, $this->getStruct($pid));
$packet->data = $data;
@$packet->create();
if($force === false and $this->isChunked($CID)){
if(!isset($this->toChunk[$CID])){
$this->toChunk[$CID] = array();
}
$this->toChunk[$CID][] = $packet->raw;
$write = strlen($packet->raw);
}else{
$write = $this->socket->write($packet->raw, $dest, $port);
$this->bandwidth[1] += $write;
}
}else{
if($force === false and $this->isChunked($CID)){
if(!isset($this->toChunk[$CID])){
$this->toChunk[$CID] = array();
}
$this->toChunk[$CID][] = $data;
$write = strlen($data);
}else{
$write = $this->socket->write($data, $dest, $port);
$this->bandwidth[1] += $write;
}
} }
$write = $this->socket->write($packet->buffer, $packet->ip, $packet->port);
$this->bandwidth[1] += $write;
return $write; return $write;
} }

View File

@ -19,325 +19,9 @@
* *
*/ */
class Packet extends stdClass{
class Packet{ public $ip;
private $struct; public $port;
protected $pid, $packet; public $buffer;
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;
}
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;
}
switch($type){
case "special1":
switch($this->pid){
case 0x99:
if($this->data[0] >= 2){
$this->addRaw(Utils::writeShort($this->data[1]["id"]));
$this->addRaw(Utils::writeShort($this->data[1]["index"]));
if($this->data[0] === 2){
$this->addRaw(Utils::writeShort($this->data[1]["count"]));
$this->addRaw(Utils::writeShort(strlen($this->data[1]["data"])).$this->data[1]["data"]);
}
}
break;
case 0xc0:
case 0xa0:
$payload = "";
$records = 0;
$pointer = 0;
sort($this->data[$field], SORT_NUMERIC);
$max = count($this->data[$field]);
while($pointer < $max){
$type = true;
$curr = $start = $this->data[$field][$pointer];
for($i = $start + 1; $i < $max; ++$i){
$n = $this->data[$field][$i];
if(($n - $curr) === 1){
$curr = $end = $n;
$type = false;
$pointer = $i + 1;
}else{
break;
}
}
++$pointer;
if($type === false){
$payload .= Utils::writeBool(false);
$payload .= strrev(Utils::writeTriad($start));
$payload .= strrev(Utils::writeTriad($end));
}else{
$payload .= Utils::writeBool(true);
$payload .= strrev(Utils::writeTriad($start));
}
++$records;
}
$this->addRaw(Utils::writeShort($records) . $payload);
break;
case 0x05:
$this->addRaw($this->data[$field]);
break;
}
break;
case "customData":
$this->addRaw(chr($this->data[1]));
if($this->data[2]["id"] === false){
$this->addRaw($this->data[2]["raw"]);
}else{
switch($this->data[1]){
case 0x40:
$reply = new CustomPacketHandler($this->data[2]["id"], "", $this->data[2], true);
$this->addRaw(Utils::writeShort((strlen($reply->raw) + 1) << 3));
$this->addRaw(strrev(Utils::writeTriad($this->data[2]["count"])));
$this->addRaw(chr($this->data[2]["id"]));
$this->addRaw($reply->raw);
break;
case 0x00:
$raw = new CustomPacketHandler($this->data[2]["id"], "", $this->data[2], true);
$raw = $raw->raw;
$this->addRaw(Utils::writeShort((strlen($raw) + 1) << 3));
$this->addRaw(chr($this->data[2]["id"]));
$this->addRaw($raw);
break;
}
}
break;
case "magic":
$this->addRaw(RAKNET_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 "string":
$this->addRaw(Utils::writeShort(strlen($this->data[$field])));
$this->addRaw($this->data[$field]);
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;
}
private function feof(){
return !isset($this->raw{$this->offset});
}
protected function addRaw($str){
$this->raw .= $str;
return $str;
}
public function parse(){
foreach($this->struct as $field => $type){
switch($type){
case "special1":
switch($this->pid){
case 0x07:
$this->data[] = $this->get(5);
break;
case 0x99:
if($this->data[0] >= 2){ //
$messageID = Utils::readShort($this->get(2), false);
$messageIndex = Utils::readShort($this->get(2), false);
$this->data[1] = array("id" => $messageID, "index" => $messageIndex);
if($this->data[0] === 2){
$this->data[1]["count"] = Utils::readShort($this->get(2), false);
$dataLength = Utils::readShort($this->get(2), false);
$this->data[1]["data"] = $this->get($dataLength);
}
}
break;
case 0xc0:
case 0xa0:
$cnt = Utils::readShort($this->get(2), false);
$this->data[$field] = array();
for($i = 0; $i < $cnt and !$this->feof(); ++$i){
if(Utils::readBool($this->get(1)) === false){
$start = Utils::readTriad(strrev($this->get(3)));
$end = min(Utils::readTriad(strrev($this->get(3))), $start + 4096);
for($c = $start; $c <= $end; ++$c){
$this->data[$field][] = $c;
}
}else{
$this->data[$field][] = Utils::readTriad(strrev($this->get(3)));
}
}
break;
case 0x05:
$this->data[] = $this->get(true);
break;
}
break;
case "customData":
$raw = $this->get(true);
$len = strlen($raw);
$offset = 0;
$this->data["packets"] = array();
while($len > $offset){
$pid = ord($raw{$offset});
++$offset;
$reliability = ($pid & 0b11100000) >> 5;
$hasSplit = ($pid & 0b00010000) >> 4;
$length = Utils::readShort(substr($raw, $offset, 2), false);
$offset += 2;
if($reliability === 2
or $reliability === 3
or $reliability === 4
or $reliability === 6
or $reliability === 7){
$messageIndex = Utils::readTriad(strrev(substr($raw, $offset, 3)));
$offset += 3;
}else{
$messageIndex = 0;
}
if($reliability === 1
or $reliability === 3
or $reliability === 4
or $reliability === 7){
$orderIndex = Utils::readTriad(strrev(substr($raw, $offset, 3)));
$offset += 3;
$orderChannel = ord($raw{$offset}); //5 bits, 32 values
++$offset;
}else{
$orderIndex = 0;
$orderChannel = 0;
}
if($hasSplit === 1){
$splitCount = Utils::readInt(substr($raw, $offset, 4));
$offset += 4;
$splitID = Utils::readShort(substr($raw, $offset, 2));
$offset += 2;
$splitIndex = Utils::readInt(substr($raw, $offset, 4));
$offset += 4;
//error! no split packets allowed!
break;
}else{
$splitCount = 0;
$splitID = 0;
$splitIndex = 0;
}
if($length == 0
or $orderChannel >= 32
or ($hasSplit === 1 and $splitIndex >= $splitCount)){
continue;
}
$ln = ceil($length / 8);
$id = ord($raw{$offset});
++$offset;
$pak = substr($raw, $offset, $ln - 1);
$offset += $ln - 1;
$pk = new CustomPacketHandler($id, $pak);
$pk->data["length"] = $ln;
$pk->data["id"] = $id;
$pk->data["counter"] = $messageIndex;
$pk->data["packetName"] = $pk->name;
$this->data["packets"][] = array($pid, $pk->data, $pak);
}
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;
}
}
}
} }

View File

@ -1,259 +0,0 @@
<?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/
*
*
*/
define("DEFLATEPACKET_LEVEL", 1);
define("CURRENT_STRUCTURE", 5);
define("CURRENT_PROTOCOL", 14);
define("RAKNET_MAGIC", "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78");
define("MC_PING", 0x00);
define("MC_PONG", 0x03);
define("MC_CLIENT_CONNECT", 0x09);
define("MC_SERVER_HANDSHAKE", 0x10);
define("MC_CLIENT_HANDSHAKE", 0x13);
define("MC_SERVER_FULL", 0x14);
define("MC_DISCONNECT", 0x15);
define("MC_BANNED", 0x17);
define("MC_LOGIN", 0x82);
define("MC_LOGIN_STATUS", 0x83);
define("MC_READY", 0x84);
define("MC_CHAT", 0x85);
define("MC_SET_TIME", 0x86);
define("MC_START_GAME", 0x87);
define("MC_ADD_MOB", 0x88);
define("MC_ADD_PLAYER", 0x89);
define("MC_REMOVE_PLAYER", 0x8a);
define("MC_ADD_ENTITY", 0x8c);
define("MC_REMOVE_ENTITY", 0x8d);
define("MC_ADD_ITEM_ENTITY", 0x8e);
define("MC_TAKE_ITEM_ENTITY", 0x8f);
define("MC_MOVE_ENTITY", 0x90);
define("MC_MOVE_ENTITY_POSROT", 0x93);
define("MC_ROTATE_HEAD", 0x94);
define("MC_MOVE_PLAYER", 0x95);
define("MC_PLACE_BLOCK", 0x96);
define("MC_REMOVE_BLOCK", 0x97);
define("MC_UPDATE_BLOCK", 0x98);
define("MC_ADD_PAINTING", 0x99);
define("MC_EXPLOSION", 0x9a);
define("MC_LEVEL_EVENT", 0x9b);
define("MC_TILE_EVENT", 0x9c);
define("MC_ENTITY_EVENT", 0x9d);
define("MC_REQUEST_CHUNK", 0x9e);
define("MC_CHUNK_DATA", 0x9f);
define("MC_PLAYER_EQUIPMENT", 0xa0);
define("MC_PLAYER_ARMOR_EQUIPMENT", 0xa1);
define("MC_INTERACT", 0xa2);
define("MC_USE_ITEM", 0xa3);
define("MC_PLAYER_ACTION", 0xa4);
define("MC_HURT_ARMOR", 0xa6);
define("MC_SET_ENTITY_DATA", 0xa7);
define("MC_SET_ENTITY_MOTION", 0xa8);
//define("MC_SET_ENTITY_LINK", 0xa9);
define("MC_SET_HEALTH", 0xaa);
define("MC_SET_SPAWN_POSITION", 0xab);
define("MC_ANIMATE", 0xac);
define("MC_RESPAWN", 0xad);
define("MC_SEND_INVENTORY", 0xae);
define("MC_DROP_ITEM", 0xaf);
define("MC_CONTAINER_OPEN", 0xb0);
define("MC_CONTAINER_CLOSE", 0xb1);
define("MC_CONTAINER_SET_SLOT", 0xb2);
define("MC_CONTAINER_SET_DATA", 0xb3);
define("MC_CONTAINER_SET_CONTENT", 0xb4);
//define("MC_CONTAINER_ACK", 0xb5);
define("MC_CLIENT_MESSAGE", 0xb6);
define("MC_ADVENTURE_SETTINGS", 0xb7);
define("MC_ENTITY_DATA", 0xb8);
//define("MC_PLAYER_INPUT", 0xb9);
class Protocol{
public static $raknet = array(
0x01 => array(
"long", //Ping ID
"magic",
),
0x02 => array(
"long", //Ping ID
"magic",
),
0x05 => array(
"magic",
"byte", //Protocol Version
"special1", //MTU Size Null Lenght
),
0x06 => array(
"magic",
"long", //Server GUID
"byte", //Server Security
"short", //MTU Size
),
0x07 => array(
"magic",
"special1", //Security Cookie
"short", //Server UDP Port
"short", //MTU Size
"long", //Client GUID
),
0x08 => array(
"magic",
"long", //Server GUID
"short", //Client UDP Port
"short", //MTU Size
"byte", //Security
),
0x1a => array(
"byte", //Server Version
"magic",
"long", //Server GUID
),
0x1c => array(
"long", //Ping ID
"long", //Server GUID
"magic",
"string", //Data
),
0x1d => array(
"long", //Ping ID
"long", //Server GUID
"magic",
"string", //Data
),
0x80 => array(
"itriad",
"customData",
),
0x81 => array(
"itriad",
"customData",
),
0x82 => array(
"itriad",
"customData",
),
0x83 => array(
"itriad",
"customData",
),
0x84 => array(
"itriad",
"customData",
),
0x85 => array(
"itriad",
"customData",
),
0x86 => array(
"itriad",
"customData",
),
0x87 => array(
"itriad",
"customData",
),
0x88 => array(
"itriad",
"customData",
),
0x89 => array(
"itriad",
"customData",
),
0x8a => array(
"itriad",
"customData",
),
0x8b => array(
"itriad",
"customData",
),
0x8c => array(
"itriad",
"customData",
),
0x8d => array(
"itriad",
"customData",
),
0x8e => array(
"itriad",
"customData",
),
0x8f => array(
"itriad",
"ubyte",
"customData",
),
0x99 => array(
"byte",
"special1",
),
0xa0 => array(
"special1",
),
0xc0 => array(
"special1",
),
);
}

View File

@ -34,8 +34,8 @@ class UDPSocket{
}else{ }else{
if(socket_bind($this->sock, $serverip, $port) === true){ if(socket_bind($this->sock, $serverip, $port) === true){
socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 0); socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 0);
socket_set_option($this->sock, SOL_SOCKET, SO_SNDBUF, 65535); socket_set_option($this->sock, SOL_SOCKET, SO_SNDBUF, 1024 * 1024 * 2); //2MB
socket_set_option($this->sock, SOL_SOCKET, SO_RCVBUF, 65535); socket_set_option($this->sock, SOL_SOCKET, SO_RCVBUF, 1024 * 1024); //1MB
$this->unblock(); $this->unblock();
$this->connected = true; $this->connected = true;
}else{ }else{
@ -64,11 +64,11 @@ class UDPSocket{
return @socket_recvfrom($this->sock, $buf, 65535, 0, $source, $port); return @socket_recvfrom($this->sock, $buf, 65535, 0, $source, $port);
} }
public function write($data, $dest = false, $port = false){ public function write($data, $dest, $port){
if($this->connected === false){ if($this->connected === false){
return false; return false;
} }
return @socket_sendto($this->sock, $data, strlen($data), 0, ($dest === false ? $this->server:$dest), ($port === false ? $this->port:$port)); return @socket_sendto($this->sock, $data, strlen($data), 0, $dest, $port);
} }
} }

View File

@ -0,0 +1,160 @@
<?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 ProtocolInfo{
const CURRENT_PROTOCOL = 14;
const PING_PACKET = 0x00;
const PONG_PACKET = 0x03;
const CLIENT_CONNECT_PACKET = 0x09;
const SERVER_HANDSHAKE_PACKET = 0x10;
const CLIENT_HANDSHAKE_PACKET = 0x13;
//const SERVER_FULL_PACKET = 0x14;
const DISCONNECT_PACKET = 0x15;
//const BANNED_PACKET = 0x17;
const LOGIN_PACKET = 0x82;
const LOGIN_STATUS_PACKET = 0x83;
const READY_PACKET = 0x84;
const MESSAGE_PACKET = 0x85;
const SET_TIME_PACKET = 0x86;
const START_GAME_PACKET = 0x87;
const ADD_MOB_PACKET = 0x88;
const ADD_PLAYER_PACKET = 0x89;
const REMOVE_PLAYER_PACKET = 0x8a;
const ADD_ENTITY_PACKET = 0x8c;
const REMOVE_ENTITY_PACKET = 0x8d;
const ADD_ITEM_ENTITY_PACKET = 0x8e;
const TAKE_ITEM_ENTITY_PACKET = 0x8f;
const MOVE_ENTITY_PACKET = 0x90;
const MOVE_ENTITY_PACKET_POSROT = 0x93;
const ROTATE_HEAD_PACKET = 0x94;
const MOVE_PLAYER_PACKET = 0x95;
//const PLACE_BLOCK_PACKET = 0x96;
const REMOVE_BLOCK_PACKET = 0x97;
const UPDATE_BLOCK_PACKET = 0x98;
const ADD_PAINTING_PACKET = 0x99;
const EXPLODE_PACKET = 0x9a;
const LEVEL_EVENT_PACKET = 0x9b;
const TILE_EVENT_PACKET = 0x9c;
const ENTITY_EVENT_PACKET = 0x9d;
const REQUEST_CHUNK_PACKET = 0x9e;
const CHUNK_DATA_PACKET = 0x9f;
const PLAYER_EQUIPMENT_PACKET = 0xa0;
const PLAYER_ARMOR_EQUIPMENT_PACKET = 0xa1;
const INTERACT_PACKET = 0xa2;
const USE_ITEM_PACKET = 0xa3;
const PLAYER_ACTION_PACKET = 0xa4;
const HURT_ARMOR_PACKET = 0xa6;
const SET_ENTITY_DATA_PACKET = 0xa7;
const SET_ENTITY_MOTION_PACKET = 0xa8;
//const SET_ENTITY_LINK_PACKET = 0xa9;
const SET_HEALTH_PACKET = 0xaa;
const SET_SPAWN_POSITION_PACKET = 0xab;
const ANIMATE_PACKET = 0xac;
const RESPAWN_PACKET = 0xad;
const SEND_INVENTORY_PACKET = 0xae;
const DROP_ITEM_PACKET = 0xaf;
const CONTAINER_OPEN_PACKET = 0xb0;
const CONTAINER_CLOSE_PACKET = 0xb1;
const CONTAINER_SET_SLOT_PACKET = 0xb2;
const CONTAINER_SET_DATA_PACKET = 0xb3;
const CONTAINER_SET_CONTENT_PACKET = 0xb4;
//const CONTAINER_ACK_PACKET = 0xb5;
const CHAT_PACKET = 0xb6;
const ADVENTURE_SETTINGS_PACKET = 0xb7;
const ENTITY_DATA_PACKET = 0xb8;
//const PLAYER_INPUT_PACKET = 0xb9;
public static $packets = array(
-1 => "UnknownPacket",
ProtocolInfo::PING_PACKET => "PingPacket",
ProtocolInfo::PONG_PACKET => "PongPacket",
ProtocolInfo::CLIENT_CONNECT_PACKET => "ClientConnectPacket",
ProtocolInfo::SERVER_HANDSHAKE_PACKET => "ServerHandshakePacket",
ProtocolInfo::DISCONNECT_PACKET => "DisconnectPacket",
ProtocolInfo::LOGIN_PACKET => "LoginPacket",
ProtocolInfo::LOGIN_STATUS_PACKET => "LoginStatusPacket",
ProtocolInfo::READY_PACKET => "ReadyPacket",
ProtocolInfo::MESSAGE_PACKET => "MessagePacket",
ProtocolInfo::SET_TIME_PACKET => "SetTimePacket",
ProtocolInfo::START_GAME_PACKET => "StartGamePacket",
ProtocolInfo::ADD_MOB_PACKET => "AddMobPacket",
ProtocolInfo::ADD_PLAYER_PACKET => "AddPlayerPacket",
ProtocolInfo::REMOVE_PLAYER_PACKET => "RemovePlayerPacket",
ProtocolInfo::ADD_ENTITY_PACKET => "AddEntityPacket",
ProtocolInfo::REMOVE_ENTITY_PACKET => "RemoveEntityPacket",
ProtocolInfo::ADD_ITEM_ENTITY_PACKET => "AddItemEntityPacket",
ProtocolInfo::TAKE_ITEM_ENTITY_PACKET => "TakeItemEntityPacket",
ProtocolInfo::MOVE_ENTITY_PACKET => "MoveEntityPacket",
ProtocolInfo::MOVE_ENTITY_PACKET_POSROT => "MoveEntityPacket_PosRot",
ProtocolInfo::ROTATE_HEAD_PACKET => "RotateHeadPacket",
ProtocolInfo::MOVE_PLAYER_PACKET => "MovePlayerPacket",
ProtocolInfo::REMOVE_BLOCK_PACKET => "RemoveBlockPacket",
ProtocolInfo::UPDATE_BLOCK_PACKET => "UpdateBlockPacket",
ProtocolInfo::ADD_PAINTING_PACKET => "AddPaintingPacket",
ProtocolInfo::EXPLODE_PACKET => "ExplodePacket",
ProtocolInfo::LEVEL_EVENT_PACKET => "LevelEventPacket",
ProtocolInfo::TILE_EVENT_PACKET => "TileEventPacket",
ProtocolInfo::ENTITY_EVENT_PACKET => "EntityEventPacket",
ProtocolInfo::REQUEST_CHUNK_PACKET => "RequestChunkPacket",
ProtocolInfo::CHUNK_DATA_PACKET => "ChunkDataPacket",
ProtocolInfo::PLAYER_EQUIPMENT_PACKET => "PlayerEquipmentPacket",
ProtocolInfo::PLAYER_ARMOR_EQUIPMENT_PACKET => "PlayerArmorEquipmentPacket",
ProtocolInfo::INTERACT_PACKET => "InteractPacket",
ProtocolInfo::USE_ITEM_PACKET => "UseItemPacket",
ProtocolInfo::PLAYER_ACTION_PACKET => "PlayerActionPacket",
ProtocolInfo::HURT_ARMOR_PACKET => "HurtArmorPacket",
ProtocolInfo::SET_ENTITY_DATA_PACKET => "SetEntityDataPacket",
ProtocolInfo::SET_ENTITY_MOTION_PACKET => "SetEntityMotionPacket",
ProtocolInfo::SET_HEALTH_PACKET => "SetHealthPacket",
ProtocolInfo::SET_SPAWN_POSITION_PACKET => "SetSpawnPositionPacket",
ProtocolInfo::ANIMATE_PACKET => "AnimatePacket",
ProtocolInfo::RESPAWN_PACKET => "RespawnPacket",
ProtocolInfo::SEND_INVENTORY_PACKET => "SendInventoryPacket",
ProtocolInfo::DROP_ITEM_PACKET => "DropItemPacket",
ProtocolInfo::CONTAINER_OPEN_PACKET => "ContainerOpenPacket",
ProtocolInfo::CONTAINER_CLOSE_PACKET => "ContainerClosePacket",
ProtocolInfo::CONTAINER_SET_SLOT_PACKET => "ContainerSetSlotPacket",
ProtocolInfo::CONTAINER_SET_DATA_PACKET => "ContainerSetDataPacket",
ProtocolInfo::CONTAINER_SET_CONTENT_PACKET => "ContainerSetContentPacket",
ProtocolInfo::CHAT_PACKET => "ChatPacket",
ProtocolInfo::ADVENTURE_SETTINGS_PACKET => "AdventureSettingsPacket",
ProtocolInfo::ENTITY_DATA_PACKET => "EntityDataPacket",
);
}
/***REM_START***/
require_once(FILE_PATH . "src/network/raknet/RakNetDataPacket.php");
/***REM_END***/

View File

@ -0,0 +1,56 @@
<?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 AddEntityPacket extends RakNetDataPacket{
public $eid;
public $type;
public $x;
public $y;
public $z;
public $did;
public $speedX;
public $speedY;
public $speedZ;
public function pid(){
return ProtocolInfo::ADD_ENTITY_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putByte($this->type);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putInt($this->did);
if($this->did > 0){
$this->putShort($this->speedX);
$this->putShort($this->speedY);
$this->putShort($this->speedZ);
}
}
}

View File

@ -0,0 +1,52 @@
<?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 AddItemEntityPacket extends RakNetDataPacket{
public $eid;
public $item;
public $x;
public $y;
public $z;
public $yaw;
public $pitch;
public $roll;
public function pid(){
return ProtocolInfo::ADD_ITEM_ENTITY_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putSlot($this->item);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putByte($this->yaw);
$this->putByte($this->pitch);
$this->putByte($this->roll);
}
}

View File

@ -0,0 +1,52 @@
<?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 AddMobPacket extends RakNetDataPacket{
public $eid;
public $type;
public $x;
public $y;
public $z;
public $pitch;
public $yaw;
public $metadata;
public function pid(){
return ProtocolInfo::ADD_MOB_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putInt($this->type);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putByte($this->yaw);
$this->putByte($this->pitch);
$this->put(Utils::writeMetadata($this->metadata));
}
}

View File

@ -0,0 +1,48 @@
<?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 AddPaintingPacket extends RakNetDataPacket{
public $eid;
public $x;
public $y;
public $z;
public $direction;
public $title;
public function pid(){
return ProtocolInfo::ADD_PAINTING_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putInt($this->direction);
$this->putString($this->title);
}
}

View File

@ -0,0 +1,58 @@
<?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 AddPlayerPacket extends RakNetDataPacket{
public $clientID;
public $username;
public $eid;
public $x;
public $y;
public $z;
public $pitch;
public $yaw;
public $unknown1;
public $unknown2;
public $metadata;
public function pid(){
return ProtocolInfo::ADD_PLAYER_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putLong($this->clientID);
$this->putString($this->username);
$this->putInt($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putByte($this->yaw);
$this->putByte($this->pitch);
$this->putShort($this->unknown1);
$this->putShort($this->unknown2);
$this->put(Utils::writeMetadata($this->metadata));
}
}

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 AdventureSettingsPacket extends RakNetDataPacket{
public $flags;
public function pid(){
return ProtocolInfo::ADVENTURE_SETTINGS_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->flags);
}
}

View File

@ -0,0 +1,41 @@
<?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 AnimatePacket extends RakNetDataPacket{
public $action;
public $eid;
public function pid(){
return ProtocolInfo::ANIMATE_PACKET;
}
public function decode(){
$this->action = $this->getByte();
$this->eid = $this->getInt();
}
public function encode(){
$this->reset();
$this->putByte($this->action);
$this->putInt($this->eid);
}
}

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 ChatPacket extends RakNetDataPacket{
public $message;
public function pid(){
return ProtocolInfo::CHAT_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putString($this->message);
}
}

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 ChunkDataPacket extends RakNetDataPacket{
public $chunkX;
public $chunkZ;
public $data;
public function pid(){
return ProtocolInfo::CHUNK_DATA_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->chunkX);
$this->putInt($this->chunkZ);
$this->put($this->data);
}
}

View File

@ -0,0 +1,41 @@
<?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 ClientConnectPacket extends RakNetDataPacket{
public $clientID;
public $session;
public $unknown1;
public function pid(){
return ProtocolInfo::CLIENT_CONNECT_PACKET;
}
public function decode(){
$this->clientID = $this->getLong();
$this->session = $this->getLong();
$this->unknown1 = $this->get(1);
}
public function encode(){
}
}

View File

@ -0,0 +1,51 @@
<?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 ClientHandshakePacket extends RakNetDataPacket{
public $cookie;
public $security;
public $port;
public $dataArray0;
public $dataArray;
public $timestamp;
public $session2;
public $session;
public function pid(){
return ProtocolInfo::CLIENT_HANDSHAKE_PACKET;
}
public function decode(){
$this->cookie = $this->get(4);
$this->security = $this->get(1);
$this->port = $this->getShort(true);
$this->dataArray0 = $this->get($this->getByte());
$this->dataArray = $this->getDataArray(9);
$this->timestamp = $this->get(2);
$this->session2 = $this->getLong();
$this->session = $this->getLong();
}
public function encode(){
}
}

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 ContainerClosePacket extends RakNetDataPacket{
public $windowid;
public function pid(){
return ProtocolInfo::CONTAINER_CLOSE_PACKET;
}
public function decode(){
$this->windowid = $this->getByte();
}
public function encode(){
$this->reset();
$this->putByte($this->windowid);
}
}

View File

@ -0,0 +1,48 @@
<?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 ContainerOpenPacket extends RakNetDataPacket{
public $windowid;
public $type;
public $slots;
public $x;
public $y;
public $z;
public function pid(){
return ProtocolInfo::CONTAINER_OPEN_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putByte($this->windowid);
$this->putByte($this->type);
$this->putByte($this->slots);
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
}
}

View File

@ -0,0 +1,60 @@
<?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 ContainerSetContentPacket extends RakNetDataPacket{
public $windowid;
public $slots = array();
public $hotbar = array();
public function pid(){
return ProtocolInfo::CONTAINER_SET_CONTENT_PACKET;
}
public function decode(){
$this->windowid = $this->getByte();
$count = $this->getShort();
for($s = 0; $s < $count and !$this->feof(); ++$s){
$this->slots[$s] = $this->getSlot();
}
if($this->windowid === 0){
$count = $this->getShort();
for($s = 0; $s < $count and !$this->feof(); ++$s){
$this->hotbar[$s] = $this->getInt();
}
}
}
public function encode(){
$this->reset();
$this->putByte($this->windowid);
$this->putShort(count($this->slots));
foreach($this->slots as $slot){
$this->putSlot($slot);
}
if($this->windowid === 0 and count($this->hotbar) > 0){
$this->putShort(count($this->hotbar));
foreach($this->hotbar as $slot){
$this->putInt($slot);
}
}
}
}

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 ContainerSetDataPacket extends RakNetDataPacket{
public $windowid;
public $property;
public $value;
public function pid(){
return ProtocolInfo::CONTAINER_SET_DATA_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putByte($this->windowid);
$this->putShort($this->property);
$this->putShort($this->value);
}
}

View File

@ -0,0 +1,44 @@
<?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 ContainerSetSlotPacket extends RakNetDataPacket{
public $windowid;
public $slot;
public $item;
public function pid(){
return ProtocolInfo::CONTAINER_SET_SLOT_PACKET;
}
public function decode(){
$this->windowid = $this->getByte();
$this->slot = $this->getShort();
$this->item = $this->getSlot();
}
public function encode(){
$this->reset();
$this->putByte($this->windowid);
$this->putShort($this->slot);
$this->putSlot($this->item);
}
}

View File

@ -0,0 +1,35 @@
<?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 DisconnectPacket extends RakNetDataPacket{
public function pid(){
return ProtocolInfo::DISCONNECT_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
}
}

View File

@ -0,0 +1,41 @@
<?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 DropItemPacket extends RakNetDataPacket{
public $eid;
public $unknown;
public $item;
public function pid(){
return ProtocolInfo::DROP_ITEM_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->unknown = $this->getByte();
$this->item = $this->getSlot();
}
public function encode(){
}
}

View File

@ -0,0 +1,47 @@
<?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 EntityDataPacket extends RakNetDataPacket{
public $x;
public $y;
public $z;
public $namedtag;
public function pid(){
return ProtocolInfo::ENTITY_DATA_PACKET;
}
public function decode(){
$this->x = $this->getShort();
$this->y = $this->getByte();
$this->z = $this->getShort();
$this->namedtag = $this->get(true);
}
public function encode(){
$this->reset();
$this->putShort($this->x);
$this->putByte($this->y);
$this->putShort($this->z);
$this->put($this->namedtag);
}
}

View File

@ -0,0 +1,41 @@
<?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 EntityEventPacket extends RakNetDataPacket{
public $eid;
public $event;
public function pid(){
return ProtocolInfo::ENTITY_EVENT_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->event = $this->getByte();
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putByte($this->event);
}
}

View File

@ -0,0 +1,53 @@
<?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 ExplodePacket extends RakNetDataPacket{
public $x;
public $y;
public $z;
public $radius;
public $records;
public function pid(){
return ProtocolInfo::EXPLODE_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->radius);
$this->putInt(@count($this->records));
if(@count($this->records) > 0){
foreach($this->records as $record){
$this->putByte($record->x);
$this->putByte($record->y);
$this->putByte($record->z);
}
}
}
}

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 HurtArmorPacket extends RakNetDataPacket{
public $health;
public function pid(){
return ProtocolInfo::HURT_ARMOR_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putByte($this->health);
}
}

View File

@ -0,0 +1,44 @@
<?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 InteractPacket extends RakNetDataPacket{
public $action;
public $eid;
public $target;
public function pid(){
return ProtocolInfo::INTERACT_PACKET;
}
public function decode(){
$this->action = $this->getByte();
$this->eid = $this->getInt();
$this->target = $this->getInt();
}
public function encode(){
$this->reset();
$this->putByte($this->action);
$this->putInt($this->eid);
$this->putInt($this->target);
}
}

View File

@ -0,0 +1,46 @@
<?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 LevelEventPacket extends RakNetDataPacket{
public $evid;
public $x;
public $y;
public $z;
public $data;
public function pid(){
return ProtocolInfo::LEVEL_EVENT_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putShort($this->evid);
$this->putShort($this->x);
$this->putShort($this->y);
$this->putShort($this->z);
$this->putInt($this->data);
}
}

View File

@ -0,0 +1,45 @@
<?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 LoginPacket extends RakNetDataPacket{
public $username;
public $protocol1;
public $protocol2;
public $clientId;
public $loginData;
public function pid(){
return ProtocolInfo::LOGIN_PACKET;
}
public function decode(){
$this->username = $this->getString();
$this->protocol1 = $this->getInt();
$this->protocol2 = $this->getInt();
$this->clientId = $this->getInt();
$this->loginData = $this->getString();
}
public function encode(){
}
}

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 LoginStatusPacket extends RakNetDataPacket{
public $status;
public function pid(){
return ProtocolInfo::LOGIN_STATUS_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->status);
}
}

View File

@ -0,0 +1,41 @@
<?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 MessagePacket extends RakNetDataPacket{
public $source;
public $message;
public function pid(){
return ProtocolInfo::MESSAGE_PACKET;
}
public function decode(){
$this->source = $this->getString();
$this->message = $this->getString();
}
public function encode(){
$this->reset();
$this->putString($this->source);
$this->putString($this->message);
}
}

View File

@ -0,0 +1,36 @@
<?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 MoveEntityPacket extends RakNetDataPacket{
public function pid(){
return ProtocolInfo::MOVE_ENTITY_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
}
}

View File

@ -0,0 +1,48 @@
<?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 MoveEntityPacket_PosRot extends RakNetDataPacket{
public $eid;
public $x;
public $y;
public $z;
public $yaw;
public $pitch;
public function pid(){
return ProtocolInfo::MOVE_ENTITY_PACKET_POSROT;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->yaw);
$this->putFloat($this->pitch);
}
}

View File

@ -0,0 +1,56 @@
<?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 MovePlayerPacket extends RakNetDataPacket{
public $eid;
public $x;
public $y;
public $z;
public $yaw;
public $pitch;
public $bodyYaw;
public function pid(){
return ProtocolInfo::MOVE_PLAYER_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->x = $this->getFloat();
$this->y = $this->getFloat();
$this->z = $this->getFloat();
$this->yaw = $this->getFloat();
$this->pitch = $this->getFloat();
$this->bodyYaw = $this->getFloat();
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
$this->putFloat($this->yaw);
$this->putFloat($this->pitch);
$this->putFloat($this->bodyYaw);
}
}

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 PingPacket extends RakNetDataPacket{
public $time = 0;
public function pid(){
return ProtocolInfo::PING_PACKET;
}
public function decode(){
$this->time = $this->getLong();
}
public function encode(){
$this->reset();
$this->putLong($this->time);
}
}

View File

@ -0,0 +1,47 @@
<?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 PlayerActionPacket extends RakNetDataPacket{
public $action;
public $x;
public $y;
public $z;
public $face;
public $eid;
public function pid(){
return ProtocolInfo::PLAYER_ACTION_PACKET;
}
public function decode(){
$this->action = $this->getInt();
$this->x = $this->getInt();
$this->y = $this->getInt();
$this->z = $this->getInt();
$this->face = $this->getInt();
$this->eid = $this->getInt();
}
public function encode(){
}
}

View File

@ -0,0 +1,47 @@
<?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 PlayerArmorEquipmentPacket extends RakNetDataPacket{
public $eid;
public $slots = array();
public function pid(){
return ProtocolInfo::PLAYER_ARMOR_EQUIPMENT_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->slots[0] = $this->getByte();
$this->slots[1] = $this->getByte();
$this->slots[2] = $this->getByte();
$this->slots[3] = $this->getByte();
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putByte($this->slots[0]);
$this->putByte($this->slots[1]);
$this->putByte($this->slots[2]);
$this->putByte($this->slots[3]);
}
}

View File

@ -0,0 +1,47 @@
<?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 PlayerEquipmentPacket extends RakNetDataPacket{
public $eid;
public $item;
public $meta;
public $slot;
public function pid(){
return ProtocolInfo::PLAYER_EQUIPMENT_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->item = $this->getShort();
$this->meta = $this->getShort();
$this->slot = $this->getByte();
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putShort($this->item);
$this->putShort($this->meta);
$this->putByte($this->slot);
}
}

View File

@ -0,0 +1,41 @@
<?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 PongPacket extends RakNetDataPacket{
public $time = 0;
public $ptime = 0;
public function pid(){
return ProtocolInfo::PONG_PACKET;
}
public function decode(){
$this->ptime = $this->getLong();
$this->time = $this->getLong();
}
public function encode(){
$this->reset();
$this->putLong($this->ptime);
$this->putLong($this->time);
}
}

View File

@ -0,0 +1,37 @@
<?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 ReadyPacket extends RakNetDataPacket{
public $status;
public function pid(){
return ProtocolInfo::READY_PACKET;
}
public function decode(){
$this->status = $this->getByte();
}
public function encode(){
}
}

View File

@ -0,0 +1,43 @@
<?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 RemoveBlockPacket extends RakNetDataPacket{
public $eid;
public $x;
public $y;
public $z;
public function pid(){
return ProtocolInfo::REMOVE_BLOCK_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->x = $this->getInt();
$this->z = $this->getInt();
$this->y = $this->getByte();
}
public function encode(){
}
}

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 RemoveEntityPacket extends RakNetDataPacket{
public $eid;
public function pid(){
return ProtocolInfo::REMOVE_ENTITY_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
}
}

View File

@ -0,0 +1,40 @@
<?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 RemovePlayerPacket extends RakNetDataPacket{
public $eid;
public $clientID;
public function pid(){
return ProtocolInfo::REMOVE_PLAYER_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putLong($this->clientID);
}
}

View File

@ -0,0 +1,39 @@
<?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 RequestChunkPacket extends RakNetDataPacket{
public $chunkX;
public $chunkZ;
public function pid(){
return ProtocolInfo::REQUEST_CHUNK_PACKET;
}
public function decode(){
$this->chunkX = $this->getInt();
$this->chunkZ = $this->getInt();
}
public function encode(){
}
}

View File

@ -0,0 +1,47 @@
<?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 RespawnPacket extends RakNetDataPacket{
public $eid;
public $x;
public $y;
public $z;
public function pid(){
return ProtocolInfo::RESPAWN_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->x = $this->getFloat();
$this->y = $this->getFloat();
$this->z = $this->getFloat();
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
}
}

View File

@ -0,0 +1,40 @@
<?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 RotateHeadPacket extends RakNetDataPacket{
public $eid;
public $yaw;
public function pid(){
return ProtocolInfo::ROTATE_HEAD_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putByte($this->yaw);
}
}

View File

@ -0,0 +1,61 @@
<?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 SendInventoryPacket extends RakNetDataPacket{
public $eid;
public $windowid;
public $slots = array();
public $armor = array();
public function pid(){
return ProtocolInfo::SEND_INVENTORY_PACKET;
}
public function decode(){
$this->eid = $this->getInt();
$this->windowid = $this->getByte();
$count = $this->getShort();
for($s = 0; $s < $count and !$this->feof(); ++$s){
$this->slots[$s] = $this->getSlot();
}
if($this->windowid === 1){ //Armir is sent
for($s = 0; $s < 4; ++$s){
$this->armor[$s] = $this->getSlot();
}
}
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putByte($this->windowid);
$this->putShort(count($this->slots));
foreach($this->slots as $slot){
$this->putSlot($slot);
}
if($this->windowid === 1 and count($this->armor) === 4){
for($s = 0; $s < 4; ++$s){
$this->putSlot($this->armor[$s]);
}
}
}
}

View File

@ -0,0 +1,57 @@
<?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 ServerHandshakePacket extends RakNetDataPacket{
public $port;
public $session;
public $session2;
public function pid(){
return ProtocolInfo::SERVER_HANDSHAKE_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->put("\x04\x3f\x57\xfe"); //cookie
$this->put("\xcd"); //Security flags
$this->putShort($this->port);
$this->putDataArray(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->put("\x00\x00");
$this->putLong($this->session);
$this->putLong($this->session2);
}
}

View File

@ -0,0 +1,40 @@
<?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 SetEntityDataPacket extends RakNetDataPacket{
public $eid;
public $metadata;
public function pid(){
return ProtocolInfo::SET_ENTITY_DATA_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->put(Utils::writeMetadata($this->metadata));
}
}

View File

@ -0,0 +1,44 @@
<?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 SetEntityMotionPacket extends RakNetDataPacket{
public $eid;
public $speedX;
public $speedY;
public $speedZ;
public function pid(){
return ProtocolInfo::SET_ENTITY_MOTION_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->eid);
$this->putShort((int) ($this->speedX * 400));
$this->putShort((int) ($this->speedY * 400));
$this->putShort((int) ($this->speedZ * 400));
}
}

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 SetHealthPacket extends RakNetDataPacket{
public $health;
public function pid(){
return ProtocolInfo::SET_HEALTH_PACKET;
}
public function decode(){
$this->health = $this->getByte();
}
public function encode(){
$this->reset();
$this->putByte($this->health);
}
}

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 SetSpawnPositionPacket extends RakNetDataPacket{
public $x;
public $z;
public $y;
public function pid(){
return ProtocolInfo::SET_SPAWN_POSITION_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->x);
$this->putInt($this->z);
$this->putByte($this->y);
}
}

View File

@ -0,0 +1,40 @@
<?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 SetTimePacket extends RakNetDataPacket{
public $time;
public $started = true;
public function pid(){
return ProtocolInfo::SET_TIME_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->time);
$this->putByte($this->started == true ? 0x80:0x00);
}
}

View File

@ -0,0 +1,50 @@
<?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 StartGamePacket extends RakNetDataPacket{
public $seed;
public $generator;
public $gamemode;
public $eid;
public $x;
public $y;
public $z;
public function pid(){
return ProtocolInfo::START_GAME_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->seed);
$this->putInt($this->generator);
$this->putInt($this->gamemode);
$this->putInt($this->eid);
$this->putFloat($this->x);
$this->putFloat($this->y);
$this->putFloat($this->z);
}
}

View File

@ -0,0 +1,40 @@
<?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 TakeItemEntityPacket extends RakNetDataPacket{
public $target;
public $eid;
public function pid(){
return ProtocolInfo::TAKE_ITEM_ENTITY_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->target);
$this->putInt($this->eid);
}
}

View File

@ -0,0 +1,46 @@
<?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 TileEventPacket extends RakNetDataPacket{
public $x;
public $y;
public $z;
public $case1;
public $case2;
public function pid(){
return ProtocolInfo::TILE_EVENT_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->x);
$this->putInt($this->y);
$this->putInt($this->z);
$this->putInt($this->case1);
$this->putInt($this->case2);
}
}

View File

@ -0,0 +1,37 @@
<?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 UnknownPacket extends RakNetDataPacket{
public $packetID = -1;
public function pid(){
return $this->packetID;
}
public function decode(){
}
public function encode(){
}
}

View File

@ -0,0 +1,46 @@
<?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 UpdateBlockPacket extends RakNetDataPacket{
public $x;
public $z;
public $y;
public $block;
public $meta;
public function pid(){
return ProtocolInfo::UPDATE_BLOCK_PACKET;
}
public function decode(){
}
public function encode(){
$this->reset();
$this->putInt($this->x);
$this->putInt($this->z);
$this->putByte($this->y);
$this->putByte($this->block);
$this->putByte($this->meta);
}
}

View File

@ -0,0 +1,61 @@
<?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 UseItemPacket extends RakNetDataPacket{
public $x;
public $y;
public $z;
public $face;
public $item;
public $meta;
public $eid;
public $fx;
public $fy;
public $fz;
public $posX;
public $posY;
public $posZ;
public function pid(){
return ProtocolInfo::USE_ITEM_PACKET;
}
public function decode(){
$this->x = $this->getInt();
$this->y = $this->getInt();
$this->z = $this->getInt();
$this->face = $this->getInt();
$this->item = $this->getShort();
$this->meta = $this->getByte(); //Mojang: fix this
$this->eid = $this->getInt();
$this->fx = $this->getFloat();
$this->fy = $this->getFloat();
$this->fz = $this->getFloat();
$this->posX = $this->getFloat();
$this->posY = $this->getFloat();
$this->posZ = $this->getFloat();
}
public function encode(){
}
}

View File

@ -24,7 +24,7 @@ Implementation of the UT3 Query Protocol (GameSpot)
Source: http://wiki.unrealadmin.org/UT3_query_protocol Source: http://wiki.unrealadmin.org/UT3_query_protocol
*/ */
class Query{ class QueryHandler{
private $socket, $server, $lastToken, $token, $longData, $timeout; private $socket, $server, $lastToken, $token, $longData, $timeout;
public function __construct(){ public function __construct(){
@ -41,7 +41,7 @@ class Query{
Then, the Query class handles itself sending the packets in raw form, because Then, the Query class handles itself sending the packets in raw form, because
packets can conflict with the MCPE ones. packets can conflict with the MCPE ones.
*/ */
$this->server->addHandler("server.unknownpacket", array($this, "packetHandler"), 50);
$this->server->schedule(20 * 30, array($this, "regenerateToken"), array(), true); $this->server->schedule(20 * 30, array($this, "regenerateToken"), array(), true);
$this->regenerateToken(); $this->regenerateToken();
$this->lastToken = $this->token; $this->lastToken = $this->token;
@ -94,40 +94,41 @@ class Query{
$this->token = Utils::readInt("\x00".Utils::getRandomBytes(3, false)); $this->token = Utils::readInt("\x00".Utils::getRandomBytes(3, false));
} }
public function packetHandler(&$packet, $event){ public function handle(QueryPacket $packet){
if($event !== "server.unknownpacket"){ $packet->decode();
return; switch($packet->packetType){
} case QueryPacket::HANDSHAKE: //Handshake
$magic = substr($packet["raw"], 0, 2); $pk = new QueryPacket;
$offset = 2; $pk->ip = $packet->ip;
if($magic !== "\xfe\xfd"){ $pk->port = $packet->port;
return; $pk->packetType = QueryPacket::HANDSHAKE;
} $pk->sessionID = $packet->sessionID;
$type = ord($packet["raw"]{2}); $pk->payload = $this->token."\x00";
++$offset; $pk->encode();
$sessionID = Utils::readInt(substr($packet["raw"], $offset, 4)); $this->server->send($pk);
$offset += 4;
$payload = substr($packet["raw"], $offset);
switch($type){
case 9: //Handshake
$this->server->send(9, chr(9).Utils::writeInt($sessionID).$this->token."\x00", true, $packet["ip"], $packet["port"]);
break; break;
case 0: //Stat case QueryPacket::STATISTICS: //Stat
$token = Utils::readInt(substr($payload, 0, 4)); $token = Utils::readInt(substr($packet->payload, 0, 4));
if($token !== $this->token and $token !== $this->lastToken){ if($token !== $this->token and $token !== $this->lastToken){
break; break;
} }
if(strlen($payload) === 8){ $pk = new QueryPacket;
$pk->ip = $packet->ip;
$pk->port = $packet->port;
$pk->packetType = QueryPacket::STATISTICS;
$pk->sessionID = $packet->sessionID;
if(strlen($packet->payload) === 8){
if($this->timeout < microtime(true)){ if($this->timeout < microtime(true)){
$this->regenerateInfo(); $this->regenerateInfo();
} }
$this->server->send(0, chr(0).Utils::writeInt($sessionID).$this->longData, true, $packet["ip"], $packet["port"]); $pk->payload = $this->longData;
}else{ }else{
$this->server->send(0, chr(0).Utils::writeInt($sessionID).$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", true, $packet["ip"], $packet["port"]); $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->encode();
$this->server->send($pk);
break; break;
} }
return true;
} }
} }

View File

@ -0,0 +1,41 @@
<?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 QueryPacket extends Packet{
const HANDSHAKE = 9;
const STATISTICS = 0;
public $packetType;
public $sessionID;
public $payload;
public function decode(){
$this->packetType = ord($this->buffer{2});
$this->sessionID = Utils::readInt(substr($this->buffer, 3, 4));
$this->payload = substr($this->buffer, 7);
}
public function encode(){
$this->buffer .= chr($this->packetType);
$this->buffer .= Utils::writeInt($this->sessionID);
$this->buffer .= $this->payload;
}
}

View File

@ -0,0 +1,184 @@
<?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 RakNetCodec{
public $packet;
public function __construct(RakNetPacket $packet){
$this->packet = $packet;
$this->buffer =& $this->packet->buffer;
$this->encode();
}
private function encode(){
if(strlen($this->packet->buffer) > 0){
return;
}
$this->buffer .= chr($this->packet->pid());
switch($this->packet->pid()){
case RakNetInfo::OPEN_CONNECTION_REPLY_1:
$this->buffer .= RakNetInfo::MAGIC;
$this->putLong($this->packet->serverID);
$this->putByte(0); //server security
$this->putShort($this->packet->mtuSize);
break;
case RakNetInfo::OPEN_CONNECTION_REPLY_2:
$this->buffer .= RakNetInfo::MAGIC;
$this->putLong($this->packet->serverID);
$this->putShort($this->packet->port);
$this->putShort($this->packet->mtuSize);
$this->putByte(0); //Server security
break;
case RakNetInfo::INCOMPATIBLE_PROTOCOL_VERSION:
$this->putByte(RakNetInfo::STRUCTURE);
$this->buffer .= RakNetInfo::MAGIC;
$this->putLong($this->packet->serverID);
break;
case RakNetInfo::UNCONNECTED_PONG:
case RakNetInfo::ADVERTISE_SYSTEM:
$this->putLong($this->packet->pingID);
$this->putLong($this->packet->serverID);
$this->buffer .= RakNetInfo::MAGIC;
$this->putString($this->packet->serverType);
break;
case RakNetInfo::DATA_PACKET_0:
case RakNetInfo::DATA_PACKET_1:
case RakNetInfo::DATA_PACKET_2:
case RakNetInfo::DATA_PACKET_3:
case RakNetInfo::DATA_PACKET_4:
case RakNetInfo::DATA_PACKET_5:
case RakNetInfo::DATA_PACKET_6:
case RakNetInfo::DATA_PACKET_7:
case RakNetInfo::DATA_PACKET_8:
case RakNetInfo::DATA_PACKET_9:
case RakNetInfo::DATA_PACKET_A:
case RakNetInfo::DATA_PACKET_B:
case RakNetInfo::DATA_PACKET_C:
case RakNetInfo::DATA_PACKET_D:
case RakNetInfo::DATA_PACKET_E:
case RakNetInfo::DATA_PACKET_F:
$this->putLTriad($this->packet->seqNumber);
foreach($this->packet->data as $pk){
$this->encodeDataPacket($pk);
}
break;
case RakNetInfo::NACK:
case RakNetInfo::ACK:
$payload = b"";
$records = 0;
$pointer = 0;
sort($this->packet->packets, SORT_NUMERIC);
$max = count($this->packet->packets);
while($pointer < $max){
$type = true;
$curr = $start = $this->packet->packets[$pointer];
for($i = $start + 1; $i < $max; ++$i){
$n = $this->packet->packets[$i];
if(($n - $curr) === 1){
$curr = $end = $n;
$type = false;
$pointer = $i + 1;
}else{
break;
}
}
++$pointer;
if($type === false){
$payload .= "\x00";
$payload .= strrev(Utils::writeTriad($start));
$payload .= strrev(Utils::writeTriad($end));
}else{
$payload .= Utils::writeBool(true);
$payload .= strrev(Utils::writeTriad($start));
}
++$records;
}
$this->putShort($records);
$this->buffer .= $payload;
break;
default:
}
}
private function encodeDataPacket(RakNetDataPacket $pk){
$this->putByte(($pk->reliability << 5) | ($pk->hasSplit > 0 ? 0b00010000:0));
$this->putShort(strlen($pk->buffer) << 3);
if($pk->reliability === 2
or $pk->reliability === 3
or $pk->reliability === 4
or $pk->reliability === 6
or $pk->reliability === 7){
$this->putLTriad($pk->messageIndex);
}
if($pk->reliability === 1
or $pk->reliability === 3
or $pk->reliability === 4
or $pk->reliability === 7){
$this->putLTriad($pk->orderIndex);
$this->putByte($pk->orderChannel);
}
if($pk->hasSplit === true){
$this->putInt($pk->splitCount);
$this->putShort($pk->splitID);
$this->putInt($pk->splitIndex);
}
$this->buffer .= $pk->buffer;
}
protected function put($str){
$this->buffer .= $str;
}
protected function putLong($v){
$this->buffer .= Utils::writeLong($v);
}
protected function putInt($v){
$this->buffer .= Utils::writeInt($v);
}
protected function putShort($v){
$this->buffer .= Utils::writeShort($v);
}
protected function putTriad($v){
$this->buffer .= Utils::writeTriad($v);
}
protected function putLTriad($v){
$this->buffer .= strrev(Utils::writeTriad($v));
}
protected function putByte($v){
$this->buffer .= chr($v);
}
protected function putString($v){
$this->putShort(strlen($v));
$this->put($v);
}
}

View File

@ -0,0 +1,171 @@
<?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 RakNetDataPacket extends stdClass{
private $offset = 0;
public $buffer = b"";
public $reliability = 0;
public $hasSplit = false;
public $messageIndex;
public $orderIndex;
public $orderChannel;
public $splitCount;
public $splitID;
public $splitIndex;
abstract public function pid();
abstract public function encode();
abstract public function decode();
protected function reset(){
$this->setBuffer(chr($this->pid()));
}
public function setBuffer($buffer = ""){
$this->buffer = $buffer;
$this->offset = 0;
}
public function getBuffer(){
return $this->buffer;
}
protected 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);
}
protected function put($str){
$this->buffer .= $str;
}
protected function getLong($unsigned = false){
return Utils::readLong($this->get(8), $unsigned);
}
protected function putLong($v){
$this->buffer .= Utils::writeLong($v);
}
protected function getInt($unsigned = false){
return Utils::readInt($this->get(4), $unsigned);
}
protected function putInt($v){
$this->buffer .= Utils::writeInt($v);
}
protected function getShort($unsigned = false){
return Utils::readShort($this->get(2), $unsigned);
}
protected function putShort($v){
$this->buffer .= Utils::writeShort($v);
}
protected function getFloat(){
return Utils::readFloat($this->get(4));
}
protected function putFloat($v){
$this->buffer .= Utils::writeFloat($v);
}
protected function getTriad(){
return Utils::readTriad($this->get(3));
}
protected function putTriad($v){
$this->buffer .= Utils::writeTriad($v);
}
protected function getLTriad(){
return Utils::readTriad(strrev($this->get(3)));
}
protected function putLTriad($v){
$this->buffer .= strrev(Utils::writeTriad($v));
}
protected function getByte(){
return ord($this->get(1));
}
protected function putByte($v){
$this->buffer .= chr($v);
}
protected function getDataArray($len = 10){
$data = array();
for($i = 1; $i <= $len and !$this->feof(); ++$i){
$data[] = $this->get($this->getTriad());
}
return $data;
}
protected function putDataArray(array $data = array()){
foreach($data as $v){
$this->putTriad(strlen($v));
$this->put($v);
}
}
protected function getSlot(){
$id = $this->getShort();
$cnt = $this->getByte();
return BlockAPI::getItem(
$id,
$this->getShort(),
$cnt
);
}
protected function putSlot(Item $item){
$this->putShort($item->getID());
$this->putByte($item->count);
$this->putShort($item->getMetadata());
}
protected function getString(){
return $this->get($this->getShort(true));
}
protected function putString($v){
$this->putShort(strlen($v));
$this->put($v);
}
protected function feof(){
return !isset($this->buffer{$this->offset});
}
}

View File

@ -0,0 +1,94 @@
<?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 RakNetInfo{
const STRUCTURE = 5;
const MAGIC = "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78";
const UNCONNECTED_PING = 0x01;
const UNCONNECTED_PING_OPEN_CONNECTIONS = 0x02;
const OPEN_CONNECTION_REQUEST_1 = 0x05;
const OPEN_CONNECTION_REPLY_1 = 0x06;
const OPEN_CONNECTION_REQUEST_2 = 0x07;
const OPEN_CONNECTION_REPLY_2 = 0x08;
const INCOMPATIBLE_PROTOCOL_VERSION = 0x1a; //CHECK THIS
const UNCONNECTED_PONG = 0x1c;
const ADVERTISE_SYSTEM = 0x1d;
const DATA_PACKET_0 = 0x80;
const DATA_PACKET_1 = 0x81;
const DATA_PACKET_2 = 0x82;
const DATA_PACKET_3 = 0x83;
const DATA_PACKET_4 = 0x84;
const DATA_PACKET_5 = 0x85;
const DATA_PACKET_6 = 0x86;
const DATA_PACKET_7 = 0x87;
const DATA_PACKET_8 = 0x88;
const DATA_PACKET_9 = 0x89;
const DATA_PACKET_A = 0x8a;
const DATA_PACKET_B = 0x8b;
const DATA_PACKET_C = 0x8c;
const DATA_PACKET_D = 0x8d;
const DATA_PACKET_E = 0x8e;
const DATA_PACKET_F = 0x8f;
const NACK = 0xa0;
const ACK = 0xc0;
public static function isValid($pid){
switch((int) $pid){
case RakNetInfo::UNCONNECTED_PING:
case RakNetInfo::UNCONNECTED_PING_OPEN_CONNECTIONS:
case RakNetInfo::OPEN_CONNECTION_REQUEST_1:
case RakNetInfo::OPEN_CONNECTION_REPLY_1:
case RakNetInfo::OPEN_CONNECTION_REQUEST_2:
case RakNetInfo::OPEN_CONNECTION_REPLY_2:
case RakNetInfo::INCOMPATIBLE_PROTOCOL_VERSION:
case RakNetInfo::UNCONNECTED_PONG:
case RakNetInfo::ADVERTISE_SYSTEM:
case RakNetInfo::DATA_PACKET_0:
case RakNetInfo::DATA_PACKET_1:
case RakNetInfo::DATA_PACKET_2:
case RakNetInfo::DATA_PACKET_3:
case RakNetInfo::DATA_PACKET_4:
case RakNetInfo::DATA_PACKET_5:
case RakNetInfo::DATA_PACKET_6:
case RakNetInfo::DATA_PACKET_7:
case RakNetInfo::DATA_PACKET_8:
case RakNetInfo::DATA_PACKET_9:
case RakNetInfo::DATA_PACKET_A:
case RakNetInfo::DATA_PACKET_B:
case RakNetInfo::DATA_PACKET_C:
case RakNetInfo::DATA_PACKET_D:
case RakNetInfo::DATA_PACKET_E:
case RakNetInfo::DATA_PACKET_F:
case RakNetInfo::NACK:
case RakNetInfo::ACK:
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,34 @@
<?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 RakNetPacket extends Packet{
private $packetID;
public function __construct($packetID){
$this->packetID = (int) $packetID;
}
public function pid(){
return $this->packetID;
}
public function __destruct(){}
}

View File

@ -0,0 +1,208 @@
<?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 RakNetParser{
private $buffer;
private $offset;
public $packet;
public function __construct(&$buffer){
$this->buffer =& $buffer;
$this->offset = 0;
if(strlen($this->buffer) > 0){
$this->parse();
}else{
$this->packet = false;
}
}
private 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);
}
private function getLong($unsigned = false){
return Utils::readLong($this->get(8), $unsigned);
}
private function getInt($unsigned = false){
return Utils::readInt($this->get(4), $unsigned);
}
private function getShort($unsigned = false){
return Utils::readShort($this->get(2), $unsigned);
}
private function getLTriad(){
return Utils::readTriad(strrev($this->get(3)));
}
private function getByte(){
return ord($this->get(1));
}
private function feof(){
return !isset($this->buffer{$this->offset});
}
private function parse(){
$this->packet = new RakNetPacket(ord($this->get(1)));
$this->packet->buffer =& $this->buffer;
$this->packet->length = strlen($this->buffer);
switch($this->packet->pid()){
case RakNetInfo::UNCONNECTED_PING:
case RakNetInfo::UNCONNECTED_PING_OPEN_CONNECTIONS:
$this->packet->pingID = $this->getLong();
$this->offset += 16; //Magic
break;
case RakNetInfo::OPEN_CONNECTION_REQUEST_1:
$this->offset += 16; //Magic
$this->packet->structure = $this->getByte();
$this->packet->mtuSize = strlen($this->get(true));
break;
case RakNetInfo::OPEN_CONNECTION_REQUEST_2:
$this->offset += 16; //Magic
$this->packet->security = $this->get(5);
$this->packet->port = $this->getShort(false);
$this->packet->mtuSize = $this->getShort(false);
$this->packet->clientID = $this->getLong();
break;
case RakNetInfo::DATA_PACKET_0:
case RakNetInfo::DATA_PACKET_1:
case RakNetInfo::DATA_PACKET_2:
case RakNetInfo::DATA_PACKET_3:
case RakNetInfo::DATA_PACKET_4:
case RakNetInfo::DATA_PACKET_5:
case RakNetInfo::DATA_PACKET_6:
case RakNetInfo::DATA_PACKET_7:
case RakNetInfo::DATA_PACKET_8:
case RakNetInfo::DATA_PACKET_9:
case RakNetInfo::DATA_PACKET_A:
case RakNetInfo::DATA_PACKET_B:
case RakNetInfo::DATA_PACKET_C:
case RakNetInfo::DATA_PACKET_D:
case RakNetInfo::DATA_PACKET_E:
case RakNetInfo::DATA_PACKET_F:
$this->packet->seqNumber = $this->getLTriad();
$this->packet->data = array();
while(!$this->feof() and ($pk = $this->parseDataPacket()) instanceof RakNetDataPacket){
$this->packet->data[] = $pk;
}
break;
case RakNetInfo::NACK:
case RakNetInfo::ACK:
$count = $this->getShort();
$this->packet->packets = array();
for($i = 0; $i < $count and !$this->feof(); ++$i){
if($this->getByte() === 0){
$start = $this->getLTriad();
$end = $this->getLTriad();
if(($end - $start) > 4096){
$end = $start + 4096;
}
for($c = $start; $c <= $end; ++$c){
$this->packet->packets[] = $c;
}
}else{
$this->packet->packets[] = $this->getLTriad();
}
}
break;
default:
$this->packet = false;
break;
}
}
private function parseDataPacket(){
$packetFlags = $this->getByte();
$reliability = ($packetFlags & 0b11100000) >> 5;
$hasSplit = ($packetFlags & 0b00010000) > 0;
$length = (int) ceil($this->getShort() / 8);
if($reliability === 2
or $reliability === 3
or $reliability === 4
or $reliability === 6
or $reliability === 7){
$messageIndex = $this->getLTriad();
}else{
$messageIndex = false;
}
if($reliability === 1
or $reliability === 3
or $reliability === 4
or $reliability === 7){
$orderIndex = $this->getLTriad();
$orderChannel = $this->getByte();
}else{
$orderIndex = false;
$orderChannel = false;
}
if($hasSplit == true){
$splitCount = $this->getInt();
$splitID = $this->getShort();
$splitIndex = $this->getInt();
}else{
$splitCount = false;
$splitID = false;
$splitIndex = false;
}
if($length <= 0
or $orderChannel >= 32
or ($hasSplit === true and $splitIndex >= $splitCount)){
return false;
}else{
$pid = $this->getByte();
$buffer = $this->get($length - 1);
if(strlen($buffer) < ($length - 1)){
return false;
}
if(isset(ProtocolInfo::$packets[$pid])){
$data = new ProtocolInfo::$packets[$pid];
}else{
$data = new UnknownPacket();
$data->packetID = $pid;
}
$data->reliability = $reliability;
$data->hasSplit = $hasSplit;
$data->messageIndex = $messageIndex;
$data->orderIndex = $orderIndex;
$data->orderChannel = $orderChannel;
$data->splitCount = $splitCount;
$data->splitID = $splitID;
$data->splitIndex = $splitIndex;
$data->setBuffer($buffer);
}
return $data;
}
}

View File

@ -28,7 +28,7 @@ class Cache{
public static function get($identifier){ public static function get($identifier){
if(isset(self::$cached[$identifier])){ if(isset(self::$cached[$identifier])){
self::$cached[$identifier][1] += $minTTL; self::$cached[$identifier][1] = microtime(true) + self::$cached[$identifier][2];
return self::$cached[$identifier][0]; return self::$cached[$identifier][0];
} }
return false; return false;

View File

@ -31,6 +31,14 @@ class Utils{
return ((@fsockopen("8.8.8.8", 80, $e = null, $n = null, 2) !== false or @fsockopen("www.linux.org", 80, $e = null, $n = null, 2) !== false or @fsockopen("www.php.net", 80, $e = null, $n = null, 2) !== false) ? true:false); return ((@fsockopen("8.8.8.8", 80, $e = null, $n = null, 2) !== false or @fsockopen("www.linux.org", 80, $e = null, $n = null, 2) !== false or @fsockopen("www.php.net", 80, $e = null, $n = null, 2) !== false) ? true:false);
} }
public static function getCallableIdentifier(callable $variable){
if(is_array($variable)){
return sha1(strtolower(get_class($variable))."::".strtolower($variable[1]));
}else{
return sha1(strtolower($variable));
}
}
public static function getUniqueID($raw = false, $extra = ""){ public static function getUniqueID($raw = false, $extra = ""){
$machine = php_uname("a"); $machine = php_uname("a");
$machine .= file_exists("/proc/cpuinfo") ? file_get_contents("/proc/cpuinfo") : ""; $machine .= file_exists("/proc/cpuinfo") ? file_get_contents("/proc/cpuinfo") : "";

View File

@ -572,24 +572,24 @@ class Entity extends Position{
$players = $this->server->api->player->getAll($this->level); $players = $this->server->api->player->getAll($this->level);
if($this->player instanceof Player){ if($this->player instanceof Player){
unset($players[$this->player->CID]); unset($players[$this->player->CID]);
$this->server->api->player->broadcastPacket($players, MC_MOVE_PLAYER, array( $pk = new MovePlayerPacket;
"eid" => $this->eid, $pk->eid = $this->eid;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"yaw" => $this->yaw, $pk->yaw = $this->yaw;
"pitch" => $this->pitch, $pk->pitch = $this->pitch;
"bodyYaw" => $this->yaw, $pk->bodyYaw = $this->yaw;
)); $this->server->api->player->broadcastPacket($players, $pk);
}else{ }else{
$this->server->api->player->broadcastPacket($players, MC_MOVE_ENTITY_POSROT, array( $pk = new MoveEntityPacket_PosRot;
"eid" => $this->eid, $pk->eid = $this->eid;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"yaw" => $this->yaw, $pk->yaw = $this->yaw;
"pitch" => $this->pitch, $pk->pitch = $this->pitch;
)); $this->server->api->player->broadcastPacket($players, $pk);
} }
} }
}else{ }else{
@ -661,116 +661,135 @@ class Entity extends Position{
if($this->player->connected !== true or $this->player->spawned === false){ if($this->player->connected !== true or $this->player->spawned === false){
return false; return false;
} }
$player->dataPacket(MC_ADD_PLAYER, array(
"clientID" => 0,/*$this->player->clientID,*/ $pk = new AddPlayerPacket;
"username" => $this->player->username, $pk->clientID = 0; //$this->player->clientID;
"eid" => $this->eid, $pk->username = $this->player->username;
"x" => $this->x, $pk->eid = $this->eid;
"y" => $this->y, $pk->x = $this->x;
"z" => $this->z, $pk->y = $this->y;
"yaw" => 0, $pk->z = $this->z;
"pitch" => 0, $pk->yaw = 0;
"unknown1" => 0, $pk->pitch = 0;
"unknown2" => 0, $pk->unknown1 = 0;
"metadata" => $this->getMetadata(), $pk->unknown2 = 0;
)); $pk->metadata = $this->getMetadata();
$player->dataPacket(MC_PLAYER_EQUIPMENT, array( $player->dataPacket($pk);
"eid" => $this->eid,
"block" => $this->player->getSlot($this->player->slot)->getID(), $pk = new SetEntityMotionPacket;
"meta" => $this->player->getSlot($this->player->slot)->getMetadata(), $pk->eid = $this->eid;
"slot" => 0, $pk->speedX = $this->speedX;
)); $pk->speedY = $this->speedY;
$pk->speedZ = $this->speedZ;
$player->dataPacket($pk);
$pk = new PlayerEquipmentPacket;
$pk->eid = $this->eid;
$pk->item = $this->player->getSlot($this->player->slot)->getID();
$pk->meta = $this->player->getSlot($this->player->slot)->getMetadata();
$pk->slot = 0;
$player->dataPacket($pk);
$this->player->sendArmor($player); $this->player->sendArmor($player);
break; break;
case ENTITY_ITEM: case ENTITY_ITEM:
$player->dataPacket(MC_ADD_ITEM_ENTITY, array( $pk = new AddItemEntityPacket;
"eid" => $this->eid, $pk->eid = $this->eid;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"yaw" => $this->yaw, $pk->yaw = $this->yaw;
"pitch" => $this->pitch, $pk->pitch = $this->pitch;
"roll" => 0, $pk->roll = 0;
"block" => $this->type, $pk->item = BlockAPI::getItem($this->type, $this->meta, $this->stack);
"meta" => $this->meta, $pk->metadata = $this->getMetadata();
"stack" => $this->stack, $player->dataPacket($pk);
));
$player->dataPacket(MC_SET_ENTITY_MOTION, array( $pk = new SetEntityMotionPacket;
"eid" => $this->eid, $pk->eid = $this->eid;
"speedX" => (int) ($this->speedX * 400), $pk->speedX = $this->speedX;
"speedY" => (int) ($this->speedY * 400), $pk->speedY = $this->speedY;
"speedZ" => (int) ($this->speedZ * 400), $pk->speedZ = $this->speedZ;
)); $player->dataPacket($pk);
break; break;
case ENTITY_MOB: case ENTITY_MOB:
$player->dataPacket(MC_ADD_MOB, array( $pk = new AddMobPacket;
"type" => $this->type, $pk->eid = $this->eid;
"eid" => $this->eid, $pk->type = $this->type;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"yaw" => 0, $pk->yaw = $this->yaw;
"pitch" => 0, $pk->pitch = $this->pitch;
"metadata" => $this->getMetadata(), $pk->metadata = $this->getMetadata();
)); $player->dataPacket($pk);
$player->dataPacket(MC_SET_ENTITY_MOTION, array(
"eid" => $this->eid, $pk = new SetEntityMotionPacket;
"speedX" => (int) ($this->speedX * 400), $pk->eid = $this->eid;
"speedY" => (int) ($this->speedY * 400), $pk->speedX = $this->speedX;
"speedZ" => (int) ($this->speedZ * 400), $pk->speedY = $this->speedY;
)); $pk->speedZ = $this->speedZ;
$player->dataPacket($pk);
break; break;
case ENTITY_OBJECT: case ENTITY_OBJECT:
if($this->type === OBJECT_PAINTING){ if($this->type === OBJECT_PAINTING){
$player->dataPacket(MC_ADD_PAINTING, array( $pk = new AddPaintingPacket;
"eid" => $this->eid, $pk->eid = $this->eid;
"x" => (int) $this->x, $pk->x = (int) $this->x;
"y" => (int) $this->y, $pk->y = (int) $this->y;
"z" => (int) $this->z, $pk->z = (int) $this->z;
"direction" => $this->getDirection(), $pk->direction = $this->getDirection();
"title" => $this->data["Motive"], $pk->title = $this->data["Motive"];
)); $player->dataPacket($pk);
}elseif($this->type === OBJECT_PRIMEDTNT){ }elseif($this->type === OBJECT_PRIMEDTNT){
$player->dataPacket(MC_ADD_ENTITY, array( $pk = new AddEntityPacket;
"eid" => $this->eid, $pk->eid = $this->eid;
"type" => $this->type, $pk->type = $this->type;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"did" => 0, $pk->did = 0;
)); $player->dataPacket($pk);
$pk = new SetEntityMotionPacket;
$pk->eid = $this->eid;
$pk->speedX = $this->speedX;
$pk->speedY = $this->speedY;
$pk->speedZ = $this->speedZ;
$player->dataPacket($pk);
}elseif($this->type === OBJECT_ARROW){ }elseif($this->type === OBJECT_ARROW){
$player->dataPacket(MC_ADD_ENTITY, array( $pk = new AddEntityPacket;
"eid" => $this->eid, $pk->eid = $this->eid;
"type" => $this->type, $pk->type = $this->type;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"did" => 0, $pk->did = 0;
)); $player->dataPacket($pk);
$player->dataPacket(MC_SET_ENTITY_MOTION, array(
"eid" => $this->eid, $pk = new SetEntityMotionPacket;
"speedX" => (int) ($this->speedX * 400), $pk->eid = $this->eid;
"speedY" => (int) ($this->speedY * 400), $pk->speedX = $this->speedX;
"speedZ" => (int) ($this->speedZ * 400), $pk->speedY = $this->speedY;
)); $pk->speedZ = $this->speedZ;
$player->dataPacket($pk);
} }
break; break;
case ENTITY_FALLING: case ENTITY_FALLING:
$player->dataPacket(MC_ADD_ENTITY, array( $pk = new AddEntityPacket;
"eid" => $this->eid, $pk->eid = $this->eid;
"type" => $this->type, $pk->type = $this->type;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"did" => -$this->data["Tile"], $pk->did = -$this->data["Tile"];
)); $player->dataPacket($pk);
$player->dataPacket(MC_SET_ENTITY_MOTION, array(
"eid" => $this->eid, $pk = new SetEntityMotionPacket;
"speedX" => (int) ($this->speedX * 400), $pk->eid = $this->eid;
"speedY" => (int) ($this->speedY * 400), $pk->speedX = $this->speedX;
"speedZ" => (int) ($this->speedZ * 400), $pk->speedY = $this->speedY;
)); $pk->speedZ = $this->speedZ;
$player->dataPacket($pk);
break; break;
} }
} }
@ -828,7 +847,7 @@ class Entity extends Position{
$this->server->preparedSQL->entity->setLevel->reset(); $this->server->preparedSQL->entity->setLevel->reset();
$this->server->preparedSQL->entity->setLevel->clear(); $this->server->preparedSQL->entity->setLevel->clear();
$this->server->preparedSQL->entity->setLevel->bindValue(":level", $this->level->getName(), SQLITE3_TEXT); $this->server->preparedSQL->entity->setLevel->bindValue(":level", $this->level->getName(), SQLITE3_TEXT);
$this->server->preparedSQL->entity->setLevel->bindValue(":eid", $this->eid, SQLITE3_TEXT); $this->server->preparedSQL->entity->setLevel->bindValue(":eid", $this->eid, SQLITE3_INTEGER);
$this->server->preparedSQL->entity->setLevel->execute(); $this->server->preparedSQL->entity->setLevel->execute();
} }
$this->x = $pos->x; $this->x = $pos->x;
@ -847,7 +866,7 @@ class Entity extends Position{
$this->server->preparedSQL->entity->setPosition->bindValue(":z", $this->z, SQLITE3_TEXT); $this->server->preparedSQL->entity->setPosition->bindValue(":z", $this->z, SQLITE3_TEXT);
$this->server->preparedSQL->entity->setPosition->bindValue(":pitch", $this->pitch, SQLITE3_TEXT); $this->server->preparedSQL->entity->setPosition->bindValue(":pitch", $this->pitch, SQLITE3_TEXT);
$this->server->preparedSQL->entity->setPosition->bindValue(":yaw", $this->yaw, SQLITE3_TEXT); $this->server->preparedSQL->entity->setPosition->bindValue(":yaw", $this->yaw, SQLITE3_TEXT);
$this->server->preparedSQL->entity->setPosition->bindValue(":eid", $this->eid, SQLITE3_TEXT); $this->server->preparedSQL->entity->setPosition->bindValue(":eid", $this->eid, SQLITE3_INTEGER);
$this->server->preparedSQL->entity->setPosition->execute(); $this->server->preparedSQL->entity->setPosition->execute();
} }
@ -981,9 +1000,9 @@ class Entity extends Position{
$this->server->api->dhandle("entity.event", array("entity" => $this, "event" => 2)); //Ouch! sound $this->server->api->dhandle("entity.event", array("entity" => $this, "event" => 2)); //Ouch! sound
} }
if($this->player instanceof Player){ if($this->player instanceof Player){
$this->player->dataPacket(MC_SET_HEALTH, array( $pk = new SetHealthPacket;
"health" => $this->health, $pk->health = $this->health;
)); $this->player->dataPacket($pk);
} }
if($this->health <= 0 and $this->dead === false){ if($this->health <= 0 and $this->dead === false){
$this->spawnDrops(); $this->spawnDrops();
@ -995,14 +1014,14 @@ class Entity extends Position{
$this->updateMetadata(); $this->updateMetadata();
$this->dead = true; $this->dead = true;
if($this->player instanceof Player){ if($this->player instanceof Player){
$this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), MC_MOVE_ENTITY_POSROT, array( $pk = new MoveEntityPacket_PosRot;
"eid" => $this->eid, $pk->eid = $this->eid;
"x" => -256, $pk->x = -256;
"y" => 128, $pk->y = 128;
"z" => -256, $pk->z = -256;
"yaw" => 0, $pk->yaw = 0;
"pitch" => 0, $pk->pitch = 0;
)); $this->server->api->player->broadcastPacket($this->level->players, $pk);
}else{ }else{
$this->server->api->dhandle("entity.event", array("entity" => $this, "event" => 3)); //Entity dead $this->server->api->dhandle("entity.event", array("entity" => $this, "event" => 3)); //Entity dead
} }

View File

@ -114,13 +114,13 @@ class Explosion{
$this->level->level->setBlockID($block->x, $block->y, $block->z, 0); $this->level->level->setBlockID($block->x, $block->y, $block->z, 0);
$send[] = new Vector3($block->x - $source->x, $block->y - $source->y, $block->z - $source->z); $send[] = new Vector3($block->x - $source->x, $block->y - $source->y, $block->z - $source->z);
} }
$server->api->player->broadcastPacket($server->api->player->getAll($this->level), MC_EXPLOSION, array( $pk = new ExplodePacket;
"x" => $this->source->x, $pk->x = $this->source->x;
"y" => $this->source->y, $pk->y = $this->source->y;
"z" => $this->source->z, $pk->z = $this->source->z;
"radius" => $this->size, $pk->radius = $this->size;
"records" => $send, $pk->records = $send;
)); $server->api->player->broadcastPacket($this->level->players, $pk);
} }
} }

View File

@ -78,10 +78,11 @@ class Level{
} }
if($this->server->api->dhandle("time.change", array("level" => $this, "time" => $time)) !== false){ if($this->server->api->dhandle("time.change", array("level" => $this, "time" => $time)) !== false){
$this->time = $time; $this->time = $time;
$this->server->api->player->broadcastPacket($this->players, MC_SET_TIME, array(
"time" => (int) $this->time, $pk = new SetTimePacket;
"started" => $this->stopTime == false, $pk->time = (int) $this->time;
)); $pk->started = $this->stopTime == false;
$this->server->api->player->broadcastPacket($this->players, $pk);
} }
} }
@ -109,13 +110,13 @@ class Level{
if(count($this->changedBlocks) > 0){ if(count($this->changedBlocks) > 0){
foreach($this->changedBlocks as $blocks){ foreach($this->changedBlocks as $blocks){
foreach($blocks as $b){ foreach($blocks as $b){
$this->server->api->player->broadcastPacket($this->players, MC_UPDATE_BLOCK, array( $pk = new UpdateBlockPacket;
"x" => $b->x, $pk->x = $b->x;
"y" => $b->y, $pk->y = $b->y;
"z" => $b->z, $pk->z = $b->z;
"block" => $b->getID(), $pk->block = $b->getID();
"meta" => $b->getMetadata(), $pk->meta = $b->getMetadata();
)); $this->server->api->player->broadcastPacket($this->players, $pk);
} }
} }
$this->changedBlocks = array(); $this->changedBlocks = array();
@ -286,13 +287,13 @@ class Level{
public function setBlockRaw(Vector3 $pos, Block $block, $direct = true, $send = true){ public function setBlockRaw(Vector3 $pos, Block $block, $direct = true, $send = true){
if(($ret = $this->level->setBlock($pos->x, $pos->y, $pos->z, $block->getID(), $block->getMetadata())) === true and $send !== false){ if(($ret = $this->level->setBlock($pos->x, $pos->y, $pos->z, $block->getID(), $block->getMetadata())) === true and $send !== false){
if($direct === true){ if($direct === true){
$this->server->api->player->broadcastPacket($this->players, MC_UPDATE_BLOCK, array( $pk = new UpdateBlockPacket;
"x" => $pos->x, $pk->x = $pos->x;
"y" => $pos->y, $pk->y = $pos->y;
"z" => $pos->z, $pk->z = $pos->z;
"block" => $block->getID(), $pk->block = $block->getID();
"meta" => $block->getMetadata(), $pk->meta = $block->getMetadata();
)); $this->server->api->player->broadcastPacket($this->players, $pk);
}elseif($direct === false){ }elseif($direct === false){
if(!($pos instanceof Position)){ if(!($pos instanceof Position)){
$pos = new Position($pos->x, $pos->y, $pos->z, $this); $pos = new Position($pos->x, $pos->y, $pos->z, $this);
@ -326,13 +327,13 @@ class Level{
$block->position($pos); $block->position($pos);
if($direct === true){ if($direct === true){
$this->server->api->player->broadcastPacket($this->players, MC_UPDATE_BLOCK, array( $pk = new UpdateBlockPacket;
"x" => $pos->x, $pk->x = $pos->x;
"y" => $pos->y, $pk->y = $pos->y;
"z" => $pos->z, $pk->z = $pos->z;
"block" => $block->getID(), $pk->block = $block->getID();
"meta" => $block->getMetadata(), $pk->meta = $block->getMetadata();
)); $this->server->api->player->broadcastPacket($this->players, $pk);
}else{ }else{
$i = ($pos->x >> 4).":".($pos->y >> 4).":".($pos->z >> 4); $i = ($pos->x >> 4).":".($pos->y >> 4).":".($pos->z >> 4);
if(!isset($this->changedBlocks[$i])){ if(!isset($this->changedBlocks[$i])){

View File

@ -142,26 +142,27 @@ class Tile extends Position{
}else{ }else{
$player->windows[$id] = $this; $player->windows[$id] = $this;
} }
$player->dataPacket(MC_CONTAINER_OPEN, array(
"windowid" => $id, $pk = new ContainerOpenPacket;
"type" => WINDOW_CHEST, $pk->windowid = $id;
"slots" => is_array($player->windows[$id]) ? CHEST_SLOTS << 1:CHEST_SLOTS, $pk->type = WINDOW_CHEST;
"x" => $this->x, $pk->slots = is_array($player->windows[$id]) ? CHEST_SLOTS << 1:CHEST_SLOTS;
"y" => $this->y, $pk->x = $this->x;
"z" => $this->z, $pk->y = $this->y;
)); $pk->z = $this->z;
$player->dataPacket($pk);
$slots = array(); $slots = array();
if(is_array($player->windows[$id])){ if(is_array($player->windows[$id])){
$all = $this->server->api->player->getAll($this->level); $all = $this->server->api->player->getAll($this->level);
foreach($player->windows[$id] as $ob){ foreach($player->windows[$id] as $ob){
$this->server->api->player->broadcastPacket($all, MC_TILE_EVENT, array( $pk = new TileEventPacket;
"x" => $ob->x, $pk->x = $ob->x;
"y" => $ob->y, $pk->y = $ob->y;
"z" => $ob->z, $pk->z = $ob->z;
"case1" => 1, $pk->case1 = 1;
"case2" => 2, $pk->case2 = 2;
)); $this->server->api->player->broadcastPacket($all, $pk);
for($s = 0; $s < CHEST_SLOTS; ++$s){ for($s = 0; $s < CHEST_SLOTS; ++$s){
$slot = $ob->getSlot($s); $slot = $ob->getSlot($s);
if($slot->getID() > AIR and $slot->count > 0){ if($slot->getID() > AIR and $slot->count > 0){
@ -172,13 +173,13 @@ class Tile extends Position{
} }
} }
}else{ }else{
$this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), MC_TILE_EVENT, array( $pk = new TileEventPacket;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"case1" => 1, $pk->case1 = 1;
"case2" => 2, $pk->case2 = 2;
)); $this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), $pk);
for($s = 0; $s < CHEST_SLOTS; ++$s){ for($s = 0; $s < CHEST_SLOTS; ++$s){
$slot = $this->getSlot($s); $slot = $this->getSlot($s);
if($slot->getID() > AIR and $slot->count > 0){ if($slot->getID() > AIR and $slot->count > 0){
@ -188,24 +189,26 @@ class Tile extends Position{
} }
} }
} }
$player->dataPacket(MC_CONTAINER_SET_CONTENT, array(
"windowid" => $id, $pk = new ContainerSetContentPacket;
"count" => count($slots), $pk->windowid = $id;
"slots" => $slots, $pk->slots = $slots;
)); $player->dataPacket($pk);
return true; return true;
}elseif($this->class === TILE_FURNACE){ }elseif($this->class === TILE_FURNACE){
$player->windowCnt++; $player->windowCnt++;
$player->windowCnt = $id = max(2, $player->windowCnt % 99); $player->windowCnt = $id = max(2, $player->windowCnt % 99);
$player->windows[$id] = $this; $player->windows[$id] = $this;
$player->dataPacket(MC_CONTAINER_OPEN, array(
"windowid" => $id, $pk = new ContainerOpenPacket;
"type" => WINDOW_FURNACE, $pk->windowid = $id;
"slots" => FURNACE_SLOTS, $pk->type = WINDOW_FURNACE;
"x" => $this->x, $pk->slots = FURNACE_SLOTS;
"y" => $this->y, $pk->x = $this->x;
"z" => $this->z $pk->y = $this->y;
)); $pk->z = $this->z;
$player->dataPacket($pk);
$slots = array(); $slots = array();
for($s = 0; $s < FURNACE_SLOTS; ++$s){ for($s = 0; $s < FURNACE_SLOTS; ++$s){
$slot = $this->getSlot($s); $slot = $this->getSlot($s);
@ -215,11 +218,10 @@ class Tile extends Position{
$slots[] = BlockAPI::getItem(AIR, 0, 0); $slots[] = BlockAPI::getItem(AIR, 0, 0);
} }
} }
$player->dataPacket(MC_CONTAINER_SET_CONTENT, array( $pk = new ContainerSetContentPacket;
"windowid" => $id, $pk->windowid = $id;
"count" => count($slots), $pk->slots = $slots;
"slots" => $slots $player->dataPacket($pk);
));
return true; return true;
} }
} }
@ -383,12 +385,12 @@ class Tile extends Position{
$nbt->write(chr(NBT::TAG_END)); $nbt->write(chr(NBT::TAG_END));
$player->dataPacket(MC_ENTITY_DATA, array( $pk = new EntityDataPacket;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"namedtag" => $nbt->binary, $pk->namedtag = $nbt->binary;
)); $player->dataPacket($pk);
break; break;
case TILE_SIGN: case TILE_SIGN:
$nbt = new NBT(); $nbt = new NBT();
@ -428,12 +430,12 @@ class Tile extends Position{
$nbt->write(chr(NBT::TAG_END)); $nbt->write(chr(NBT::TAG_END));
$player->dataPacket(MC_ENTITY_DATA, array( $pk = new EntityDataPacket;
"x" => $this->x, $pk->x = $this->x;
"y" => $this->y, $pk->y = $this->y;
"z" => $this->z, $pk->z = $this->z;
"namedtag" => $nbt->binary, $pk->namedtag = $nbt->binary;
)); $player->dataPacket($pk);
break; break;
} }
} }