mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-05 19:37:17 +00:00
Map saving, breaking blocks. Huge rewrite
This commit is contained in:
parent
72c4cc7a30
commit
3a2010696f
3
TODO
Normal file
3
TODO
Normal file
@ -0,0 +1,3 @@
|
||||
- Save broken/placed blocks and relay them to other players.
|
||||
- Fix spawn position resetting to 0,128,0
|
||||
- Mob spawning, item drop and pick up
|
@ -31,11 +31,14 @@ class ConsoleAPI{
|
||||
$this->help = array();
|
||||
$this->server = $server;
|
||||
$this->input = fopen(FILE_PATH."console.in", "w+b");
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->event = $this->server->event("onTick", array($this, "handle"));
|
||||
}
|
||||
|
||||
function __destroy(){
|
||||
$this->server->deleteEvent("onTick", $this->event);
|
||||
$this->server->deleteEvent($this->event);
|
||||
fclose($this->input);
|
||||
}
|
||||
|
||||
|
94
classes/API/EntityAPI.php
Normal file
94
classes/API/EntityAPI.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class EntityAPI{
|
||||
private $server;
|
||||
function __construct($server){
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
$this->server->api->console->register("give", "Give items to a player", array($this, "commandHandler"));
|
||||
}
|
||||
|
||||
public function commandHandler($cmd, $params){
|
||||
switch($cmd){
|
||||
case "give":
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function get($eid){
|
||||
if(isset($this->server->entities[$eid])){
|
||||
return $this->server->entities[$eid];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getAll(){
|
||||
return $this->server->entities;
|
||||
}
|
||||
|
||||
public function add($class, $type = 0, $data = array()){
|
||||
$eid = $this->server->eidCnt++;
|
||||
$this->server->entities[$eid] = new Entity($this->server, $eid, $class, $type, $data);
|
||||
return $this->server->entities[$eid];
|
||||
}
|
||||
|
||||
public function spawnTo($eid, $player){
|
||||
$e = $this->get($eid);
|
||||
if($e === false){
|
||||
return false;
|
||||
}
|
||||
$e->spawn($player);
|
||||
}
|
||||
|
||||
public function spawnToAll($eid){
|
||||
$e = $this->get($eid);
|
||||
if($e === false){
|
||||
return false;
|
||||
}
|
||||
foreach($this->server->api->player->getAll() as $player){
|
||||
if($player->eid !== false){
|
||||
$e->spawn($player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function spawnAll($player){
|
||||
foreach($this->getAll() as $e){
|
||||
$e->spawn($player);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove($eid){
|
||||
if(isset($this->server->entities[$eid])){
|
||||
$this->server->entities[$eid]->close();
|
||||
unset($this->server->entities[$eid]);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,6 +35,32 @@ class LevelAPI{
|
||||
}
|
||||
}
|
||||
|
||||
public function init(){
|
||||
//$this->server->event("onBlockBreak", array($this, "handle"));
|
||||
}
|
||||
|
||||
public function handle($data, $event){
|
||||
switch($event){
|
||||
case "onBlockBreak":
|
||||
$block = $this->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
console("[DEBUG] EID ".$data["eid"]." broke block ".$block[0].":".$block[1]." at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
|
||||
|
||||
if($block[0] === 0){
|
||||
break;
|
||||
}
|
||||
$this->setBlock($data["x"], $data["y"], $data["z"], 0, 0);
|
||||
$data["block"] = $block[0];
|
||||
$data["meta"] = $block[1];
|
||||
$data["stack"] = 1;
|
||||
$data["x"] += mt_rand(2, 8) / 10;
|
||||
$data["y"] += mt_rand(2, 8) / 10;
|
||||
$data["z"] += mt_rand(2, 8) / 10;
|
||||
$e = $this->server->api->entity->add(ENTITY_ITEM, $block[0], $data);
|
||||
$this->server->api->entity->spawnToAll($e->eid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function check(){
|
||||
if($this->active === false and $this->server->map === false){
|
||||
return false;
|
||||
@ -57,6 +83,19 @@ class LevelAPI{
|
||||
return array(0,0);
|
||||
}
|
||||
|
||||
public function setBlock($x, $y, $z, $block, $meta = 0){
|
||||
if($this->check()){
|
||||
$this->map->setBlock($x, $y, $z, $block, $meta);
|
||||
}
|
||||
$this->server->trigger("onBlockUpdate", array(
|
||||
"x" => $x,
|
||||
"y" => $y,
|
||||
"z" => $z,
|
||||
"block" => $block,
|
||||
"meta" => $meta,
|
||||
));
|
||||
}
|
||||
|
||||
public function getOrderedChunk($X, $Z, $columnsPerPacket = 2){
|
||||
$columnsPerPacket = max(1, (int) $columnsPerPacket);
|
||||
$c = $this->getChunk($X, $Z);
|
||||
|
@ -73,7 +73,7 @@ class PlayerAPI{
|
||||
case "list":
|
||||
console("[INFO] Player list:");
|
||||
foreach($this->server->clients as $c){
|
||||
console("[INFO] ".$c->username." (".$c->ip.":".$c->port."), ClientID ".$c->clientID.", (".round($c->username->entity->position["x"], 2).", ".round($c->username->entity->position["y"], 2).", ".round($c->username->entity->position["z"], 2).")");
|
||||
console("[INFO] ".$c->username." (".$c->ip.":".$c->port."), ClientID ".$c->clientID.", (".round($c->username->entity->x, 2).", ".round($c->username->entity->y, 2).", ".round($c->username->entity->z, 2).")");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -82,7 +82,7 @@ class PlayerAPI{
|
||||
public function teleport($name, $target){
|
||||
$target = $this->get($target);
|
||||
if($target !== false){
|
||||
$this->tppos($name, $target->entity->position["x"], $target->entity->position["y"], $target->entity->position["z"]);
|
||||
$this->tppos($name, $target->entity->x, $target->entity->y, $target->entity->z);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,6 +102,10 @@ class PlayerAPI{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getAll(){
|
||||
return $this->server->clients;
|
||||
}
|
||||
|
||||
public function getByEID($eid){
|
||||
$eid = (int) $eid;
|
||||
$CID = $this->server->query("SELECT ip,port FROM players WHERE EID = '".$eid."';", true);
|
||||
@ -112,6 +116,16 @@ class PlayerAPI{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getByClientID($clientID){
|
||||
$clientID = (int) $clientID;
|
||||
$CID = $this->server->query("SELECT ip,port FROM players WHERE clientID = '".$clientID."';", true);
|
||||
$CID = $this->server->clientID($CID["ip"], $CID["port"]);
|
||||
if(isset($this->server->clients[$CID])){
|
||||
return $this->server->clients[$CID];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function online(){
|
||||
$o = array();
|
||||
foreach($this->server->clients as $p){
|
||||
@ -127,7 +141,7 @@ class PlayerAPI{
|
||||
$player = $this->server->clients[$CID];
|
||||
console("[INFO] Player \"".$player->username."\" connected from ".$player->ip.":".$player->port);
|
||||
$player->data = $this->getOffline($player->username);
|
||||
$this->server->query("INSERT OR REPLACE INTO players (clientID, EID, ip, port, name) VALUES (".$player->clientID.", ".$player->eid.", '".$player->ip."', ".$player->port.", '".$player->username."');");
|
||||
$this->server->query("INSERT OR REPLACE INTO players (clientID, ip, port, name) VALUES (".$player->clientID.", '".$player->ip."', ".$player->port.", '".$player->username."');");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,8 @@ class ServerAPI extends stdClass{ //Yay! I can add anything to this class in run
|
||||
$this->$a->init();
|
||||
}
|
||||
}
|
||||
|
||||
$this->server->loadEntities();
|
||||
}
|
||||
|
||||
public function getList(){
|
||||
|
@ -26,7 +26,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
class ChunkParser{
|
||||
private $location, $raw = b"";
|
||||
private $location, $raw = b"", $file;
|
||||
var $sectorLenght = 4096; //16 * 16 * 16
|
||||
var $chunkLenght = 86016; //21 * $sectorLenght
|
||||
var $map;
|
||||
@ -62,6 +62,7 @@ class ChunkParser{
|
||||
if(!file_exists($file)){
|
||||
return false;
|
||||
}
|
||||
$this->file = $file;
|
||||
$this->raw = file_get_contents($file);
|
||||
$this->chunkLenght = $this->sectorLenght * ord($this->raw{0});
|
||||
return true;
|
||||
@ -78,15 +79,25 @@ class ChunkParser{
|
||||
return 0x1000 + (($Z * $sectors) << 12) + (($X * $sectors) << 16);
|
||||
}
|
||||
|
||||
public function getChunk($X, $Z, $header = true){
|
||||
public function getChunk($X, $Z){
|
||||
$X = (int) $X;
|
||||
$Z = (int) $Z;
|
||||
if($header === false){
|
||||
$add = 4;
|
||||
}else{
|
||||
$add = 0;
|
||||
return substr($this->raw, $this->getOffset($X, $Z), $this->chunkLenght);
|
||||
}
|
||||
|
||||
public function writeChunk($X, $Z){
|
||||
$X = (int) $X;
|
||||
$Z = (int) $Z;
|
||||
if(!isset($this->map[$X][$Z])){
|
||||
return false;
|
||||
}
|
||||
return substr($this->raw, $this->getOffset($X, $Z) + $add, $this->chunkLenght - $add);
|
||||
$chunk = "";
|
||||
foreach($this->map[$X][$Z] as $section => $data){
|
||||
foreach($data as $r){
|
||||
$chunk .= $r;
|
||||
}
|
||||
}
|
||||
return Utils::writeLInt(strlen($chunk)).$chunk;
|
||||
}
|
||||
|
||||
public function parseChunk($X, $Z){
|
||||
@ -154,6 +165,20 @@ class ChunkParser{
|
||||
console("[DEBUG] Chunks loaded!", true, true, 2);
|
||||
}
|
||||
|
||||
public function saveMap(){
|
||||
console("[DEBUG] Saving chunks...", true, true, 2);
|
||||
$fp = fopen($this->file, "r+b");
|
||||
flock($fp, LOCK_EX);
|
||||
foreach($this->map as $x => $d){
|
||||
foreach($d as $z => $chunk){
|
||||
fseek($fp, $this->getOffset($x, $z));
|
||||
fwrite($fp, $this->writeChunk($x, $z), $this->chunkLenght);
|
||||
}
|
||||
}
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
public function getBlock($x, $y, $z){
|
||||
$x = (int) $x;
|
||||
$y = (int) $y;
|
||||
@ -164,8 +189,32 @@ class ChunkParser{
|
||||
$aZ = $z - ($Z << 4);
|
||||
$index = $aX + ($aZ << 4);
|
||||
$block = ord($this->map[$X][$Z][0][$index]{$y});
|
||||
//$meta = $this->getOffset($X, $Z) + 4 + (($x << 6) + $y + ($z << 10));
|
||||
return array($block, 0);
|
||||
$meta = ord($this->map[$X][$Z][1][$index]{$y >> 1});
|
||||
if(($y & 1) === 0){
|
||||
$meta = $meta & 0x0F;
|
||||
}else{
|
||||
$meta = $meta >> 4;
|
||||
}
|
||||
return array($block, $meta);
|
||||
}
|
||||
|
||||
public function setBlock($x, $y, $z, $block, $meta = 0){
|
||||
$x = (int) $x;
|
||||
$y = (int) $y;
|
||||
$z = (int) $z;
|
||||
$X = $x >> 4;
|
||||
$Z = $z >> 4;
|
||||
$aX = $x - ($X << 4);
|
||||
$aZ = $z - ($Z << 4);
|
||||
$index = $aX + ($aZ << 4);
|
||||
$this->map[$X][$Z][0][$index]{$y} = chr($block);
|
||||
$old_meta = ord($this->map[$X][$Z][1][$index]{$y >> 1});
|
||||
if(($y & 1) === 0){
|
||||
$meta = ($old_meta & 0xF0) | ($meta & 0x0F);
|
||||
}else{
|
||||
$meta = (($meta << 4) & 0xF0) | ($old_meta & 0x0F);
|
||||
}
|
||||
$this->map[$X][$Z][1][$index]{$y >> 1} = chr($meta);
|
||||
}
|
||||
|
||||
}
|
@ -186,7 +186,7 @@ class CustomPacketHandler{
|
||||
break;
|
||||
case MC_ADD_MOB:
|
||||
if($this->c === false){
|
||||
$this->data["int"] = Utils::readInt($this->get(4));
|
||||
$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));
|
||||
|
@ -32,17 +32,17 @@ define("ENTITY_OBJECT", 2);
|
||||
define("ENTITY_ITEM", 3);
|
||||
define("ENTITY_PAINTING", 4);
|
||||
|
||||
class Entity{
|
||||
var $eid, $type, $name, $position, $dead, $metadata, $class, $attach, $data, $closed;
|
||||
protected $health, $client;
|
||||
class Entity extends stdClass{
|
||||
var $eid, $type, $name, $x, $y, $z, $yaw, $pitch, $dead, $data, $class, $attach, $metadata, $closed, $player;
|
||||
|
||||
function __construct($eid, $class, $type = 0, $server){ //$type = 0 ---> player
|
||||
function __construct($server, $eid, $class, $type = 0, $data = array()){
|
||||
$this->server = $server;
|
||||
$this->eid = (int) $eid;
|
||||
$this->type = (int) $type;
|
||||
$this->class = (int) $class;
|
||||
$this->player = false;
|
||||
$this->attach = false;
|
||||
$this->data = array();
|
||||
$this->data = $data;
|
||||
$this->status = 0;
|
||||
$this->health = 20;
|
||||
$this->dead = false;
|
||||
@ -50,19 +50,72 @@ class Entity{
|
||||
$this->name = "";
|
||||
$this->server->query("INSERT OR REPLACE INTO entities (EID, type, class, health) VALUES (".$this->eid.", ".$this->type.", ".$this->class.", ".$this->health.");");
|
||||
$this->metadata = array();
|
||||
/*include("misc/entities.php");
|
||||
$this->x = isset($this->data["x"]) ? $this->data["x"]:0;
|
||||
$this->y = isset($this->data["y"]) ? $this->data["y"]:0;
|
||||
$this->z = isset($this->data["z"]) ? $this->data["z"]:0;
|
||||
$this->yaw = isset($this->data["yaw"]) ? $this->data["yaw"]:0;
|
||||
$this->pitch = isset($this->data["pitch"]) ? $this->data["pitch"]:0;
|
||||
$this->position = array("x" => &$this->x, "y" => &$this->y, "z" => &$this->z, "yaw" => &$this->yaw, "pitch" => &$this->pitch);
|
||||
switch($this->class){
|
||||
case ENTITY_PLAYER:
|
||||
case ENTITY_ITEM:
|
||||
$this->player = $this->data["player"];
|
||||
$this->health = &$this->player->data["health"];
|
||||
break;
|
||||
case ENTITY_ITEM:
|
||||
$this->meta = (int) $this->data["meta"];
|
||||
$this->stack = (int) $this->data["stack"];
|
||||
break;
|
||||
|
||||
case ENTITY_MOB:
|
||||
$this->setName((isset($mobs[$this->type]) ? $mobs[$this->type]:$this->type));
|
||||
//$this->setName((isset($mobs[$this->type]) ? $mobs[$this->type]:$this->type));
|
||||
break;
|
||||
case ENTITY_OBJECT:
|
||||
$this->setName((isset($objects[$this->type]) ? $objects[$this->type]:$this->type));
|
||||
//$this->setName((isset($objects[$this->type]) ? $objects[$this->type]:$this->type));
|
||||
break;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
public function spawn($player){
|
||||
if(!is_object($player)){
|
||||
$player = $this->server->api->player->get($player);
|
||||
}
|
||||
if($player->eid === $this->eid){
|
||||
return false;
|
||||
}
|
||||
switch($this->class){
|
||||
case ENTITY_PLAYER:
|
||||
$player->dataPacket(MC_ADD_PLAYER, array(
|
||||
"clientID" => $this->player->clientID,
|
||||
"username" => $this->player->username,
|
||||
"eid" => $this->eid,
|
||||
"x" => $this->x,
|
||||
"y" => $this->y,
|
||||
"z" => $this->z,
|
||||
));
|
||||
break;
|
||||
case ENTITY_ITEM:
|
||||
$player->dataPacket(MC_ADD_ITEM_ENTITY, array(
|
||||
"eid" => $this->eid,
|
||||
"x" => $this->x,
|
||||
"y" => $this->y,
|
||||
"z" => $this->z,
|
||||
"block" => $this->type,
|
||||
"meta" => $this->meta,
|
||||
"stack" => $this->stack,
|
||||
));
|
||||
break;
|
||||
case ENTITY_MOB:
|
||||
$player->dataPacket(MC_ADD_MOB, array(
|
||||
"type" => $this->type,
|
||||
"eid" => $this->eid,
|
||||
"x" => $this->x,
|
||||
"y" => $this->y,
|
||||
"z" => $this->z,
|
||||
));
|
||||
break;
|
||||
case ENTITY_OBJECT:
|
||||
//$this->setName((isset($objects[$this->type]) ? $objects[$this->type]:$this->type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function close(){
|
||||
@ -93,59 +146,36 @@ class Entity{
|
||||
public function look($pos2){
|
||||
$pos = $this->getPosition();
|
||||
$angle = Utils::angle3D($pos2, $pos);
|
||||
$this->position["yaw"] = $angle["yaw"];
|
||||
$this->position["pitch"] = $angle["pitch"];
|
||||
$this->server->query("UPDATE entities SET pitch = ".$this->position["pitch"].", yaw = ".$this->position["yaw"]." WHERE EID = ".$this->eid.";");
|
||||
$this->yaw = $angle["yaw"];
|
||||
$this->pitch = $angle["pitch"];
|
||||
$this->server->query("UPDATE entities SET pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
public function setCoords($x, $y, $z){
|
||||
if(!isset($this->position)){
|
||||
$this->position = array(
|
||||
"x" => 0,
|
||||
"y" => 0,
|
||||
"z" => 0,
|
||||
"yaw" => 0,
|
||||
"pitch" => 0,
|
||||
"ground" => 0,
|
||||
);
|
||||
}
|
||||
$this->position["x"] = $x;
|
||||
$this->position["y"] = $y;
|
||||
$this->position["z"] = $z;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->position["x"].", y = ".$this->position["y"].", z = ".$this->position["z"]." WHERE EID = ".$this->eid.";");
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
public function move($x, $y, $z, $yaw = 0, $pitch = 0){
|
||||
if(!isset($this->position)){
|
||||
$this->position = array(
|
||||
"x" => 0,
|
||||
"y" => 0,
|
||||
"z" => 0,
|
||||
"yaw" => 0,
|
||||
"pitch" => 0,
|
||||
"ground" => 0,
|
||||
);
|
||||
}
|
||||
$this->position["x"] += $x;
|
||||
$this->position["y"] += $y;
|
||||
$this->position["z"] += $z;
|
||||
$this->position["yaw"] += $yaw;
|
||||
$this->position["yaw"] %= 360;
|
||||
$this->position["pitch"] += $pitch;
|
||||
$this->position["pitch"] %= 90;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->position["x"].", y = ".$this->position["y"].", z = ".$this->position["z"].", pitch = ".$this->position["pitch"].", yaw = ".$this->position["yaw"]." WHERE EID = ".$this->eid.";");
|
||||
$this->x += $x;
|
||||
$this->y += $y;
|
||||
$this->z += $z;
|
||||
$this->yaw += $yaw;
|
||||
$this->yaw %= 360;
|
||||
$this->pitch += $pitch;
|
||||
$this->pitch %= 90;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||
}
|
||||
|
||||
public function setPosition($x, $y, $z, $yaw, $pitch){
|
||||
$this->position = array(
|
||||
"x" => $x,
|
||||
"y" => $y,
|
||||
"z" => $z,
|
||||
"yaw" => $yaw,
|
||||
"pitch" => $pitch,
|
||||
"ground" => $ground,
|
||||
);
|
||||
$this->server->query("UPDATE entities SET x = ".$this->position["x"].", y = ".$this->position["y"].", z = ".$this->position["z"].", pitch = ".$this->position["pitch"].", yaw = ".$this->position["yaw"]." WHERE EID = ".$this->eid.";");
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
$this->yaw = $yaw;
|
||||
$this->pitch = $pitch;
|
||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,8 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
*/
|
||||
|
||||
class MinecraftInterface{
|
||||
var $pstruct, $name, $protocol, $client, $buffer, $dataName;
|
||||
private $socket;
|
||||
var $pstruct, $name, $protocol, $client, $dataName;
|
||||
private $socket, $data;
|
||||
function __construct($server, $protocol = CURRENT_PROTOCOL, $port = 25565, $listen = false, $client = true){
|
||||
$this->socket = new UDPSocket($server, $port, (bool) $listen);
|
||||
$this->protocol = (int) $protocol;
|
||||
@ -88,8 +88,7 @@ class MinecraftInterface{
|
||||
$p = "[".(microtime(true) - $this->start)."] [".((($origin === "client" and $this->client === true) or ($origin === "server" and $this->client === false)) ? "CLIENT->SERVER":"SERVER->CLIENT")." ".$ip.":".$port."]: Error, bad packet id 0x".Utils::strTohex(chr($pid))." [length ".strlen($raw)."]".PHP_EOL;
|
||||
$p .= Utils::hexdump($data[0]);
|
||||
$p .= PHP_EOL;
|
||||
logg($p, "packets", true, 2);
|
||||
$this->buffer = "";
|
||||
logg($p, "packets", true, 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,242 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class PocketMinecraftClient{
|
||||
protected $interface, $protocol, $entities, $player, $cnt, $events, $username, $version, $clientID, $connected, $serverID, $start;
|
||||
var $serverList = array(), $counter;
|
||||
function __construct($username, $protocol = CURRENT_PROTOCOL, $clientID = false, $version = CURRENT_VERSION){
|
||||
//$this->player = new Player($username);
|
||||
$this->start = microtime(true);
|
||||
$this->version = (int) $version;
|
||||
$this->username = $username;
|
||||
$this->connected = false;
|
||||
$this->cnt = 1;
|
||||
$this->clientID = $clientID === false ? Utils::readLong(Utils::getRandomBytes(8)):$clientID;
|
||||
$this->events = array("disabled" => array());
|
||||
$this->actions = array();
|
||||
$this->interface = new MinecraftInterface("255.255.255.255", $protocol, 19132);
|
||||
console("[INFO] Starting Minecraft Client");
|
||||
console("[INFO] Username: ".$this->username);
|
||||
console("[INFO] Client GUID: ".$this->clientID);
|
||||
$this->event("onReceivedPacket", "packetHandler", true);
|
||||
$this->stop = false;
|
||||
$this->counter = array(0,0);
|
||||
declare(ticks=15);
|
||||
register_tick_function(array($this, "tickerFunction"));
|
||||
}
|
||||
|
||||
public function action($microseconds, $code){
|
||||
$this->actions[] = array($microseconds / 1000000, microtime(true), $code);
|
||||
console("[INTERNAL] Attached to action ".$microseconds, true, true, 3);
|
||||
}
|
||||
|
||||
public function tickerFunction(){
|
||||
//actions that repeat every x time will go here
|
||||
$time = microtime(true);
|
||||
foreach($this->actions as $id => $action){
|
||||
if($action[1] <= ($time - $action[0])){
|
||||
$this->actions[$id][1] = $time;
|
||||
eval($action[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function start($ip){
|
||||
$this->stop = false;
|
||||
$this->action(50000, '$this->trigger("onTick", $time);');
|
||||
$this->interface = new MinecraftInterface($ip, $this->protocol, 19132);
|
||||
console("[INFO] Connecting to Server ".$ip);
|
||||
$this->send(0x05, array(
|
||||
MAGIC,
|
||||
$this->version,
|
||||
str_repeat("\x00", 1447),
|
||||
));
|
||||
$this->process();
|
||||
}
|
||||
|
||||
public function getServerList(){
|
||||
$this->action(1000000, '$this->send(0x02, array(((microtime(true) - $this->start) * 1000)));');
|
||||
$this->action(5000000, '$this->actions = array();$this->stop = true;');
|
||||
$this->process();
|
||||
$list = array();
|
||||
foreach($this->serverList as $ip => $info){
|
||||
$info["ip"] = $ip;
|
||||
$list[] = $info;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function packetHandler($packet, $event){
|
||||
$data =& $packet["data"];
|
||||
switch($packet["pid"]){
|
||||
case 0x1c:
|
||||
$pingID = $data[0];
|
||||
$this->serverID = $data[1];
|
||||
$info = explode(";", $data[3]);
|
||||
$this->serverList[$packet["ip"]] = array("serverID" => $serverID, "username" => array_pop($info));
|
||||
break;
|
||||
case 0x06:
|
||||
$serverID = $data[1];
|
||||
$length = $data[3];
|
||||
$this->send(0x07, array(
|
||||
MAGIC,
|
||||
"\x04\x3f\x57\xfe\xfd",
|
||||
19132,
|
||||
$length,
|
||||
$this->clientID,
|
||||
));
|
||||
break;
|
||||
case 0x08:
|
||||
$serverID = $data[1];
|
||||
$this->send(0x84, array(
|
||||
$this->counter[0],
|
||||
0x00,
|
||||
array(
|
||||
"id" => 0x09,
|
||||
"clientID" => $this->clientID,
|
||||
"session" => Utils::readLong("\x00\x00\x00\x00\x03\x1c\xaf\x05"),
|
||||
),
|
||||
));
|
||||
++$this->counter[0];
|
||||
break;
|
||||
case 0x84:
|
||||
if(isset($data[0])){
|
||||
$this->counter[1] = $data[0];
|
||||
$this->send(0xc0, array(1, true, $data[0]));
|
||||
}
|
||||
switch($data["id"]){
|
||||
case 0x10:
|
||||
$this->send(0x84, array(
|
||||
$this->counter[0],
|
||||
0x00,
|
||||
array(
|
||||
"id" => 0x13,
|
||||
"port" => 19132,
|
||||
"dataArray" => $data["dataArray"],
|
||||
"session" => $data["session"],
|
||||
"session2" => $data["session2"],
|
||||
),
|
||||
));
|
||||
++$this->counter[0];
|
||||
$this->send(0x84, array(
|
||||
$this->counter[0],
|
||||
0x00,
|
||||
array(
|
||||
"id" => 0x00,
|
||||
"payload" => $data["session"],
|
||||
),
|
||||
));
|
||||
++$this->counter[0];
|
||||
$this->send(0x84, array(
|
||||
$this->counter[0],
|
||||
0x00,
|
||||
array(
|
||||
"id" => 0x82,
|
||||
"username" => $this->username,
|
||||
),
|
||||
));
|
||||
++$this->counter[0];
|
||||
/*$this->send(0x84, array(
|
||||
$this->counter[0],
|
||||
0x00,
|
||||
array(
|
||||
"id" => 0xb1,
|
||||
"message" => $this->username,
|
||||
),
|
||||
));
|
||||
++$this->counter[0];*/
|
||||
break;
|
||||
case 0x86:
|
||||
console("[DEBUG] Time: ".$data["time"], true, true, 2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function send($pid, $data = array(), $raw = false, $dest = false, $port = false){
|
||||
$this->trigger($pid, $data);
|
||||
$this->trigger("onSentPacket", $data);
|
||||
$this->interface->writePacket($pid, $data, $raw, $dest, $port);
|
||||
}
|
||||
|
||||
public function process(){
|
||||
while($this->stop === false){
|
||||
$packet = $this->interface->readPacket();
|
||||
if($packet !== false){
|
||||
$this->trigger("onReceivedPacket", $packet);
|
||||
$this->trigger($packet["pid"], $packet);
|
||||
}else{
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function trigger($event, $data = ""){
|
||||
console("[INTERNAL] Event ". $event, true, true, 3);
|
||||
if(isset($this->events[$event]) and !isset($this->events["disabled"][$event])){
|
||||
foreach($this->events[$event] as $eid => $ev){
|
||||
if(isset($ev[1]) and ($ev[1] === true or is_object($ev[1]))){
|
||||
$this->responses[$eid] = call_user_func(array(($ev[1] === true ? $this:$ev[1]), $ev[0]), $data, $event, $this);
|
||||
}else{
|
||||
$this->responses[$eid] = call_user_func($ev[0], $data, $event, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public function toggleEvent($event){
|
||||
if(isset($this->events["disabled"][$event])){
|
||||
unset($this->events["disabled"][$event]);
|
||||
console("[INTERNAL] Enabled event ".$event, true, true, 3);
|
||||
}else{
|
||||
$this->events["disabled"][$event] = false;
|
||||
console("[INTERNAL] Disabled event ".$event, true, true, 3);
|
||||
}
|
||||
}
|
||||
|
||||
public function event($event, $func, $in = false){
|
||||
++$this->cnt;
|
||||
if(!isset($this->events[$event])){
|
||||
$this->events[$event] = array();
|
||||
}
|
||||
$this->events[$event][$this->cnt] = array($func, $in);
|
||||
console("[INTERNAL] Attached to event ".$event, true, true, 3);
|
||||
return $this->cnt;
|
||||
}
|
||||
|
||||
public function deleteEvent($event, $id = -1){
|
||||
if($id === -1){
|
||||
unset($this->events[$event]);
|
||||
}else{
|
||||
unset($this->events[$event][$id]);
|
||||
if(isset($this->events[$event]) and count($this->events[$event]) === 0){
|
||||
unset($this->events[$event]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -31,9 +31,12 @@ class PocketMinecraftServer extends stdClass{
|
||||
var $seed, $protocol, $gamemode, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $timePerSecond, $responses, $spawn, $entities, $mapDir, $mapName, $map, $level, $tileEntities;
|
||||
private $database, $interface, $cnt, $events, $version, $serverType, $lastTick;
|
||||
function __construct($name, $gamemode = 1, $seed = false, $protocol = CURRENT_PROTOCOL, $port = 19132, $serverID = false, $version = CURRENT_VERSION){
|
||||
$this->port = (int) $port;
|
||||
$this->port = (int) $port; //19132 - 19135
|
||||
console("[INFO] Pocket-Minecraft-PHP by @shoghicp, LGPL License. http://bit.ly/RE7uaW", true, true, 0);
|
||||
console("[INFO] Starting Minecraft PE Server at *:".$this->port);
|
||||
if($this->port < 19132 or $this->port > 19135){
|
||||
console("[WARNING] You've selected a not-standard port. Normal port range is from 19132 to 19135 included");
|
||||
}
|
||||
console("[INFO] Loading database...");
|
||||
$this->startDatabase();
|
||||
$this->gamemode = (int) $gamemode;
|
||||
@ -47,7 +50,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->tileEntities = array();
|
||||
$this->entities = array();
|
||||
$this->custom = array();
|
||||
$this->cnt = 1;
|
||||
$this->cnt = 0;
|
||||
$this->eidCnt = 1;
|
||||
$this->maxClients = 20;
|
||||
$this->description = "";
|
||||
@ -61,8 +64,6 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->spawn = array("x" => 128.5,"y" => 100,"z" => 128.5);
|
||||
$this->time = 0;
|
||||
$this->timePerSecond = 10;
|
||||
console("[INFO] Loading events...");
|
||||
$this->loadEvents();
|
||||
$this->setType("normal");
|
||||
$this->interface = new MinecraftInterface("255.255.255.255", $this->protocol, $this->port, true, false);
|
||||
$this->reloadConfig();
|
||||
@ -73,9 +74,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->stop = false;
|
||||
}
|
||||
|
||||
public function loadEvents(){
|
||||
$this->events = array("disabled" => array());
|
||||
|
||||
public function loadEvents(){
|
||||
$this->event("onChat", "eventHandler", true);
|
||||
$this->event("onPlayerDeath", "eventHandler", true);
|
||||
$this->event("onPlayerAdd", "eventHandler", true);
|
||||
@ -85,7 +84,9 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->action(5000000, '$this->trigger("onHealthRegeneration", 1);');
|
||||
$this->action(1000000 * 60, '$this->reloadConfig();');
|
||||
$this->action(1000000 * 60 * 10, '$this->custom = array();');
|
||||
$this->action(1000000 * 80, '$this->chat(false, count($this->clients)."/".$this->maxClients." online: ".implode(", ",$this->api->player->online()));');
|
||||
if($this->api !== false){
|
||||
$this->action(1000000 * 80, '$this->chat(false, count($this->clients)."/".$this->maxClients." online: ".implode(", ",$this->api->player->online()));');
|
||||
}
|
||||
$this->action(1000000 * 75, '$this->debugInfo(true);');
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->query("CREATE TABLE entities (EID INTEGER PRIMARY KEY, type NUMERIC, class NUMERIC, name TEXT, x NUMERIC, y NUMERIC, z NUMERIC, yaw NUMERIC, pitch NUMERIC, health NUMERIC);");
|
||||
$this->query("CREATE TABLE metadata (EID INTEGER PRIMARY KEY, name TEXT, value TEXT);");
|
||||
$this->query("CREATE TABLE actions (ID INTEGER PRIMARY KEY, interval NUMERIC, last NUMERIC, code TEXT, repeat NUMERIC);");
|
||||
$this->query("CREATE TABLE events (ID INTEGER PRIMARY KEY, eventName TEXT, priority NUMERIC, disabled INTEGER);");
|
||||
$this->query("CREATE TABLE events (ID INTEGER PRIMARY KEY, eventName TEXT, priority NUMERIC);");
|
||||
}
|
||||
|
||||
public function query($sql, $fetch = false){
|
||||
@ -216,18 +217,6 @@ class PocketMinecraftServer extends stdClass{
|
||||
}else{
|
||||
$this->map->loadMap();
|
||||
}
|
||||
if($this->map !== false){
|
||||
console("[INFO] Loading entities...");
|
||||
$entities = unserialize(file_get_contents($this->mapDir."entities.dat"));
|
||||
foreach($entities as $entity){
|
||||
$this->entities[$this->eidCnt] = new Entity($this->eidCnt, ENTITY_MOB, $entity["id"], $this);
|
||||
$this->entities[$this->eidCnt]->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
||||
$this->entities[$this->eidCnt]->setHealth($entity["Health"]);
|
||||
++$this->eidCnt;
|
||||
}
|
||||
console("[DEBUG] Loaded ".count($this->entities)." Entities", true, true, 2);
|
||||
$this->action(1000000 * 60 * 15, '$this->chat(false, "Forcing save...");$this->save();$this->chat(false, "Done");');
|
||||
}
|
||||
}else{
|
||||
console("[INFO] Time: ".$this->time);
|
||||
console("[INFO] Seed: ".$this->seed);
|
||||
@ -235,16 +224,47 @@ class PocketMinecraftServer extends stdClass{
|
||||
}
|
||||
}
|
||||
|
||||
public function loadEntities(){
|
||||
if($this->map !== false){
|
||||
console("[INFO] Loading entities...");
|
||||
$entities = unserialize(file_get_contents($this->mapDir."entities.dat"));
|
||||
foreach($entities as $entity){
|
||||
if(!isset($entity["id"])){
|
||||
break;
|
||||
}
|
||||
if(!isset($this->api) or $this->api === false){
|
||||
$this->entities[$this->eidCnt] = new Entity($his, $this->eidCnt, ENTITY_MOB, $entity["id"]);
|
||||
$this->entities[$this->eidCnt]->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
||||
$this->entities[$this->eidCnt]->setHealth($entity["Health"]);
|
||||
++$this->eidCnt;
|
||||
}else{
|
||||
$e = $this->api->entity->add(ENTITY_MOB, $entity["id"]);
|
||||
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
||||
$e->setHealth($entity["Health"]);
|
||||
}
|
||||
}
|
||||
console("[DEBUG] Loaded ".count($this->entities)." Entities", true, true, 2);
|
||||
$this->action(1000000 * 60 * 15, '$this->chat(false, "Forcing save...");$this->save();$this->chat(false, "Done");');
|
||||
}
|
||||
}
|
||||
|
||||
public function save(){
|
||||
if($this->mapName !== false){
|
||||
file_put_contents($this->mapDir."level.dat", serialize($this->level));
|
||||
$this->map->saveMap();
|
||||
}
|
||||
}
|
||||
|
||||
public function start(){
|
||||
if($this->mapName !== false and $this->map === false){
|
||||
$this->loadMap();
|
||||
$this->loadEntities();
|
||||
}
|
||||
console("[INFO] Loading events...");
|
||||
$this->loadEvents();
|
||||
declare(ticks=15);
|
||||
register_tick_function(array($this, "tick"));
|
||||
$this->event("onTick", array($this, "tickerFunction"));
|
||||
$this->event("onTick", "tickerFunction", true);
|
||||
register_shutdown_function(array($this, "close"));
|
||||
console("[INFO] Server started!");
|
||||
$this->process();
|
||||
@ -327,8 +347,7 @@ class PocketMinecraftServer extends stdClass{
|
||||
$port = $data[2];
|
||||
$MTU = $data[3];
|
||||
$clientID = $data[4];
|
||||
$eid = $this->eidCnt++;
|
||||
$this->clients[$CID] = new Session($this, $clientID, $eid, $packet["ip"], $packet["port"], $MTU);
|
||||
$this->clients[$CID] = new Session($this, $clientID, $packet["ip"], $packet["port"], $MTU);
|
||||
$this->clients[$CID]->handle(0x07, $data);
|
||||
break;
|
||||
}
|
||||
@ -351,18 +370,14 @@ class PocketMinecraftServer extends stdClass{
|
||||
}
|
||||
|
||||
public function trigger($event, $data = ""){
|
||||
$events = $this->query("SELECT ID FROM events WHERE eventName = '".$event."' AND disabled = 0;");
|
||||
$events = $this->query("SELECT ID FROM events WHERE eventName = '".$event."';");
|
||||
if($events === false or $events === true){
|
||||
return;
|
||||
}
|
||||
//console("[INTERNAL] Event ". $event, true, true, 3);
|
||||
while($evn = $events->fetchArray(SQLITE3_ASSOC)){
|
||||
$ev = $this->events[$event][$evn["ID"]];
|
||||
if(isset($ev[1]) and ($ev[1] === true or is_object($ev[1]))){
|
||||
$this->responses[$evn["ID"]] = call_user_func(array(($ev[1] === true ? $this:$ev[1]), $ev[0]), $data, $event, $this);
|
||||
}else{
|
||||
$this->responses[$evn["ID"]] = call_user_func($ev[0], $data, $event, $this);
|
||||
}
|
||||
$evid = (int) $evn["ID"];
|
||||
$this->responses[$evid] = call_user_func($this->events[$evid], $data, $event, $this);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -397,42 +412,23 @@ class PocketMinecraftServer extends stdClass{
|
||||
$this->query("UPDATE actions SET last = ".$time." WHERE last <= (".$time." - interval);");
|
||||
}
|
||||
|
||||
public function toggleEvent($event){
|
||||
if(isset($this->events["disabled"][$event])){
|
||||
unset($this->events["disabled"][$event]);
|
||||
$this->query("UPDATE events SET disabled = 0 WHERE eventName = '".$event."';");
|
||||
console("[INTERNAL] Enabled event ".$event, true, true, 3);
|
||||
}else{
|
||||
$this->events["disabled"][$event] = false;
|
||||
$this->query("UPDATE events SET disabled = 1 WHERE eventName = '".$event."';");
|
||||
console("[INTERNAL] Disabled event ".$event, true, true, 3);
|
||||
}
|
||||
}
|
||||
|
||||
public function event($event, $func, $in = false){
|
||||
++$this->cnt;
|
||||
if(!isset($this->events[$event])){
|
||||
$this->events[$event] = array();
|
||||
if($in === true){
|
||||
$func = array($this, $func);
|
||||
}
|
||||
$this->query("INSERT INTO events (ID, eventName, disabled) VALUES (".$this->cnt.", '".str_replace("'", "\\'", $event)."', 0);");
|
||||
$this->events[$event][$this->cnt] = array($func, $in);
|
||||
console("[INTERNAL] Attached to event ".$event, true, true, 3);
|
||||
return $this->cnt;
|
||||
if(!is_callable($func)){
|
||||
return false;
|
||||
}
|
||||
$this->events[$this->cnt] = $func;
|
||||
$this->query("INSERT INTO events (ID, eventName) VALUES (".$this->cnt.", '".str_replace("'", "\\'", $event)."');");
|
||||
console("[INTERNAL] Attached ".(is_array($func) ? get_class($func[0])."::".$func[1]:$func)." to event ".$event." (ID ".$this->cnt.")", true, true, 3);
|
||||
return $this->cnt++;
|
||||
}
|
||||
|
||||
public function deleteEvent($event, $id = -1){
|
||||
public function deleteEvent($id){
|
||||
$id = (int) $id;
|
||||
if($id === -1){
|
||||
unset($this->events[$event]);
|
||||
$this->query("DELETE FROM events WHERE eventName = '".str_replace("'", "\\'", $event)."';");
|
||||
}else{
|
||||
unset($this->events[$event][$id]);
|
||||
$this->query("DELETE FROM events WHERE ID = ".$id.";");
|
||||
if(isset($this->events[$event]) and count($this->events[$event]) === 0){
|
||||
unset($this->events[$event]);
|
||||
$this->query("DELETE FROM events WHERE eventName = '".str_replace("'", "\\'", $event)."';");
|
||||
}
|
||||
}
|
||||
unset($this->events[$id]);
|
||||
$this->query("DELETE FROM events WHERE ID = ".$id.";");
|
||||
}
|
||||
|
||||
}
|
@ -29,22 +29,22 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
class Session{
|
||||
private $server, $timeout, $connected, $evid, $queue, $buffer;
|
||||
var $clientID, $ip, $port, $counter, $username, $eid, $data, $entity, $auth, $CID, $MTU;
|
||||
function __construct($server, $clientID, $eid, $ip, $port, $MTU){
|
||||
function __construct($server, $clientID, $ip, $port, $MTU){
|
||||
$this->queue = array();
|
||||
$this->buffer = array();
|
||||
$this->MTU = $MTU;
|
||||
$this->server = $server;
|
||||
$this->clientID = $clientID;
|
||||
$this->CID = $this->server->clientID($ip, $port);
|
||||
$this->eid = $eid;
|
||||
$this->eid = false;
|
||||
$this->data = array();
|
||||
$this->ip = $ip;
|
||||
$this->entity = false;
|
||||
$this->port = $port;
|
||||
$this->timeout = microtime(true) + 25;
|
||||
$this->evid = array();
|
||||
$this->evid[] = array("onTick", $this->server->event("onTick", array($this, "onTick")));
|
||||
$this->evid[] = array("onClose", $this->server->event("onClose", array($this, "close")));
|
||||
$this->evid[] = $this->server->event("onTick", array($this, "onTick"));
|
||||
$this->evid[] = $this->server->event("onClose", array($this, "close"));
|
||||
console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2);
|
||||
$this->connected = true;
|
||||
$this->auth = false;
|
||||
@ -83,9 +83,9 @@ class Session{
|
||||
public function save(){
|
||||
if(is_object($this->entity)){
|
||||
$this->data["spawn"] = array(
|
||||
"x" => $this->entity->position["x"],
|
||||
"y" => $this->entity->position["y"],
|
||||
"z" => $this->entity->position["z"],
|
||||
"x" => $this->entity->x,
|
||||
"y" => $this->entity->y,
|
||||
"z" => $this->entity->z,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -94,7 +94,7 @@ class Session{
|
||||
$reason = $reason == "" ? "server stop":$reason;
|
||||
$this->save();
|
||||
foreach($this->evid as $ev){
|
||||
$this->server->deleteEvent($ev[0], $ev[1]);
|
||||
$this->server->deleteEvent($ev);
|
||||
}
|
||||
$this->eventHandler("You have been kicked. Reason: ".$reason, "onChat");
|
||||
$this->dataPacket(MC_DISCONNECT);
|
||||
@ -113,6 +113,9 @@ class Session{
|
||||
$this->server->trigger("onPlayerDeath", array("name" => $this->username, "cause" => $data["cause"]));
|
||||
}
|
||||
break;
|
||||
case "onBlockUpdate":
|
||||
$this->dataPacket(MC_UPDATE_BLOCK, $data);
|
||||
break;
|
||||
case "onTeleport":
|
||||
if($data["eid"] !== $this->eid){
|
||||
break;
|
||||
@ -133,11 +136,11 @@ class Session{
|
||||
$entity = $this->server->entities[$data];
|
||||
$this->dataPacket(MC_MOVE_ENTITY_POSROT, array(
|
||||
"eid" => $data,
|
||||
"x" => $entity->position["x"],
|
||||
"y" => $entity->position["y"],
|
||||
"z" => $entity->position["z"],
|
||||
"yaw" => $entity->position["yaw"],
|
||||
"pitch" => $entity->position["pitch"],
|
||||
"x" => $entity->x,
|
||||
"y" => $entity->y,
|
||||
"z" => $entity->z,
|
||||
"yaw" => $entity->yaw,
|
||||
"pitch" => $entity->pitch,
|
||||
));
|
||||
break;
|
||||
case "onHealthRegeneration":
|
||||
@ -151,24 +154,11 @@ class Session{
|
||||
"health" => $data["health"],
|
||||
));
|
||||
$this->data["health"] = $data["health"];
|
||||
if(is_object($this->entity)){
|
||||
/*if(is_object($this->entity)){
|
||||
$this->entity->setHealth($data["health"]);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case "onPlayerAdd":
|
||||
if($data["eid"] === $this->eid){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_ADD_PLAYER, array(
|
||||
"clientID" => $data["clientID"],
|
||||
"username" => $data["username"],
|
||||
"eid" => $data["eid"],
|
||||
"x" => $data["x"],
|
||||
"y" => $data["y"],
|
||||
"z" => $data["z"],
|
||||
));
|
||||
break;
|
||||
case "onEntityRemove":
|
||||
if($data === $this->eid){
|
||||
break;
|
||||
@ -260,10 +250,13 @@ class Session{
|
||||
break;
|
||||
case MC_LOGIN:
|
||||
$this->username = str_replace("/", "", $data["username"]);
|
||||
foreach($this->server->clients as $c){
|
||||
if($c->eid !== $this->eid and $c->username === $this->username){
|
||||
$c->close("logged in from another location");
|
||||
}
|
||||
$u = $this->server->api->player->get($this->username);
|
||||
$c = $this->server->api->player->getByClientID($this->clientID);
|
||||
if($u !== false){
|
||||
$c->close("logged in from another location");
|
||||
}
|
||||
if($c !== false){
|
||||
$c->close("logged in from another location");
|
||||
}
|
||||
if($this->server->whitelist !== false and !in_array($this->username, $this->server->whitelist)){
|
||||
$this->close("\"".$this->username."\" not being on white-list", false);
|
||||
@ -273,16 +266,6 @@ class Session{
|
||||
$this->auth = true;
|
||||
$this->data["lastIP"] = $this->ip;
|
||||
$this->data["lastID"] = $this->clientID;
|
||||
$this->evid[] = array("onTimeChange", $this->server->event("onTimeChange", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onChat", $this->server->event("onChat", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onDeath", $this->server->event("onDeath", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onPlayerAdd", $this->server->event("onPlayerAdd", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onEntityRemove", $this->server->event("onEntityRemove", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onEntityMove", $this->server->event("onEntityMove", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onHealthChange", $this->server->event("onHealthChange", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onHealthRegeneration", $this->server->event("onHealthRegeneration", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onAnimate", $this->server->event("onAnimate", array($this, "eventHandler")));
|
||||
$this->evid[] = array("onTeleport", $this->server->event("onTeleport", array($this, "eventHandler")));
|
||||
$this->dataPacket(MC_LOGIN_STATUS, array(
|
||||
"status" => 0,
|
||||
));
|
||||
@ -300,43 +283,25 @@ class Session{
|
||||
if(is_object($this->entity)){
|
||||
break;
|
||||
}
|
||||
$this->server->trigger("onHealthChange", array("eid" => $this->eid, "health" => $this->data["health"], "cause" => "respawn"));
|
||||
console("[DEBUG] Player with EID ".$this->eid." \"".$this->username."\" spawned!", true, true, 2);
|
||||
$this->entity = new Entity($this->eid, ENTITY_PLAYER, 0, $this->server);
|
||||
$this->entity = $this->server->api->entity->add(ENTITY_PLAYER, 0, array("player" => $this));
|
||||
$this->eid = $this->entity->eid;
|
||||
$this->server->query("UPDATE players SET EID = ".$this->eid." WHERE clientID = ".$this->clientID.";");
|
||||
$this->entity->setName($this->username);
|
||||
$this->entity->setHealth($this->data["health"]);
|
||||
$this->entity->data["clientID"] = $this->clientID;
|
||||
$this->server->entities[$this->eid] = &$this->entity;
|
||||
$this->server->trigger("onPlayerAdd", array(
|
||||
"clientID" => $this->clientID,
|
||||
"username" => $this->username,
|
||||
"eid" => $this->eid,
|
||||
"x" => $this->data["spawn"]["x"],
|
||||
"y" => $this->data["spawn"]["y"],
|
||||
"z" => $this->data["spawn"]["z"],
|
||||
));
|
||||
foreach($this->server->entities as $entity){
|
||||
if($entity->eid !== $this->eid){
|
||||
if($entity->class === ENTITY_PLAYER){
|
||||
$this->eventHandler(array(
|
||||
"clientID" => $entity->data["clientID"],
|
||||
"username" => $entity->name,
|
||||
"eid" => $entity->eid,
|
||||
"x" => $entity->position["x"],
|
||||
"y" => $entity->position["y"],
|
||||
"z" => $entity->position["z"],
|
||||
), "onPlayerAdd");
|
||||
}else{
|
||||
$this->dataPacket(MC_ADD_MOB, array(
|
||||
"eid" => $entity->eid,
|
||||
"type" => $entity->type,
|
||||
"x" => $entity->position["x"],
|
||||
"y" => $entity->position["y"],
|
||||
"z" => $entity->position["z"],
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->server->api->entity->spawnAll($this);
|
||||
$this->server->api->entity->spawnToAll($this->eid);
|
||||
$this->evid[] = $this->server->event("onTimeChange", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onChat", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onDeath", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onEntityRemove", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onEntityMove", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onHealthChange", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onHealthRegeneration", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onAnimate", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onTeleport", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("onBlockUpdate", array($this, "eventHandler"));
|
||||
console("[DEBUG] Player with EID ".$this->eid." \"".$this->username."\" spawned!", true, true, 2);
|
||||
|
||||
$this->eventHandler($this->server->motd, "onChat");
|
||||
if($this->MTU <= 548){
|
||||
$this->eventHandler("Your connection is bad, you may experience lag and slow map loading.", "onChat");
|
||||
@ -363,40 +328,22 @@ class Session{
|
||||
), true);
|
||||
}
|
||||
');
|
||||
console("[DEBUG] Chunk X ".$data["x"]." Z ".$data["z"]." requested", true, true, 2);
|
||||
console("[INTERNAL] Chunk X ".$data["x"]." Z ".$data["z"]." requested", true, true, 3);
|
||||
break;
|
||||
case MC_PLACE_BLOCK:
|
||||
var_dump($data);
|
||||
break;
|
||||
case MC_REMOVE_BLOCK:
|
||||
console("[DEBUG] EID ".$this->eid." broke block at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
|
||||
$block = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
|
||||
if($block[0] === 0){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_ADD_ITEM_ENTITY, array(
|
||||
"eid" => $this->server->eidCnt++,
|
||||
"x" => $data["x"] + mt_rand(0, 100)/100,
|
||||
"y" => $data["y"],
|
||||
"z" => $data["z"] + mt_rand(0, 100)/100,
|
||||
"block" => $block[0],
|
||||
"meta" => $block[1],
|
||||
"stack" => 1,
|
||||
));
|
||||
/*$this->send(0x84, array(
|
||||
$this->counter[0],
|
||||
0x00,
|
||||
array(
|
||||
"id" => MC_UPDATE_BLOCK,
|
||||
"x" => $data["x"],
|
||||
"y" => $data["y"],
|
||||
"z" => $data["z"],
|
||||
"block" => 56,
|
||||
"meta" => 0,
|
||||
),
|
||||
));
|
||||
++$this->counter[0];*/
|
||||
$data["eid"] = $this->eid;
|
||||
$this->server->api->level->handle($data, "onBlockBreak");
|
||||
//$this->server->trigger("onBlockBreak", $data);
|
||||
break;
|
||||
case MC_INTERACT:
|
||||
if($this->server->gamemode !== 1 and $this->server->difficulty > 0 and isset($this->server->entities[$data["target"]]) and Utils::distance($this->entity->position, $this->server->entities[$data["target"]]->position) <= 8){
|
||||
if(isset($this->server->entities[$data["target"]]) and Utils::distance($this->entity->position, $this->server->entities[$data["target"]]->position) <= 8){
|
||||
console("[DEBUG] EID ".$this->eid." attacked EID ".$data["target"], true, true, 2);
|
||||
if($this->server->gamemode !== 1 and $this->server->difficulty > 0){
|
||||
|
||||
}
|
||||
$this->server->trigger("onHealthChange", array("eid" => $data["target"], "health" => $this->server->entities[$data["target"]]->getHealth() - $this->server->difficulty, "cause" => $this->eid));
|
||||
}
|
||||
break;
|
||||
|
@ -28,6 +28,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
require_once(dirname(__FILE__)."/config.php");
|
||||
require_once("common/functions.php");
|
||||
//set_error_handler("error_handler");
|
||||
|
||||
$errors = 0;
|
||||
|
||||
|
@ -120,6 +120,10 @@ function console($message, $EOL = true, $log = true, $level = 1){
|
||||
}
|
||||
}
|
||||
|
||||
function error_handler($errno, $errstr, $errfile, $errline){
|
||||
console("[ERROR] A level ".$errno." error happened: \"$errstr\" in \"$errfile\" at line $errline", true, true, 0);
|
||||
}
|
||||
|
||||
function logg($message, $name, $EOL = true, $level = 2, $close = false){
|
||||
global $fpointers;
|
||||
if((!defined("DEBUG") or DEBUG >= $level) and (!defined("LOG") or LOG === true)){
|
||||
|
Loading…
x
Reference in New Issue
Block a user