mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 12:18:46 +00:00
PMF & Multiworld [part 1]
This commit is contained in:
parent
bbbc54f606
commit
db8f50f408
@ -180,7 +180,7 @@ class BlockAPI{
|
|||||||
}else{
|
}else{
|
||||||
$b = new GenericBlock($id, $meta);
|
$b = new GenericBlock($id, $meta);
|
||||||
}
|
}
|
||||||
if($v instanceof Vector3){
|
if($v instanceof Position){
|
||||||
$b->position($v);
|
$b->position($v);
|
||||||
}
|
}
|
||||||
return $b;
|
return $b;
|
||||||
@ -197,44 +197,12 @@ class BlockAPI{
|
|||||||
return $i;
|
return $i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBlock(Vector3 $block, $id, $meta, $update = true, $tiles = false){
|
|
||||||
if(($block instanceof Vector3) or (($block instanceof Block) and $block->inWorld === true)){
|
|
||||||
$this->server->api->level->setBlock($block->x, $block->y, $block->z, (int) $id, (int) $meta, $update, $tiles);
|
|
||||||
if($update === true){
|
|
||||||
$this->blockUpdate($block, BLOCK_UPDATE_NORMAL); //????? water?
|
|
||||||
$this->blockUpdateAround($block, BLOCK_UPDATE_NORMAL);
|
|
||||||
}
|
|
||||||
if($tiles === true){
|
|
||||||
if(($t = $this->server->api->tileentity->get($block->x, $block->y, $block->z)) !== false){
|
|
||||||
$t[0]->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBlock($x, $y = 0, $z = 0){
|
|
||||||
if($x instanceof Vector3){
|
|
||||||
$y = $x->y;
|
|
||||||
$z = $x->z;
|
|
||||||
$x = $x->x;
|
|
||||||
}
|
|
||||||
$b = $this->server->api->level->getBlock($x, $y, $z);
|
|
||||||
return BlockAPI::get($b[0], $b[1], new Vector3($b[2][0], $b[2][1], $b[2][2]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBlockFace(Block $block, $face){
|
|
||||||
return $this->getBlock($block->getSide($face));
|
|
||||||
}
|
|
||||||
|
|
||||||
function __construct(){
|
function __construct(){
|
||||||
$this->server = ServerAPI::request();
|
$this->server = ServerAPI::request();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function init(){
|
public function init(){
|
||||||
$this->server->event("server.tick", array($this, "blockUpdateTick"));
|
$this->server->event("server.tick", array($this, "blockUpdateTick"));
|
||||||
$this->server->addHandler("block.update", array($this, "blockUpdateRemote"), 1);
|
|
||||||
$this->server->api->console->register("give", "<player> <item[:damage]> [amount]", array($this, "commandHandler"));
|
$this->server->api->console->register("give", "<player> <item[:damage]> [amount]", array($this, "commandHandler"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +259,7 @@ class BlockAPI{
|
|||||||
|
|
||||||
public function playerBlockBreak(Player $player, Vector3 $vector){
|
public function playerBlockBreak(Player $player, Vector3 $vector){
|
||||||
|
|
||||||
$target = $this->getBlock($vector);
|
$target = $player->level->getBlock($vector);
|
||||||
$item = $player->equipment;
|
$item = $player->equipment;
|
||||||
|
|
||||||
if($this->server->api->dhandle("player.block.touch", array("type" => "break", "player" => $player, "target" => $target, "item" => $item)) === false){
|
if($this->server->api->dhandle("player.block.touch", array("type" => "break", "player" => $player, "target" => $target, "item" => $item)) === false){
|
||||||
@ -306,7 +274,7 @@ class BlockAPI{
|
|||||||
if($this->server->api->dhandle("player.block.break", array("player" => $player, "target" => $target, "item" => $item)) !== false){
|
if($this->server->api->dhandle("player.block.break", array("player" => $player, "target" => $target, "item" => $item)) !== false){
|
||||||
$player->lastBreak = microtime(true);
|
$player->lastBreak = microtime(true);
|
||||||
$drops = $target->getDrops($item, $player);
|
$drops = $target->getDrops($item, $player);
|
||||||
$target->onBreak($this, $item, $player);
|
$target->onBreak($item, $player);
|
||||||
}else{
|
}else{
|
||||||
return $this->cancelAction($target, $player);
|
return $this->cancelAction($target, $player);
|
||||||
}
|
}
|
||||||
@ -320,7 +288,7 @@ class BlockAPI{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function drop(Vector3 $pos, Item $item){
|
public function drop(Position $pos, Item $item){
|
||||||
if($item->getID() === AIR or $item->count <= 0){
|
if($item->getID() === AIR or $item->count <= 0){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -335,7 +303,7 @@ class BlockAPI{
|
|||||||
$item->count = min($item->getMaxStackSize(), $count);
|
$item->count = min($item->getMaxStackSize(), $count);
|
||||||
$count -= $item->count;
|
$count -= $item->count;
|
||||||
$server = ServerAPI::request();
|
$server = ServerAPI::request();
|
||||||
$e = $server->api->entity->add(ENTITY_ITEM, $item->getID(), $data);
|
$e = $server->api->entity->add($pos->level, ENTITY_ITEM, $item->getID(), $data);
|
||||||
//$e->speedX = mt_rand(-10, 10) / 100;
|
//$e->speedX = mt_rand(-10, 10) / 100;
|
||||||
//$e->speedY = mt_rand(0, 5) / 100;
|
//$e->speedY = mt_rand(0, 5) / 100;
|
||||||
//$e->speedZ = mt_rand(-10, 10) / 100;
|
//$e->speedZ = mt_rand(-10, 10) / 100;
|
||||||
@ -349,8 +317,8 @@ class BlockAPI{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = $this->getBlock($vector);
|
$target = $player->level->getBlock($vector);
|
||||||
$block = $this->getBlockFace($target, $face);
|
$block = $target->getSide($face);
|
||||||
$item = $player->equipment;
|
$item = $player->equipment;
|
||||||
|
|
||||||
if($target->getID() === AIR and $this->server->api->dhandle("player.block.place.invalid", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) !== true){ //If no block exists or not allowed in CREATIVE
|
if($target->getID() === AIR and $this->server->api->dhandle("player.block.place.invalid", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) !== true){ //If no block exists or not allowed in CREATIVE
|
||||||
@ -364,7 +332,7 @@ class BlockAPI{
|
|||||||
$this->blockUpdate($target, BLOCK_UPDATE_TOUCH);
|
$this->blockUpdate($target, BLOCK_UPDATE_TOUCH);
|
||||||
|
|
||||||
if($target->isActivable === true){
|
if($target->isActivable === true){
|
||||||
if($this->server->api->dhandle("player.block.activate", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) !== false and $target->onActivate($this, $item, $player) === true){
|
if($this->server->api->dhandle("player.block.activate", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) !== false and $target->onActivate($item, $player) === true){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,11 +365,11 @@ class BlockAPI{
|
|||||||
|
|
||||||
if($this->server->api->dhandle("player.block.place", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) === false){
|
if($this->server->api->dhandle("player.block.place", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) === false){
|
||||||
return $this->cancelAction($block, $player);
|
return $this->cancelAction($block, $player);
|
||||||
}elseif($hand->place($this, $item, $player, $block, $target, $face, $fx, $fy, $fz) === false){
|
}elseif($hand->place($item, $player, $block, $target, $face, $fx, $fy, $fz) === false){
|
||||||
return $this->cancelAction($block, $player);
|
return $this->cancelAction($block, $player);
|
||||||
}
|
}
|
||||||
if($hand->getID() === SIGN_POST or $hand->getID() === WALL_POST){
|
if($hand->getID() === SIGN_POST or $hand->getID() === WALL_POST){
|
||||||
$t = $this->server->api->tileentity->addSign($block->x, $block->y, $block->z);
|
$t = $this->server->api->tileentity->addSign($player->level, $block->x, $block->y, $block->z);
|
||||||
$t->data["creator"] = $player->username;
|
$t->data["creator"] = $player->username;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,36 +737,42 @@ class BlockAPI{
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public function blockUpdateAround(Vector3 $pos, $type = BLOCK_UPDATE_NORMAL){
|
public function blockUpdateAround(Position $pos, $type = BLOCK_UPDATE_NORMAL){
|
||||||
$this->blockUpdate($pos->getSide(0), $type);
|
|
||||||
$this->blockUpdate($pos->getSide(1), $type);
|
|
||||||
$this->blockUpdate($pos->getSide(2), $type);
|
|
||||||
$this->blockUpdate($pos->getSide(3), $type);
|
|
||||||
$this->blockUpdate($pos->getSide(4), $type);
|
|
||||||
$this->blockUpdate($pos->getSide(5), $type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function blockUpdate(Vector3 $pos, $type = BLOCK_UPDATE_NORMAL){
|
|
||||||
if(!($pos instanceof Block)){
|
if(!($pos instanceof Block)){
|
||||||
$pos = $pos->floor();
|
$pos = $pos->floor();
|
||||||
$block = $this->getBlock($pos);
|
$block = $pos->level->getBlock($pos);
|
||||||
}else{
|
}else{
|
||||||
$block = $pos;
|
$block = $pos;
|
||||||
}
|
}
|
||||||
$level = $block->onUpdate($this, $type);
|
$this->blockUpdate($block->getSide(0), $type);
|
||||||
|
$this->blockUpdate($block->getSide(1), $type);
|
||||||
|
$this->blockUpdate($block->getSide(2), $type);
|
||||||
|
$this->blockUpdate($block->getSide(3), $type);
|
||||||
|
$this->blockUpdate($block->getSide(4), $type);
|
||||||
|
$this->blockUpdate($block->getSide(5), $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function blockUpdate(Position $pos, $type = BLOCK_UPDATE_NORMAL){
|
||||||
|
if(!($pos instanceof Block)){
|
||||||
|
$pos = $pos->floor();
|
||||||
|
$block = $pos->level->getBlock($pos);
|
||||||
|
}else{
|
||||||
|
$block = $pos;
|
||||||
|
}
|
||||||
|
$level = $block->onUpdate($type);
|
||||||
if($level === BLOCK_UPDATE_NORMAL){
|
if($level === BLOCK_UPDATE_NORMAL){
|
||||||
$this->blockUpdateAround($block, $level);
|
$this->blockUpdateAround($block, $level);
|
||||||
}
|
}
|
||||||
return $level;
|
return $level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scheduleBlockUpdate(Vector3 $pos, $delay, $type = BLOCK_UPDATE_SCHEDULED){
|
public function scheduleBlockUpdate(Position $pos, $delay, $type = BLOCK_UPDATE_SCHEDULED){
|
||||||
$type = (int) $type;
|
$type = (int) $type;
|
||||||
if($delay < 0){
|
if($delay < 0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$pos = $pos->floor();
|
$pos = $pos->floor();
|
||||||
$index = $pos->x.".".$pos->y.".".$pos->z;
|
$index = $pos->x.".".$pos->y.".".$pos->z.".".$pos->level->getName();
|
||||||
$delay = microtime(true) + $delay * 0.05;
|
$delay = microtime(true) + $delay * 0.05;
|
||||||
if(!isset($this->scheduledUpdates[$index])){
|
if(!isset($this->scheduledUpdates[$index])){
|
||||||
$this->scheduledUpdates[$index] = array(
|
$this->scheduledUpdates[$index] = array(
|
||||||
@ -806,29 +780,21 @@ class BlockAPI{
|
|||||||
$type,
|
$type,
|
||||||
$delay,
|
$delay,
|
||||||
);
|
);
|
||||||
$this->server->query("INSERT INTO blockUpdates (x, y, z, delay) VALUES (".$pos->x.", ".$pos->y.", ".$pos->z.", ".$delay.");");
|
$this->server->query("INSERT INTO blockUpdates (x, y, z, level, delay) VALUES (".$pos->x.", ".$pos->y.", ".$pos->z.", '".$pos->level->getName()."', ".$delay.");");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function blockUpdateRemote($data, $event){
|
|
||||||
if($event !== "block.update"){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->blockUpdate(new Vector3($data["x"], $data["y"], $data["z"]), isset($data["type"]) ? ((int) $data["type"]):BLOCK_UPDATE_RANDOM);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function blockUpdateTick($time, $event){
|
public function blockUpdateTick($time, $event){
|
||||||
if($event !== "server.tick"){ //WTF??
|
if($event !== "server.tick"){ //WTF??
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(count($this->scheduledUpdates) > 0){
|
if(count($this->scheduledUpdates) > 0){
|
||||||
$update = $this->server->query("SELECT x,y,z FROM blockUpdates WHERE delay <= ".$time.";");
|
$update = $this->server->query("SELECT x,y,z,level FROM blockUpdates WHERE delay <= ".$time.";");
|
||||||
if($update !== false and $update !== true){
|
if($update !== false and $update !== true){
|
||||||
while(($up = $update->fetchArray(SQLITE3_ASSOC)) !== false){
|
while(($up = $update->fetchArray(SQLITE3_ASSOC)) !== false){
|
||||||
$index = $up["x"].".".$up["y"].".".$up["z"];
|
$index = $up["x"].".".$up["y"].".".$up["z"].".".$up["level"];
|
||||||
if(isset($this->scheduledUpdates[$index])){
|
if(isset($this->scheduledUpdates[$index])){
|
||||||
$up = $this->scheduledUpdates[$index];
|
$up = $this->scheduledUpdates[$index];
|
||||||
unset($this->scheduledUpdates[$index]);
|
unset($this->scheduledUpdates[$index]);
|
||||||
|
@ -27,13 +27,17 @@ the Free Software Foundation, either version 3 of the License, or
|
|||||||
|
|
||||||
class EntityAPI{
|
class EntityAPI{
|
||||||
private $server;
|
private $server;
|
||||||
|
private $entities;
|
||||||
|
private $eCnt = 1;
|
||||||
|
|
||||||
function __construct(){
|
function __construct(){
|
||||||
|
$this->entities = array();
|
||||||
$this->server = ServerAPI::request();
|
$this->server = ServerAPI::request();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($eid){
|
public function get($eid){
|
||||||
if(isset($this->server->entities[$eid])){
|
if(isset($this->entities[$eid])){
|
||||||
return $this->server->entities[$eid];
|
return $this->entities[$eid];
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -42,8 +46,21 @@ class EntityAPI{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAll(){
|
public function getAll($level = null){
|
||||||
return $this->server->entities;
|
if($level instanceof Level){
|
||||||
|
$entities = array();
|
||||||
|
$l = $this->server->query("SELECT EID FROM entities WHERE level = '".$this->level->getName()."';");
|
||||||
|
if($l !== false and $l !== true){
|
||||||
|
while(($e = $l->fetchArray(SQLITE3_ASSOC)) !== false){
|
||||||
|
$e = $this->get($e["EID"]);
|
||||||
|
if($e instanceof Entity){
|
||||||
|
$entities[$e->eid] = $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $entities;
|
||||||
|
}
|
||||||
|
return $this->entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function heal($eid, $heal = 1, $cause){
|
public function heal($eid, $heal = 1, $cause){
|
||||||
@ -58,11 +75,11 @@ class EntityAPI{
|
|||||||
$e->setHealth($e->getHealth() - $attack, $cause, $force);
|
$e->setHealth($e->getHealth() - $attack, $cause, $force);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add($class, $type = 0, $data = array()){
|
public function add(Level $level, $class, $type = 0, $data = array()){
|
||||||
$eid = $this->server->eidCnt++;
|
$eid = $this->eCnt++;
|
||||||
$this->server->entities[$eid] = new Entity($eid, $class, $type, $data);
|
$this->entities[$eid] = new Entity($level, $eid, $class, $type, $data);
|
||||||
$this->server->handle("entity.add", $this->server->entities[$eid]);
|
$this->server->handle("entity.add", $this->entities[$eid]);
|
||||||
return $this->server->entities[$eid];
|
return $this->entities[$eid];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function spawnTo($eid, $player){
|
public function spawnTo($eid, $player){
|
||||||
@ -92,10 +109,10 @@ class EntityAPI{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function remove($eid){
|
public function remove($eid){
|
||||||
if(isset($this->server->entities[$eid])){
|
if(isset($this->entities[$eid])){
|
||||||
$entity = $this->server->entities[$eid];
|
$entity = $this->entities[$eid];
|
||||||
$this->server->entities[$eid] = null;
|
$this->entities[$eid] = null;
|
||||||
unset($this->server->entities[$eid]);
|
unset($this->entities[$eid]);
|
||||||
$entity->closed = true;
|
$entity->closed = true;
|
||||||
$this->server->query("DELETE FROM entities WHERE EID = ".$eid.";");
|
$this->server->query("DELETE FROM entities WHERE EID = ".$eid.";");
|
||||||
$this->server->api->dhandle("entity.remove", $entity);
|
$this->server->api->dhandle("entity.remove", $entity);
|
||||||
|
@ -26,15 +26,80 @@ the Free Software Foundation, either version 3 of the License, or
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class LevelAPI{
|
class LevelAPI{
|
||||||
private $server, $map;
|
private $server, $levels, $default;
|
||||||
function __construct(){
|
public function __construct(){
|
||||||
$this->server = ServerAPI::request();
|
$this->server = ServerAPI::request();
|
||||||
$this->map = $this->server->map;
|
$this->levels = array();
|
||||||
$this->heightMap = array_fill(0, 256, array());
|
$this->map = $this->server->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDefault(){
|
||||||
|
return $this->levels[$this->default];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function init(){
|
public function init(){
|
||||||
|
$this->default = $this->server->api->getProperty("level-name");
|
||||||
|
if($this->loadLevel($this->default) === false){
|
||||||
|
$path = DATA_PATH."worlds/".$this->default."/";
|
||||||
|
$generator = "SuperflatGenerator";
|
||||||
|
if($this->server->api->getProperty("generator") !== false and class_exists($this->server->api->getProperty("generator"))){
|
||||||
|
$generator = $this->server->api->getProperty("generator");
|
||||||
|
}
|
||||||
|
$gen = new WorldGenerator($generator, $this->server->seed);
|
||||||
|
if($this->server->api->getProperty("generator-settings") !== false and trim($this->server->api->getProperty("generator-settings")) != ""){
|
||||||
|
$gen->set("preset", $this->server->api->getProperty("generator-settings"));
|
||||||
|
}
|
||||||
|
$gen->init();
|
||||||
|
$gen->generate();
|
||||||
|
$gen->save($path, $this->default);
|
||||||
|
$this->loadLevel($this->default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadLevel($name){
|
||||||
|
$path = DATA_PATH."worlds/".$name."/";
|
||||||
|
if(!file_exists($path."level.pmf")){
|
||||||
|
$level = new LevelImport($path);
|
||||||
|
if($level->import() === false){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console("[INFO] Preparing level \"".$name."\"");
|
||||||
|
$level = new PMFLevel($path."level.pmf");
|
||||||
|
$entities = new Config($path."entities.yml", CONFIG_YAML);
|
||||||
|
$tileEntities = new Config($path."tileEntities.yml", CONFIG_YAML);
|
||||||
|
$this->levels[$name] = new Level($level, $entities, $tileEntities);
|
||||||
|
foreach($entities->getAll() as $entity){
|
||||||
|
if(!isset($entity["id"])){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if($entity["id"] === 64){ //Item Drop
|
||||||
|
$e = $this->server->api->entity->add($this->levels[$name], ENTITY_ITEM, $entity["Item"]["id"], array(
|
||||||
|
"meta" => $entity["Item"]["Damage"],
|
||||||
|
"stack" => $entity["Item"]["Count"],
|
||||||
|
"x" => $entity["Pos"][0],
|
||||||
|
"y" => $entity["Pos"][1],
|
||||||
|
"z" => $entity["Pos"][2],
|
||||||
|
"yaw" => $entity["Rotation"][0],
|
||||||
|
"pitch" => $entity["Rotation"][1],
|
||||||
|
));
|
||||||
|
}elseif($entity["id"] === OBJECT_PAINTING){ //Painting
|
||||||
|
$e = $this->server->api->entity->add($this->levels[$name], ENTITY_OBJECT, $entity["id"], $entity);
|
||||||
|
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
||||||
|
$e->setHealth($entity["Health"]);
|
||||||
|
}else{
|
||||||
|
$e = $this->server->api->entity->add($this->levels[$name], ENTITY_MOB, $entity["id"], $entity);
|
||||||
|
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
||||||
|
$e->setHealth($entity["Health"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($tileEntities->getAll() as $tile){
|
||||||
|
if(!isset($tile["id"])){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$t = $this->server->api->tileentity->add($this->levels[$name], $tile["id"], $tile["x"], $tile["y"], $tile["z"], $tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle($data, $event){
|
public function handle($data, $event){
|
||||||
@ -46,91 +111,124 @@ class LevelAPI{
|
|||||||
return $this->server->spawn;
|
return $this->server->spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getChunk($X, $Z){
|
/*
|
||||||
return $this->map->map[$X][$Z];
|
if(file_exists(DATA_PATH."worlds/level.dat")){
|
||||||
}
|
console("[NOTICE] Detected unimported map data. Importing...");
|
||||||
|
$this->importMap(DATA_PATH."worlds/", true);
|
||||||
public function getBlockFace($block, $face){
|
}
|
||||||
$data = array("x" => $block[2][0], "y" => $block[2][1], "z" => $block[2][2]);
|
|
||||||
BlockFace::setPosition($data, $face);
|
$this->server->mapName = $this->getProperty("level-name");
|
||||||
return $this->getBlock($data["x"], $data["y"], $data["z"]);
|
$this->server->mapDir = DATA_PATH."worlds/".$this->server->mapName."/";
|
||||||
}
|
if($this->server->mapName === false or trim($this->server->mapName) === "" or (!file_exists($this->server->mapDir."chunks.dat") and !file_exists($this->server->mapDir."chunks.dat.gz") and !file_exists($this->server->mapDir."level.pmf"))){
|
||||||
|
if($this->server->mapName === false or trim($this->server->mapName) === ""){
|
||||||
public function getBlock($x, $y, $z){
|
$this->server->mapName = "world";
|
||||||
$b = $this->map->getBlock($x, $y, $z);
|
}
|
||||||
$b[2] = array($x, $y, $z);
|
$this->server->mapDir = DATA_PATH."worlds/".$this->server->mapName."/";
|
||||||
return $b;
|
$generator = "SuperflatGenerator";
|
||||||
}
|
if($this->getProperty("generator") !== false and class_exists($this->getProperty("generator"))){
|
||||||
|
$generator = $this->getProperty("generator");
|
||||||
public function getFloor($x, $z){
|
}
|
||||||
if(!isset($this->heightMap[$z][$x])){
|
$this->gen = new WorldGenerator($generator, $this->server->seed);
|
||||||
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
|
if($this->getProperty("generator-settings") !== false and trim($this->getProperty("generator-settings")) != ""){
|
||||||
|
$this->gen->set("preset", $this->getProperty("generator-settings"));
|
||||||
|
}
|
||||||
|
$this->gen->init();
|
||||||
|
$this->gen->generate();
|
||||||
|
$this->gen->save($this->server->mapDir, $this->server->mapName);
|
||||||
|
$this->setProperty("level-name", $this->server->mapName);
|
||||||
|
$this->setProperty("gamemode", SURVIVAL);
|
||||||
|
}
|
||||||
|
$this->server->loadMap();
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function loadMap(){
|
||||||
|
if($this->mapName !== false and trim($this->mapName) !== ""){
|
||||||
|
if(!file_exists($this->mapDir."level.pmf")){
|
||||||
|
$level = new LevelImport($this->mapDir);
|
||||||
|
$level->import();
|
||||||
|
}
|
||||||
|
$this->level = new PMFLevel($this->mapDir."level.pmf");
|
||||||
|
console("[INFO] Preparing level \"".$this->level->getData("name")."\"");
|
||||||
|
$this->time = (int) $this->level->getData("time");
|
||||||
|
$this->seed = (int) $this->level->getData("seed");
|
||||||
|
$this->spawn = $this->level->getSpawn();
|
||||||
}
|
}
|
||||||
return $this->heightMap[$z][$x];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBlock($x, $y, $z, $block, $meta = 0){
|
public function save($final = false){
|
||||||
if($x < 0 or $y < 0 or $z < 0){
|
if($this->mapName !== false){
|
||||||
return false;
|
$this->levelData["Time"] = $this->time;
|
||||||
}
|
file_put_contents($this->mapDir."level.dat", serialize($this->levelData));
|
||||||
if($this->server->api->dhandle("block.change", array(
|
$this->map->saveMap($final);
|
||||||
"x" => $x,
|
$this->trigger("server.save", $final);
|
||||||
"y" => $y,
|
if(count($this->entities) > 0){
|
||||||
"z" => $z,
|
$entities = array();
|
||||||
"block" => $block,
|
foreach($this->entities as $entity){
|
||||||
"meta" => $meta,
|
if($entity->class === ENTITY_MOB){
|
||||||
)) !== false){
|
$entities[] = array(
|
||||||
$this->map->setBlock($x, $y, $z, $block, $meta);
|
"id" => $entity->type,
|
||||||
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
|
"Color" => @$entity->data["Color"],
|
||||||
}
|
"Sheared" => @$entity->data["Sheared"],
|
||||||
return true;
|
"Health" => $entity->health,
|
||||||
}
|
"Pos" => array(
|
||||||
|
0 => $entity->x,
|
||||||
public function getOrderedChunks($X, $Z, $columnsPerPacket = 2){
|
1 => $entity->y,
|
||||||
$columnsPerPacket = max(1, (int) $columnsPerPacket);
|
2 => $entity->z,
|
||||||
$ordered = array();
|
),
|
||||||
$i = 0;
|
"Rotation" => array(
|
||||||
$cnt = 0;
|
0 => $entity->yaw,
|
||||||
$ordered[$i] = "";
|
1 => $entity->pitch,
|
||||||
for($z = 0; $z < 16; ++$z){
|
),
|
||||||
for($x = 0; $x < 16; ++$x){
|
);
|
||||||
if($cnt >= $columnsPerPacket){
|
}elseif($entity->class === ENTITY_OBJECT){
|
||||||
++$i;
|
$entities[] = array(
|
||||||
$ordered[$i] = str_repeat("\x00", $i * $columnsPerPacket);
|
"id" => $entity->type,
|
||||||
$cnt = 0;
|
"TileX" => $entity->x,
|
||||||
|
"TileX" => $entity->y,
|
||||||
|
"TileX" => $entity->z,
|
||||||
|
"Health" => $entity->health,
|
||||||
|
"Motive" => $entity->data["Motive"],
|
||||||
|
"Pos" => array(
|
||||||
|
0 => $entity->x,
|
||||||
|
1 => $entity->y,
|
||||||
|
2 => $entity->z,
|
||||||
|
),
|
||||||
|
"Rotation" => array(
|
||||||
|
0 => $entity->yaw,
|
||||||
|
1 => $entity->pitch,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}elseif($entity->class === ENTITY_ITEM){
|
||||||
|
$entities[] = array(
|
||||||
|
"id" => 64,
|
||||||
|
"Item" => array(
|
||||||
|
"id" => $entity->type,
|
||||||
|
"Damage" => $entity->meta,
|
||||||
|
"Count" => $entity->stack,
|
||||||
|
),
|
||||||
|
"Health" => $entity->health,
|
||||||
|
"Pos" => array(
|
||||||
|
0 => $entity->x,
|
||||||
|
1 => $entity->y,
|
||||||
|
2 => $entity->z,
|
||||||
|
),
|
||||||
|
"Rotation" => array(
|
||||||
|
0 => 0,
|
||||||
|
1 => 0,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$ordered[$i] .= "\xff";
|
file_put_contents($this->mapDir."entities.dat", serialize($entities));
|
||||||
$block = $this->map->getChunkColumn($X, $Z, $x, $z, 0);
|
}
|
||||||
$meta = $this->map->getChunkColumn($X, $Z, $x, $z, 1);
|
if(count($this->tileEntities) > 0){
|
||||||
for($k = 0; $k < 8; ++$k){
|
$tiles = array();
|
||||||
$ordered[$i] .= substr($block, $k << 4, 16);
|
foreach($this->tileEntities as $tile){
|
||||||
$ordered[$i] .= substr($meta, $k << 3, 8);
|
$tiles[] = $tile->data;
|
||||||
}
|
}
|
||||||
++$cnt;
|
file_put_contents($this->mapDir."tileEntities.dat", serialize($tiles));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $ordered;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMiniChunk($X, $Z, $Y, $MTU){
|
|
||||||
$ordered = array();
|
|
||||||
$i = 0;
|
|
||||||
$ordered[$i] = "";
|
|
||||||
$cnt = 0;
|
|
||||||
for($z = 0; $z < 16; ++$z){
|
|
||||||
for($x = 0; $x < 16; ++$x){
|
|
||||||
if((strlen($ordered[$i]) + 16 + 8 + 1) > $MTU){
|
|
||||||
++$i;
|
|
||||||
$ordered[$i] = str_repeat("\x00", $cnt);
|
|
||||||
}
|
|
||||||
$ordered[$i] .= chr(1 << $Y);
|
|
||||||
$block = $this->map->getChunkColumn($X, $Z, $x, $z, 0);
|
|
||||||
$meta = $this->map->getChunkColumn($X, $Z, $x, $z, 1);
|
|
||||||
$ordered[$i] .= substr($block, $Y << 4, 16);
|
|
||||||
$ordered[$i] .= substr($meta, $Y << 3, 8);
|
|
||||||
++$cnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $ordered;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -318,14 +318,16 @@ class PlayerAPI{
|
|||||||
$default = array(
|
$default = array(
|
||||||
"caseusername" => $name,
|
"caseusername" => $name,
|
||||||
"position" => array(
|
"position" => array(
|
||||||
"x" => $this->server->spawn["x"],
|
"level" => $this->server->spawn->level->getName(),
|
||||||
"y" => $this->server->spawn["y"],
|
"x" => $this->server->spawn->x,
|
||||||
"z" => $this->server->spawn["z"],
|
"y" => $this->server->spawn->y,
|
||||||
|
"z" => $this->server->spawn->z,
|
||||||
),
|
),
|
||||||
"spawn" => array(
|
"spawn" => array(
|
||||||
"x" => $this->server->spawn["x"],
|
"level" => $this->server->spawn->level->getName(),
|
||||||
"y" => $this->server->spawn["y"],
|
"x" => $this->server->spawn->x,
|
||||||
"z" => $this->server->spawn["z"],
|
"y" => $this->server->spawn->y,
|
||||||
|
"z" => $this->server->spawn->z,
|
||||||
),
|
),
|
||||||
"inventory" => array_fill(0, 36, array(AIR, 0, 0)),
|
"inventory" => array_fill(0, 36, array(AIR, 0, 0)),
|
||||||
"armor" => array_fill(0, 4, array(AIR, 0, 0)),
|
"armor" => array_fill(0, 4, array(AIR, 0, 0)),
|
||||||
|
@ -54,7 +54,7 @@ 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);
|
||||||
console("[INFO] \x1b[33;1mPocketMine-MP ".MAJOR_VERSION.", LGPL License", true, true, 0);
|
console("[INFO] \x1b[33;1mPocketMine-MP ".MAJOR_VERSION." API #".CURRENT_API_VERSION.", LGPL License", true, true, 0);
|
||||||
|
|
||||||
console("[INFO] Loading properties...");
|
console("[INFO] Loading properties...");
|
||||||
$this->config = new Config(DATA_PATH . "server.properties", CONFIG_PROPERTIES, array(
|
$this->config = new Config(DATA_PATH . "server.properties", CONFIG_PROPERTIES, array(
|
||||||
@ -149,33 +149,9 @@ class ServerAPI{
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(file_exists(DATA_PATH."worlds/level.dat")){
|
|
||||||
console("[NOTICE] Detected unimported map data. Importing...");
|
|
||||||
$this->importMap(DATA_PATH."worlds/", true);
|
|
||||||
}
|
|
||||||
$this->server->mapName = $this->getProperty("level-name");
|
|
||||||
$this->server->mapDir = DATA_PATH."worlds/".$this->server->mapName."/";
|
|
||||||
if($this->server->mapName === false or trim($this->server->mapName) === "" or (!file_exists($this->server->mapDir."chunks.dat") and !file_exists($this->server->mapDir."chunks.dat.gz"))){
|
|
||||||
if($this->server->mapName === false or trim($this->server->mapName) === ""){
|
|
||||||
$this->server->mapName = "world";
|
|
||||||
}
|
|
||||||
$this->server->mapDir = DATA_PATH."worlds/".$this->server->mapName."/";
|
|
||||||
$generator = "SuperflatGenerator";
|
|
||||||
if($this->getProperty("generator") !== false and class_exists($this->getProperty("generator"))){
|
|
||||||
$generator = $this->getProperty("generator");
|
|
||||||
}
|
|
||||||
$this->gen = new WorldGenerator($generator, $this->server->seed);
|
|
||||||
if($this->getProperty("generator-settings") !== false and trim($this->getProperty("generator-settings")) != ""){
|
|
||||||
$this->gen->set("preset", $this->getProperty("generator-settings"));
|
|
||||||
}
|
|
||||||
$this->gen->init();
|
|
||||||
$this->gen->generate();
|
|
||||||
$this->gen->save($this->server->mapDir, $this->server->mapName);
|
|
||||||
$this->setProperty("level-name", $this->server->mapName);
|
|
||||||
$this->setProperty("gamemode", SURVIVAL);
|
|
||||||
}
|
|
||||||
$this->loadProperties();
|
$this->loadProperties();
|
||||||
$this->server->loadMap();
|
|
||||||
|
|
||||||
$this->loadAPI("console", "ConsoleAPI");
|
$this->loadAPI("console", "ConsoleAPI");
|
||||||
$this->loadAPI("level", "LevelAPI");
|
$this->loadAPI("level", "LevelAPI");
|
||||||
@ -228,7 +204,7 @@ class ServerAPI{
|
|||||||
"online" => count($this->server->clients),
|
"online" => count($this->server->clients),
|
||||||
"max" => $this->server->maxClients,
|
"max" => $this->server->maxClients,
|
||||||
"plugins" => $plist,
|
"plugins" => $plist,
|
||||||
), 2);
|
), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct(){
|
public function __destruct(){
|
||||||
@ -480,7 +456,7 @@ class ServerAPI{
|
|||||||
}
|
}
|
||||||
$this->$name = new $class();
|
$this->$name = new $class();
|
||||||
$this->apiList[] = $this->$name;
|
$this->apiList[] = $this->$name;
|
||||||
console("[".($internal === true ? "INTERNAL":"DEBUG")."] API \x1b[36m".$name."\x1b[0m [\x1b[30;1m".$class."\x1b[0m] loaded", true, true, ($internal === true ? 2:1));
|
console("[".($internal === true ? "INTERNAL":"DEBUG")."] API \x1b[36m".$name."\x1b[0m [\x1b[30;1m".$class."\x1b[0m] loaded", true, true, ($internal === true ? 3:2));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -27,21 +27,15 @@ the Free Software Foundation, either version 3 of the License, or
|
|||||||
|
|
||||||
class TileEntityAPI{
|
class TileEntityAPI{
|
||||||
private $server;
|
private $server;
|
||||||
|
private $tileEntities;
|
||||||
|
private $tCnt = 1;
|
||||||
function __construct(){
|
function __construct(){
|
||||||
|
$this->tileEntities = array();
|
||||||
$this->server = ServerAPI::request();
|
$this->server = ServerAPI::request();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get($x, $y = false, $z = false){
|
public function get(Position $pos){
|
||||||
if(($x instanceof Vector3) or ($x instanceof Block)){
|
$tiles = $this->server->query("SELECT * FROM tileentities WHERE level = '".$pos->level->getName()."' AND x = {$pos->x} AND y = {$pos->y} AND z = {$pos->z};");
|
||||||
$z = (int) $x->z;
|
|
||||||
$y = (int) $x->y;
|
|
||||||
$x = (int) $x->x;
|
|
||||||
}else{
|
|
||||||
$x = (int) $x;
|
|
||||||
$y = (int) $y;
|
|
||||||
$z = (int) $z;
|
|
||||||
}
|
|
||||||
$tiles = $this->server->query("SELECT * FROM tileentities WHERE x = $x AND y = $y AND z = $z;");
|
|
||||||
$ret = array();
|
$ret = array();
|
||||||
if($tiles !== false and $tiles !== true){
|
if($tiles !== false and $tiles !== true){
|
||||||
while(($t = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){
|
while(($t = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){
|
||||||
@ -61,8 +55,8 @@ class TileEntityAPI{
|
|||||||
public function getByID($id){
|
public function getByID($id){
|
||||||
if($id instanceof TileEntity){
|
if($id instanceof TileEntity){
|
||||||
return $id;
|
return $id;
|
||||||
}elseif(isset($this->server->tileEntities[$id])){
|
}elseif(isset($this->tileEntities[$id])){
|
||||||
return $this->server->tileEntities[$id];
|
return $this->tileEntities[$id];
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -71,18 +65,31 @@ class TileEntityAPI{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAll(){
|
public function getAll($level = null){
|
||||||
return $this->server->tileEntities;
|
if($level instanceof Level){
|
||||||
|
$tileEntities = array();
|
||||||
|
$l = $this->server->query("SELECT ID FROM tileentities WHERE level = '".$this->level->getName()."';");
|
||||||
|
if($l !== false and $l !== true){
|
||||||
|
while(($t = $l->fetchArray(SQLITE3_ASSOC)) !== false){
|
||||||
|
$t = $this->get($e["ID"]);
|
||||||
|
if($t instanceof TileEntity){
|
||||||
|
$tileEntities[$t->id] = $t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $tileEntities;
|
||||||
|
}
|
||||||
|
return $this->tileEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add($class, $x, $y, $z, $data = array()){
|
public function add(Level $level, $class, $x, $y, $z, $data = array()){
|
||||||
$id = $this->tCnt++;
|
$id = $this->tCnt++;
|
||||||
$this->server->tileEntities[$id] = new TileEntity($id, $class, $x, $y, $z, $data);
|
$this->tileEntities[$id] = new TileEntity($id, $class, $x, $y, $z, $data);
|
||||||
$this->spawnToAll($id);
|
$this->spawnToAll($id);
|
||||||
return $this->server->tileEntities[$id];
|
return $this->tileEntities[$id];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addSign($x, $y, $z, $lines = array("", "", "", "")){
|
public function addSign(Level $level, $x, $y, $z, $lines = array("", "", "", "")){
|
||||||
return $this->add(TILE_SIGN, $x, $y, $z, $data = array(
|
return $this->add(TILE_SIGN, $x, $y, $z, $data = array(
|
||||||
"id" => "Sign",
|
"id" => "Sign",
|
||||||
"x" => $x,
|
"x" => $x,
|
||||||
@ -122,10 +129,10 @@ class TileEntityAPI{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function remove($id){
|
public function remove($id){
|
||||||
if(isset($this->server->tileEntities[$id])){
|
if(isset($this->tileEntities[$id])){
|
||||||
$t = $this->server->tileEntities[$id];
|
$t = $this->tileEntities[$id];
|
||||||
$this->server->tileEntities[$id] = null;
|
$this->tileEntities[$id] = null;
|
||||||
unset($this->server->tileEntities[$id]);
|
unset($this->tileEntities[$id]);
|
||||||
$t->closed = true;
|
$t->closed = true;
|
||||||
$t->close();
|
$t->close();
|
||||||
$this->server->query("DELETE FROM tileentities WHERE ID = ".$id.";");
|
$this->server->query("DELETE FROM tileentities WHERE ID = ".$id.";");
|
||||||
|
@ -81,19 +81,19 @@ class Player{
|
|||||||
$this->ip = $ip;
|
$this->ip = $ip;
|
||||||
$this->port = $port;
|
$this->port = $port;
|
||||||
$this->itemEnforcement = $this->server->api->getProperty("item-enforcement");
|
$this->itemEnforcement = $this->server->api->getProperty("item-enforcement");
|
||||||
$this->spawnPosition = new Vector3($this->server->spawn["x"], $this->server->spawn["y"], $this->server->spawn["z"]);
|
$this->spawnPosition = $this->server->spawn;
|
||||||
$this->timeout = microtime(true) + 20;
|
$this->timeout = microtime(true) + 20;
|
||||||
$this->inventory = array_fill(0, 36, array(AIR, 0, 0));
|
$this->inventory = array_fill(0, 36, array(AIR, 0, 0));
|
||||||
$this->armor = array_fill(0, 4, array(AIR, 0, 0));
|
$this->armor = array_fill(0, 4, array(AIR, 0, 0));
|
||||||
$this->gamemode = $this->server->gamemode;
|
$this->gamemode = $this->server->gamemode;
|
||||||
$this->level = $this->server->api->level;
|
$this->level = $this->server->api->level->getDefault();
|
||||||
$this->equipment = BlockAPI::getItem(AIR);
|
$this->equipment = BlockAPI::getItem(AIR);
|
||||||
$this->evid[] = $this->server->event("server.tick", array($this, "onTick"));
|
$this->evid[] = $this->server->event("server.tick", array($this, "onTick"));
|
||||||
$this->evid[] = $this->server->event("server.close", array($this, "close"));
|
$this->evid[] = $this->server->event("server.close", array($this, "close"));
|
||||||
console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2);
|
console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setSpawn(Vector3 $pos){
|
public function setSpawn(Position $pos){
|
||||||
$this->spawnPosition = $pos;
|
$this->spawnPosition = $pos;
|
||||||
$this->dataPacket(MC_SET_SPAWN_POSITION, array(
|
$this->dataPacket(MC_SET_SPAWN_POSITION, array(
|
||||||
"x" => (int) $this->spawnPosition->x,
|
"x" => (int) $this->spawnPosition->x,
|
||||||
@ -141,7 +141,7 @@ class Player{
|
|||||||
$z = $Z << 4;
|
$z = $Z << 4;
|
||||||
$y = $Y << 4;
|
$y = $Y << 4;
|
||||||
$MTU = $this->MTU - 16;
|
$MTU = $this->MTU - 16;
|
||||||
$chunk = $this->level->getMiniChunk($X, $Z, $Y, $MTU);
|
$chunk = $this->level->getOrderedMiniChunk($X, $Z, $Y, $MTU);
|
||||||
foreach($chunk as $d){
|
foreach($chunk as $d){
|
||||||
$this->dataPacket(MC_CHUNK_DATA, array(
|
$this->dataPacket(MC_CHUNK_DATA, array(
|
||||||
"x" => $X,
|
"x" => $X,
|
||||||
@ -197,11 +197,13 @@ class Player{
|
|||||||
public function save(){
|
public function save(){
|
||||||
if($this->entity instanceof Entity){
|
if($this->entity instanceof Entity){
|
||||||
$this->data->set("position", array(
|
$this->data->set("position", array(
|
||||||
|
"level" => $this->entity->level->getName(),
|
||||||
"x" => $this->entity->x,
|
"x" => $this->entity->x,
|
||||||
"y" => $this->entity->y,
|
"y" => $this->entity->y,
|
||||||
"z" => $this->entity->z,
|
"z" => $this->entity->z,
|
||||||
));
|
));
|
||||||
$this->data->set("spawn", array(
|
$this->data->set("spawn", array(
|
||||||
|
"level" => $this->entity->level->getName(),
|
||||||
"x" => $this->spawnPosition->x,
|
"x" => $this->spawnPosition->x,
|
||||||
"y" => $this->spawnPosition->y,
|
"y" => $this->spawnPosition->y,
|
||||||
"z" => $this->spawnPosition->z,
|
"z" => $this->spawnPosition->z,
|
||||||
|
@ -27,7 +27,7 @@ the Free Software Foundation, either version 3 of the License, or
|
|||||||
|
|
||||||
class PocketMinecraftServer{
|
class PocketMinecraftServer{
|
||||||
public $tCnt;
|
public $tCnt;
|
||||||
public $version, $invisible, $api, $tickMeasure, $preparedSQL, $seed, $gamemode, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $timePerSecond, $spawn, $entities, $mapDir, $mapName, $map, $levelData, $tileEntities;
|
public $version, $invisible, $api, $tickMeasure, $preparedSQL, $seed, $gamemode, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $timePerSecond;
|
||||||
private $port, $serverip, $database, $interface, $evCnt, $handCnt, $events, $eventsID, $handlers, $serverType, $lastTick;
|
private $port, $serverip, $database, $interface, $evCnt, $handCnt, $events, $eventsID, $handlers, $serverType, $lastTick;
|
||||||
|
|
||||||
private function load(){
|
private function load(){
|
||||||
@ -45,12 +45,9 @@ class PocketMinecraftServer{
|
|||||||
$this->startDatabase();
|
$this->startDatabase();
|
||||||
$this->api = false;
|
$this->api = false;
|
||||||
$this->tCnt = 1;
|
$this->tCnt = 1;
|
||||||
$this->mapDir = false;
|
|
||||||
$this->mapName = false;
|
|
||||||
$this->events = array();
|
$this->events = array();
|
||||||
$this->eventsID = array();
|
$this->eventsID = array();
|
||||||
$this->handlers = array();
|
$this->handlers = array();
|
||||||
$this->map = false;
|
|
||||||
$this->invisible = false;
|
$this->invisible = false;
|
||||||
$this->levelData = false;
|
$this->levelData = false;
|
||||||
$this->difficulty = 1;
|
$this->difficulty = 1;
|
||||||
@ -113,15 +110,15 @@ class PocketMinecraftServer{
|
|||||||
public function startDatabase(){
|
public function startDatabase(){
|
||||||
$this->preparedSQL = new stdClass();
|
$this->preparedSQL = new stdClass();
|
||||||
$this->database = new SQLite3(":memory:");
|
$this->database = new SQLite3(":memory:");
|
||||||
//$this->query("PRAGMA journal_mode = OFF;");
|
$this->query("PRAGMA journal_mode = OFF;");
|
||||||
//$this->query("PRAGMA encoding = \"UTF-8\";");
|
$this->query("PRAGMA encoding = \"UTF-8\";");
|
||||||
//$this->query("PRAGMA secure_delete = OFF;");
|
$this->query("PRAGMA secure_delete = OFF;");
|
||||||
$this->query("CREATE TABLE players (clientID INTEGER PRIMARY KEY, EID NUMERIC, ip TEXT, port NUMERIC, name TEXT UNIQUE COLLATE NOCASE);");
|
$this->query("CREATE TABLE players (clientID INTEGER PRIMARY KEY, EID NUMERIC, ip TEXT, port NUMERIC, name TEXT UNIQUE COLLATE NOCASE);");
|
||||||
$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 entities (EID INTEGER PRIMARY KEY, level TEXT, type NUMERIC, class NUMERIC, name TEXT, x NUMERIC, y NUMERIC, z NUMERIC, yaw NUMERIC, pitch NUMERIC, health NUMERIC);");
|
||||||
$this->query("CREATE TABLE tileentities (ID INTEGER PRIMARY KEY, class TEXT, x NUMERIC, y NUMERIC, z NUMERIC, spawnable NUMERIC);");
|
$this->query("CREATE TABLE tileentities (ID INTEGER PRIMARY KEY, level TEXT, class TEXT, x NUMERIC, y NUMERIC, z NUMERIC, spawnable NUMERIC);");
|
||||||
$this->query("CREATE TABLE actions (ID INTEGER PRIMARY KEY, interval NUMERIC, last NUMERIC, code TEXT, repeat NUMERIC);");
|
$this->query("CREATE TABLE actions (ID INTEGER PRIMARY KEY, interval NUMERIC, last NUMERIC, code TEXT, repeat NUMERIC);");
|
||||||
$this->query("CREATE TABLE handlers (ID INTEGER PRIMARY KEY, name TEXT, priority NUMERIC);");
|
$this->query("CREATE TABLE handlers (ID INTEGER PRIMARY KEY, name TEXT, priority NUMERIC);");
|
||||||
$this->query("CREATE TABLE blockUpdates (x INTEGER, y INTEGER, z INTEGER, delay NUMERIC);");
|
$this->query("CREATE TABLE blockUpdates (level TEXT, x INTEGER, y INTEGER, z INTEGER, delay NUMERIC);");
|
||||||
//$this->query("PRAGMA synchronous = OFF;");
|
//$this->query("PRAGMA synchronous = OFF;");
|
||||||
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT DISTINCT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
|
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT DISTINCT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
|
||||||
$this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (:time - interval);");
|
$this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (:time - interval);");
|
||||||
@ -255,34 +252,6 @@ class PocketMinecraftServer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadMap(){
|
|
||||||
if($this->mapName !== false and trim($this->mapName) !== ""){
|
|
||||||
$this->levelData = unserialize(file_get_contents($this->mapDir."level.dat"));
|
|
||||||
if($this->levelData === false){
|
|
||||||
console("[ERROR] Invalid world data for \"".$this->mapDir."\. Please import the world correctly");
|
|
||||||
$this->close("invalid world data");
|
|
||||||
}
|
|
||||||
$this->time = (int) $this->levelData["Time"];
|
|
||||||
$this->seed = (int) $this->levelData["RandomSeed"];
|
|
||||||
if(isset($this->levelData["SpawnX"])){
|
|
||||||
$this->spawn = array("x" => $this->levelData["SpawnX"], "y" => $this->levelData["SpawnY"], "z" => $this->levelData["SpawnZ"]);
|
|
||||||
}else{
|
|
||||||
$this->levelData["SpawnX"] = $this->spawn["x"];
|
|
||||||
$this->levelData["SpawnY"] = $this->spawn["y"];
|
|
||||||
$this->levelData["SpawnZ"] = $this->spawn["z"];
|
|
||||||
}
|
|
||||||
$this->levelData["Time"] = $this->time;
|
|
||||||
console("[INFO] Preparing level \"".$this->levelData["LevelName"]."\"");
|
|
||||||
$this->map = new ChunkParser();
|
|
||||||
if(!$this->map->loadFile($this->mapDir."chunks.dat")){
|
|
||||||
console("[ERROR] Couldn't load the map \"\x1b[32m".$this->levelData["LevelName"]."\x1b[0m\"!", true, true, 0);
|
|
||||||
$this->map = false;
|
|
||||||
}else{
|
|
||||||
$this->map->loadMap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGamemode(){
|
public function getGamemode(){
|
||||||
switch($this->gamemode){
|
switch($this->gamemode){
|
||||||
case SURVIVAL:
|
case SURVIVAL:
|
||||||
@ -296,131 +265,9 @@ class PocketMinecraftServer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadEntities(){
|
|
||||||
if($this->map !== false){
|
|
||||||
$entities = unserialize(file_get_contents($this->mapDir."entities.dat"));
|
|
||||||
if($entities === false or !is_array($entities)){
|
|
||||||
console("[ERROR] Invalid world data for \"".$this->mapDir."\. Please import the world correctly");
|
|
||||||
$this->close("invalid world data");
|
|
||||||
}
|
|
||||||
foreach($entities as $entity){
|
|
||||||
if(!isset($entity["id"])){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(isset($this->api) and $this->api !== false){
|
|
||||||
if($entity["id"] === 64){ //Item Drop
|
|
||||||
$e = $this->api->entity->add(ENTITY_ITEM, $entity["Item"]["id"], array(
|
|
||||||
"meta" => $entity["Item"]["Damage"],
|
|
||||||
"stack" => $entity["Item"]["Count"],
|
|
||||||
"x" => $entity["Pos"][0],
|
|
||||||
"y" => $entity["Pos"][1],
|
|
||||||
"z" => $entity["Pos"][2],
|
|
||||||
"yaw" => $entity["Rotation"][0],
|
|
||||||
"pitch" => $entity["Rotation"][1],
|
|
||||||
));
|
|
||||||
}elseif($entity["id"] === OBJECT_PAINTING){ //Painting
|
|
||||||
$e = $this->api->entity->add(ENTITY_OBJECT, $entity["id"], $entity);
|
|
||||||
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
|
||||||
$e->setHealth($entity["Health"]);
|
|
||||||
}else{
|
|
||||||
$e = $this->api->entity->add(ENTITY_MOB, $entity["id"], $entity);
|
|
||||||
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
|
|
||||||
$e->setHealth($entity["Health"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$tiles = unserialize(file_get_contents($this->mapDir."tileEntities.dat"));
|
|
||||||
foreach($tiles as $tile){
|
|
||||||
if(!isset($tile["id"])){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$t = $this->api->tileentity->add($tile["id"], $tile["x"], $tile["y"], $tile["z"], $tile);
|
|
||||||
}
|
|
||||||
$this->action(1000000 * 60 * 25, '$this->api->chat->broadcast("Forcing save...");$this->save();');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function save($final = false){
|
|
||||||
if($this->mapName !== false){
|
|
||||||
$this->levelData["Time"] = $this->time;
|
|
||||||
file_put_contents($this->mapDir."level.dat", serialize($this->levelData));
|
|
||||||
$this->map->saveMap($final);
|
|
||||||
$this->trigger("server.save", $final);
|
|
||||||
if(count($this->entities) > 0){
|
|
||||||
$entities = array();
|
|
||||||
foreach($this->entities as $entity){
|
|
||||||
if($entity->class === ENTITY_MOB){
|
|
||||||
$entities[] = array(
|
|
||||||
"id" => $entity->type,
|
|
||||||
"Color" => @$entity->data["Color"],
|
|
||||||
"Sheared" => @$entity->data["Sheared"],
|
|
||||||
"Health" => $entity->health,
|
|
||||||
"Pos" => array(
|
|
||||||
0 => $entity->x,
|
|
||||||
1 => $entity->y,
|
|
||||||
2 => $entity->z,
|
|
||||||
),
|
|
||||||
"Rotation" => array(
|
|
||||||
0 => $entity->yaw,
|
|
||||||
1 => $entity->pitch,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}elseif($entity->class === ENTITY_OBJECT){
|
|
||||||
$entities[] = array(
|
|
||||||
"id" => $entity->type,
|
|
||||||
"TileX" => $entity->x,
|
|
||||||
"TileX" => $entity->y,
|
|
||||||
"TileX" => $entity->z,
|
|
||||||
"Health" => $entity->health,
|
|
||||||
"Motive" => $entity->data["Motive"],
|
|
||||||
"Pos" => array(
|
|
||||||
0 => $entity->x,
|
|
||||||
1 => $entity->y,
|
|
||||||
2 => $entity->z,
|
|
||||||
),
|
|
||||||
"Rotation" => array(
|
|
||||||
0 => $entity->yaw,
|
|
||||||
1 => $entity->pitch,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}elseif($entity->class === ENTITY_ITEM){
|
|
||||||
$entities[] = array(
|
|
||||||
"id" => 64,
|
|
||||||
"Item" => array(
|
|
||||||
"id" => $entity->type,
|
|
||||||
"Damage" => $entity->meta,
|
|
||||||
"Count" => $entity->stack,
|
|
||||||
),
|
|
||||||
"Health" => $entity->health,
|
|
||||||
"Pos" => array(
|
|
||||||
0 => $entity->x,
|
|
||||||
1 => $entity->y,
|
|
||||||
2 => $entity->z,
|
|
||||||
),
|
|
||||||
"Rotation" => array(
|
|
||||||
0 => 0,
|
|
||||||
1 => 0,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_put_contents($this->mapDir."entities.dat", serialize($entities));
|
|
||||||
}
|
|
||||||
if(count($this->tileEntities) > 0){
|
|
||||||
$tiles = array();
|
|
||||||
foreach($this->tileEntities as $tile){
|
|
||||||
$tiles[] = $tile->data;
|
|
||||||
}
|
|
||||||
file_put_contents($this->mapDir."tileEntities.dat", serialize($tiles));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function init(){
|
public function init(){
|
||||||
if($this->mapName !== false and $this->map === false){
|
|
||||||
$this->loadMap();
|
|
||||||
$this->loadEntities();
|
|
||||||
}
|
|
||||||
$this->loadEvents();
|
$this->loadEvents();
|
||||||
declare(ticks=40);
|
declare(ticks=40);
|
||||||
register_tick_function(array($this, "tick"));
|
register_tick_function(array($this, "tick"));
|
||||||
|
@ -92,5 +92,9 @@ if($errors > 0){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***REM_START***/
|
/***REM_START***/
|
||||||
|
require_once(FILE_PATH."/src/math/Vector3.php");
|
||||||
|
require_once(FILE_PATH."/src/world/Position.php");
|
||||||
|
require_once(FILE_PATH."/src/pmf/PMF.php");
|
||||||
|
|
||||||
require_all(FILE_PATH . "src/");
|
require_all(FILE_PATH . "src/");
|
||||||
/***REM_END***/
|
/***REM_END***/
|
@ -25,11 +25,7 @@ the Free Software Foundation, either version 3 of the License, or
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/***REM_START***/
|
abstract class Block extends Position{
|
||||||
require_once(FILE_PATH."/src/math/Vector3.php");
|
|
||||||
/***REM_END***/
|
|
||||||
|
|
||||||
abstract class Block extends Vector3{
|
|
||||||
public static $class = array(
|
public static $class = array(
|
||||||
AIR => "AirBlock",
|
AIR => "AirBlock",
|
||||||
STONE => "StoneBlock",
|
STONE => "StoneBlock",
|
||||||
@ -147,12 +143,12 @@ abstract class Block extends Vector3{
|
|||||||
public $isTransparent = false;
|
public $isTransparent = false;
|
||||||
public $isReplaceable = false;
|
public $isReplaceable = false;
|
||||||
public $isPlaceable = true;
|
public $isPlaceable = true;
|
||||||
public $inWorld = false;
|
public $level = false;
|
||||||
public $hasPhysics = false;
|
public $hasPhysics = false;
|
||||||
public $isLiquid = false;
|
public $isLiquid = false;
|
||||||
public $x;
|
public $x = 0;
|
||||||
public $y;
|
public $y = 0;
|
||||||
public $z;
|
public $z = 0;
|
||||||
|
|
||||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||||
$this->id = (int) $id;
|
$this->id = (int) $id;
|
||||||
@ -173,8 +169,8 @@ abstract class Block extends Vector3{
|
|||||||
return $this->meta & 0x0F;
|
return $this->meta & 0x0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
final public function position(Vector3 $v){
|
final public function position(Position $v){
|
||||||
$this->inWorld = true;
|
$this->level = $v->level;
|
||||||
$this->x = (int) $v->x;
|
$this->x = (int) $v->x;
|
||||||
$this->y = (int) $v->y;
|
$this->y = (int) $v->y;
|
||||||
$this->z = (int) $v->z;
|
$this->z = (int) $v->z;
|
||||||
@ -197,19 +193,27 @@ abstract class Block extends Vector3{
|
|||||||
return $this->breakTime;
|
return $this->breakTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSide($side){
|
||||||
|
$v = parent::getSide($side);
|
||||||
|
if($this->level instanceof Level){
|
||||||
|
return $this->level->getBlock($v);
|
||||||
|
}
|
||||||
|
return $v;
|
||||||
|
}
|
||||||
|
|
||||||
final public function __toString(){
|
final public function __toString(){
|
||||||
return "Block ". $this->name ." (".$this->id.":".$this->meta.")";
|
return "Block ". $this->name ." (".$this->id.":".$this->meta.")";
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract function isBreakable(Item $item, Player $player);
|
abstract function isBreakable(Item $item, Player $player);
|
||||||
|
|
||||||
abstract function onBreak(BlockAPI $level, Item $item, Player $player);
|
abstract function onBreak(Item $item, Player $player);
|
||||||
|
|
||||||
abstract function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz);
|
abstract function place(Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz);
|
||||||
|
|
||||||
abstract function onActivate(BlockAPI $level, Item $item, Player $player);
|
abstract function onActivate(Item $item, Player $player);
|
||||||
|
|
||||||
abstract function onUpdate(BlockAPI $level, $type);
|
abstract function onUpdate($type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***REM_START***/
|
/***REM_START***/
|
||||||
|
@ -30,31 +30,23 @@ class GenericBlock extends Block{
|
|||||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||||
parent::__construct($id, $meta, $name);
|
parent::__construct($id, $meta, $name);
|
||||||
}
|
}
|
||||||
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
|
public function place(Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
|
||||||
if($block->inWorld === true){
|
return $this->level->setBlock($block, $this);
|
||||||
$level->setBlock($block, $this->id, $this->getMetadata());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isBreakable(Item $item, Player $player){
|
public function isBreakable(Item $item, Player $player){
|
||||||
return ($this->breakable);
|
return ($this->breakable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBreak(BlockAPI $level, Item $item, Player $player){
|
public function onBreak(Item $item, Player $player){
|
||||||
if($this->inWorld === true){
|
return $this->level->setBlock($this, BlockAPI::getBlock(AIR, 0));
|
||||||
$level->setBlock($this, AIR, 0);
|
}
|
||||||
return true;
|
|
||||||
}
|
public function onUpdate($type){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(BlockAPI $level, $type){
|
public function onActivate(Item $item, Player $player){
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(BlockAPI $level, Item $item, Player $player){
|
|
||||||
return ($this->isActivable);
|
return ($this->isActivable);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,10 +25,6 @@ the Free Software Foundation, either version 3 of the License, or
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/***REM_START***/
|
|
||||||
require_once(FILE_PATH."/src/pmf/PMF.php");
|
|
||||||
/***REM_END***/
|
|
||||||
|
|
||||||
define("PMF_CURRENT_LEVEL_VERSION", 0x00);
|
define("PMF_CURRENT_LEVEL_VERSION", 0x00);
|
||||||
|
|
||||||
class PMFLevel extends PMF{
|
class PMFLevel extends PMF{
|
||||||
@ -40,6 +36,21 @@ class PMFLevel extends PMF{
|
|||||||
private $chunks = array();
|
private $chunks = array();
|
||||||
private $chunkChange = array();
|
private $chunkChange = array();
|
||||||
|
|
||||||
|
public function getData($index){
|
||||||
|
if(!isset($this->levelData[$index])){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ($this->levelData[$index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setData($index, $data){
|
||||||
|
if(!isset($this->levelData[$index])){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->levelData[$index] = $data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function __construct($file, $blank = false){
|
public function __construct($file, $blank = false){
|
||||||
if(is_array($blank)){
|
if(is_array($blank)){
|
||||||
$this->create($file, 0);
|
$this->create($file, 0);
|
||||||
@ -62,8 +73,9 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createBlank(){
|
public function saveData($locationTable = true){
|
||||||
$this->levelData["version"] = PMF_CURRENT_LEVEL_VERSION;
|
$this->levelData["version"] = PMF_CURRENT_LEVEL_VERSION;
|
||||||
|
@ftruncate($this->fp, 5);
|
||||||
$this->seek(5);
|
$this->seek(5);
|
||||||
$this->write(chr($this->levelData["version"]));
|
$this->write(chr($this->levelData["version"]));
|
||||||
$this->write(Utils::writeShort(strlen($this->levelData["name"])).$this->levelData["name"]);
|
$this->write(Utils::writeShort(strlen($this->levelData["name"])).$this->levelData["name"]);
|
||||||
@ -74,11 +86,20 @@ class PMFLevel extends PMF{
|
|||||||
$this->write(Utils::writeFloat($this->levelData["spawnZ"]));
|
$this->write(Utils::writeFloat($this->levelData["spawnZ"]));
|
||||||
$this->write(chr($this->levelData["width"]));
|
$this->write(chr($this->levelData["width"]));
|
||||||
$this->write(chr($this->levelData["height"]));
|
$this->write(chr($this->levelData["height"]));
|
||||||
$this->write(gzdeflate("", 9));
|
$extra = gzdeflate($this->levelData["extra"], 9);
|
||||||
|
$this->write(Utils::writeShort(strlen($extra)).$extra);
|
||||||
|
$this->payloadOffset = ftell($this->fp);
|
||||||
|
|
||||||
|
if($locationTable !== false){
|
||||||
|
$this->writeLocationTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createBlank(){
|
||||||
|
$this->saveData(false);
|
||||||
$this->locationTable = array();
|
$this->locationTable = array();
|
||||||
$cnt = pow($this->levelData["width"], 2);
|
$cnt = pow($this->levelData["width"], 2);
|
||||||
@mkdir(dirname($this->file)."/chunks/", 0755);
|
@mkdir(dirname($this->file)."/chunks/", 0755);
|
||||||
$this->payloadOffset = ftell($this->fp);
|
|
||||||
for($index = 0; $index < $cnt; ++$index){
|
for($index = 0; $index < $cnt; ++$index){
|
||||||
$this->chunks[$index] = false;
|
$this->chunks[$index] = false;
|
||||||
$this->chunkChange[$index] = false;
|
$this->chunkChange[$index] = false;
|
||||||
@ -154,6 +175,15 @@ class PMFLevel extends PMF{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function writeLocationTable(){
|
||||||
|
$cnt = pow($this->levelData["width"], 2);
|
||||||
|
@ftruncate($this->fp, $this->payloadOffset);
|
||||||
|
$this->seek($this->payloadOffset);
|
||||||
|
for($index = 0; $index < $cnt; ++$index){
|
||||||
|
$this->write(Utils::writeShort($this->locationTable[$index]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function getChunkPath($X, $Z){
|
private function getChunkPath($X, $Z){
|
||||||
return dirname($this->file)."/chunks/".$Z.".".$X.".pmc";
|
return dirname($this->file)."/chunks/".$Z.".".$X.".pmc";
|
||||||
}
|
}
|
||||||
@ -186,6 +216,18 @@ class PMFLevel extends PMF{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function unloadChunk($X, $Z, $save = true){
|
||||||
|
$X = (int) $X;
|
||||||
|
$Z = (int) $Z;
|
||||||
|
if($this->isChunkLoaded($X, $Z)){
|
||||||
|
return false;
|
||||||
|
}elseif($save !== false){
|
||||||
|
$this->saveChunk($X, $Z);
|
||||||
|
}
|
||||||
|
unset($this->chunks[$index], $this->chunkChange[$index]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public function isChunkLoaded($X, $Z){
|
public function isChunkLoaded($X, $Z){
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = $this->getIndex($X, $Z);
|
||||||
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
if(!isset($this->chunks[$index]) or $this->chunks[$index] === false){
|
||||||
@ -205,9 +247,9 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getBlock($x, $y, $z){
|
public function getBlock($x, $y, $z){
|
||||||
$X = $x << 4;
|
$X = $x >> 4;
|
||||||
$Z = $z << 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y << 4;
|
$Y = $y >> 4;
|
||||||
if($X >= 32 or $Z >= 32){
|
if($X >= 32 or $Z >= 32){
|
||||||
return array(AIR, 0);
|
return array(AIR, 0);
|
||||||
}
|
}
|
||||||
@ -222,8 +264,8 @@ class PMFLevel extends PMF{
|
|||||||
$aX = $x - ($X << 4);
|
$aX = $x - ($X << 4);
|
||||||
$aZ = $z - ($Z << 4);
|
$aZ = $z - ($Z << 4);
|
||||||
$aY = $y - ($Y << 4);
|
$aY = $y - ($Y << 4);
|
||||||
$bindex = $aY + $aZ << 5 + $aX << 9;
|
$bindex = $aY + ($aX << 5) + ($aZ << 9);
|
||||||
$mindex = $aY >> 1 + 16 + $aZ << 5 + $aX << 9;
|
$mindex = ($aY >> 1) + 16 + ($aX << 5) + ($aZ << 9);
|
||||||
$b = ord($this->chunks[$index][$Y]{$bindex});
|
$b = ord($this->chunks[$index][$Y]{$bindex});
|
||||||
$m = ord($this->chunks[$index][$Y]{$mindex});
|
$m = ord($this->chunks[$index][$Y]{$mindex});
|
||||||
if(($y & 1) === 0){
|
if(($y & 1) === 0){
|
||||||
@ -245,11 +287,11 @@ class PMFLevel extends PMF{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getMiniChunk($X, $Z, $Y){
|
public function getMiniChunk($X, $Z, $Y){
|
||||||
if($this->isChunkLoaded($X, $Z) === false){
|
if($this->loadChunk($X, $Z) === false){
|
||||||
return str_repeat("\x00", 8192);
|
return str_repeat("\x00", 8192);
|
||||||
}
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = $this->getIndex($X, $Z);
|
||||||
if(!isset($this->chunks[$index][$Y])){
|
if($this->chunks[$index][$Y] === false){
|
||||||
return str_repeat("\x00", 8192);
|
return str_repeat("\x00", 8192);
|
||||||
}
|
}
|
||||||
return $this->chunks[$index][$Y];
|
return $this->chunks[$index][$Y];
|
||||||
@ -259,16 +301,20 @@ class PMFLevel extends PMF{
|
|||||||
if($this->isChunkLoaded($X, $Z) === false){
|
if($this->isChunkLoaded($X, $Z) === false){
|
||||||
$this->loadChunk($X, $Z);
|
$this->loadChunk($X, $Z);
|
||||||
}
|
}
|
||||||
|
if(strlen($data) !== 8192){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$index = $this->getIndex($X, $Z);
|
$index = $this->getIndex($X, $Z);
|
||||||
$this->chunks[$index][$Y] = substr($data, 0, 8192);
|
$this->chunks[$index][$Y] = $data;
|
||||||
|
$this->chunkChange[$index][$Y] = 8192;
|
||||||
$this->locationTable[$index][0] |= 1 << $Y;
|
$this->locationTable[$index][0] |= 1 << $Y;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBlock($x, $y, $z, $block, $meta = 0){
|
public function setBlock($x, $y, $z, $block, $meta = 0){
|
||||||
$X = $x << 4;
|
$X = $x >> 4;
|
||||||
$Z = $z << 4;
|
$Z = $z >> 4;
|
||||||
$Y = $y << 4;
|
$Y = $y >> 4;
|
||||||
$block &= 0xFF;
|
$block &= 0xFF;
|
||||||
$meta &= 0x0F;
|
$meta &= 0x0F;
|
||||||
if($X >= 32 or $Z >= 32){
|
if($X >= 32 or $Z >= 32){
|
||||||
@ -285,8 +331,8 @@ class PMFLevel extends PMF{
|
|||||||
$aX = $x - ($X << 4);
|
$aX = $x - ($X << 4);
|
||||||
$aZ = $z - ($Z << 4);
|
$aZ = $z - ($Z << 4);
|
||||||
$aY = $y - ($Y << 4);
|
$aY = $y - ($Y << 4);
|
||||||
$bindex = $aY + $aZ << 5 + $aX << 9;
|
$bindex = $aY + ($aX << 5) + ($aZ << 9);
|
||||||
$mindex = $aY >> 1 + 16 + $aZ << 5 + $aX << 9;
|
$mindex = ($aY >> 1) + 16 + ($aX << 5) + ($aZ << 9);
|
||||||
$old_b = $this->chunks[$index][$Y]{$bindex};
|
$old_b = $this->chunks[$index][$Y]{$bindex};
|
||||||
$old_m = ord($this->map[$X][$Z][1][$index]{$y >> 1});
|
$old_m = ord($this->map[$X][$Z][1][$index]{$y >> 1});
|
||||||
if(($y & 1) === 0){
|
if(($y & 1) === 0){
|
||||||
@ -319,16 +365,24 @@ class PMFLevel extends PMF{
|
|||||||
$chunk = @gzopen($this->getChunkPath($X, $Z), "wb9");
|
$chunk = @gzopen($this->getChunkPath($X, $Z), "wb9");
|
||||||
$bitmap = 0;
|
$bitmap = 0;
|
||||||
for($Y = 0; $Y < $this->levelData["height"]; ++$Y){
|
for($Y = 0; $Y < $this->levelData["height"]; ++$Y){
|
||||||
if($this->chunks[$index][$Y] !== false and !$this->isMiniChunkEmpty($X, $Z, $Y)){
|
if($this->chunks[$index][$Y] !== false and ((isset($this->chunkChange[$index][$Y]) and $this->chunkChange[$index][$Y] === 0) or !$this->isMiniChunkEmpty($X, $Z, $Y))){
|
||||||
gzwrite($chunk, $this->chunks[$index][$Y]);
|
gzwrite($chunk, $this->chunks[$index][$Y]);
|
||||||
$bitmap |= 1 << $Y;
|
$bitmap |= 1 << $Y;
|
||||||
}else{
|
}else{
|
||||||
$this->chunks[$index][$Y] = false;
|
$this->chunks[$index][$Y] = false;
|
||||||
}
|
}
|
||||||
|
$this->chunkChange[$index][$Y] = 0;
|
||||||
}
|
}
|
||||||
$this->locationTable[$index][0] = $bitmap;
|
$this->locationTable[$index][0] = $bitmap;
|
||||||
$this->seek($this->payloadOffset + ($index << 1));
|
$this->seek($this->payloadOffset + ($index << 1));
|
||||||
$this->write(Utils::writeShort($this->locationTable[$index][0]));
|
$this->write(Utils::writeShort($this->locationTable[$index][0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function doSaveRound(){
|
||||||
|
foreach($this->chunks as $index => $chunk){
|
||||||
|
$this->getXZ($index, $X, $Z);
|
||||||
|
$this->saveChunk($X, $Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -45,7 +45,7 @@ define("ENTITY_OBJECT", 2);
|
|||||||
|
|
||||||
define("ENTITY_ITEM", 3);
|
define("ENTITY_ITEM", 3);
|
||||||
|
|
||||||
class Entity extends stdClass{
|
class Entity extends Position{
|
||||||
public $age;
|
public $age;
|
||||||
public $air;
|
public $air;
|
||||||
public $spawntime;
|
public $spawntime;
|
||||||
@ -74,7 +74,9 @@ class Entity extends stdClass{
|
|||||||
private $tickCounter;
|
private $tickCounter;
|
||||||
private $speedMeasure = array(0, 0, 0, 0, 0);
|
private $speedMeasure = array(0, 0, 0, 0, 0);
|
||||||
private $server;
|
private $server;
|
||||||
function __construct($eid, $class, $type = 0, $data = array()){
|
public $level;
|
||||||
|
function __construct(Level $level, $eid, $class, $type = 0, $data = array()){
|
||||||
|
$this->level = $level;
|
||||||
$this->fallY = false;
|
$this->fallY = false;
|
||||||
$this->fallStart = false;
|
$this->fallStart = false;
|
||||||
$this->server = ServerAPI::request();
|
$this->server = ServerAPI::request();
|
||||||
@ -97,7 +99,7 @@ class Entity extends stdClass{
|
|||||||
$this->closed = false;
|
$this->closed = false;
|
||||||
$this->name = "";
|
$this->name = "";
|
||||||
$this->tickCounter = 0;
|
$this->tickCounter = 0;
|
||||||
$this->server->query("INSERT OR REPLACE INTO entities (EID, type, class, health) VALUES (".$this->eid.", ".$this->type.", ".$this->class.", ".$this->health.");");
|
$this->server->query("INSERT OR REPLACE INTO entities (EID, level, type, class, health) VALUES (".$this->eid.", '".$this->level->getName()."', ".$this->type.", ".$this->class.", ".$this->health.");");
|
||||||
$this->x = isset($this->data["x"]) ? $this->data["x"]:0;
|
$this->x = isset($this->data["x"]) ? $this->data["x"]:0;
|
||||||
$this->y = isset($this->data["y"]) ? $this->data["y"]:0;
|
$this->y = isset($this->data["y"]) ? $this->data["y"]:0;
|
||||||
$this->z = isset($this->data["z"]) ? $this->data["z"]:0;
|
$this->z = isset($this->data["z"]) ? $this->data["z"]:0;
|
||||||
@ -107,7 +109,7 @@ class Entity extends stdClass{
|
|||||||
$this->speed = 0;
|
$this->speed = 0;
|
||||||
$this->yaw = isset($this->data["yaw"]) ? $this->data["yaw"]:0;
|
$this->yaw = isset($this->data["yaw"]) ? $this->data["yaw"]:0;
|
||||||
$this->pitch = isset($this->data["pitch"]) ? $this->data["pitch"]: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);
|
$this->position = array("level" => $this->level, "x" => &$this->x, "y" => &$this->y, "z" => &$this->z, "yaw" => &$this->yaw, "pitch" => &$this->pitch);
|
||||||
switch($this->class){
|
switch($this->class){
|
||||||
case ENTITY_PLAYER:
|
case ENTITY_PLAYER:
|
||||||
$this->player = $this->data["player"];
|
$this->player = $this->data["player"];
|
||||||
@ -175,7 +177,7 @@ class Entity extends stdClass{
|
|||||||
|
|
||||||
private function spawnDrops(){
|
private function spawnDrops(){
|
||||||
foreach($this->getDrops() as $drop){
|
foreach($this->getDrops() as $drop){
|
||||||
$this->server->api->block->drop(new Vector3($this->x, $this->y, $this->z), BlockAPI::getItem($drop[0] & 0xFFFF, $drop[1] & 0xFFFF, $drop[2] & 0xFF), true);
|
$this->server->api->block->drop($this, BlockAPI::getItem($drop[0] & 0xFFFF, $drop[1] & 0xFFFF, $drop[2] & 0xFF), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,8 +188,8 @@ class Entity extends stdClass{
|
|||||||
$this->close(); //Despawn timer
|
$this->close(); //Despawn timer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(($time - $this->spawntime) >= 2){
|
if(($time - $this->spawntime) >= 0.6){ //TODO: set this on Player class, updates things when it moves
|
||||||
$player = $this->server->query("SELECT EID FROM entities WHERE class = ".ENTITY_PLAYER." AND abs(x - {$this->x}) <= 1.5 AND abs(y - {$this->y}) <= 1.5 AND abs(z - {$this->z}) <= 1.5 LIMIT 1;", true);
|
$player = $this->server->query("SELECT EID FROM entities WHERE level = '".$this->level->getName()."' AND class = ".ENTITY_PLAYER." AND abs(x - {$this->x}) <= 1.5 AND abs(y - {$this->y}) <= 1.5 AND abs(z - {$this->z}) <= 1.5 LIMIT 1;", true);
|
||||||
$player = $this->server->api->entity->get($player["EID"]);
|
$player = $this->server->api->entity->get($player["EID"]);
|
||||||
if($player instanceof Entity){
|
if($player instanceof Entity){
|
||||||
$player = $player->player;
|
$player = $player->player;
|
||||||
@ -439,7 +441,7 @@ class Entity extends stdClass{
|
|||||||
if(!($player instanceof Player)){
|
if(!($player instanceof Player)){
|
||||||
$player = $this->server->api->player->get($player);
|
$player = $this->server->api->player->get($player);
|
||||||
}
|
}
|
||||||
if($player->eid === $this->eid or $this->closed !== false){
|
if($player->eid === $this->eid or $this->closed !== false or $player->level !== $this->level){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch($this->class){
|
switch($this->class){
|
||||||
@ -530,17 +532,23 @@ class Entity extends stdClass{
|
|||||||
$this->server->query("UPDATE entities SET pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
$this->server->query("UPDATE entities SET pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCoords($x, $y, $z){
|
public function setCoords(Vector3 $pos){
|
||||||
$this->x = $x;
|
if($pos instanceof Position){
|
||||||
$this->y = $y;
|
$this->level = $pos->level;
|
||||||
$this->z = $z;
|
$this->server->query("UPDATE entities SET level = '".$this->level->getName()."' WHERE EID = ".$this->eid.";");
|
||||||
|
}
|
||||||
|
$this->x = $pos->x;
|
||||||
|
$this->y = $pos->y;
|
||||||
|
$this->z = $pos->z;
|
||||||
|
$this->yaw = $yaw;
|
||||||
|
$this->pitch = $pitch;
|
||||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE EID = ".$this->eid.";");
|
$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){
|
public function move(Vector3 $pos, $yaw = 0, $pitch = 0){
|
||||||
$this->x += $x;
|
$this->x += $pos->x;
|
||||||
$this->y += $y;
|
$this->y += $pos->y;
|
||||||
$this->z += $z;
|
$this->z += $pos->z;
|
||||||
$this->yaw += $yaw;
|
$this->yaw += $yaw;
|
||||||
$this->yaw %= 360;
|
$this->yaw %= 360;
|
||||||
$this->pitch += $pitch;
|
$this->pitch += $pitch;
|
||||||
@ -548,17 +556,20 @@ class Entity extends stdClass{
|
|||||||
$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.";");
|
$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){
|
public function setPosition(Vector3 $pos, $yaw, $pitch){
|
||||||
$this->x = $x;
|
if($pos instanceof Position){
|
||||||
$this->y = $y;
|
$this->level = $pos->level;
|
||||||
$this->z = $z;
|
$this->server->query("UPDATE entities SET level = '".$this->level->getName()."' WHERE EID = ".$this->eid.";");
|
||||||
|
}
|
||||||
|
$this->x = $pos->x;
|
||||||
|
$this->y = $pos->y;
|
||||||
|
$this->z = $pos->z;
|
||||||
$this->yaw = $yaw;
|
$this->yaw = $yaw;
|
||||||
$this->pitch = $pitch;
|
$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.";");
|
$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 inBlock($x, $y, $z, $radius = 0.8){
|
public function inBlock(Vector3 $block, $radius = 0.8){
|
||||||
$block = new Vector3($x, $y, $z);
|
|
||||||
$me = new Vector3($this->x - 0.5, $this->y, $this->z - 0.5);
|
$me = new Vector3($this->x - 0.5, $this->y, $this->z - 0.5);
|
||||||
if(($y == ((int) $this->y) or $y == (((int) $this->y) + 1)) and $block->maxPlainDistance($me) < $radius){
|
if(($y == ((int) $this->y) or $y == (((int) $this->y) + 1)) and $block->maxPlainDistance($me) < $radius){
|
||||||
return true;
|
return true;
|
||||||
@ -566,8 +577,7 @@ class Entity extends stdClass{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function touchingBlock($x, $y, $z, $radius = 0.9){
|
public function touchingBlock(Vector3 $block, $radius = 0.9){
|
||||||
$block = new Vector3($x, $y, $z);
|
|
||||||
$me = new Vector3($this->x - 0.5, $this->y, $this->z - 0.5);
|
$me = new Vector3($this->x - 0.5, $this->y, $this->z - 0.5);
|
||||||
if(($y == (((int) $this->y) - 1) or $y == ((int) $this->y) or $y == (((int) $this->y) + 1)) and $block->maxPlainDistance($me) < $radius){
|
if(($y == (((int) $this->y) - 1) or $y == ((int) $this->y) or $y == (((int) $this->y) + 1)) and $block->maxPlainDistance($me) < $radius){
|
||||||
return true;
|
return true;
|
||||||
|
151
src/world/Level.php
Normal file
151
src/world/Level.php
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
-
|
||||||
|
/ \
|
||||||
|
/ \
|
||||||
|
/ PocketMine \
|
||||||
|
/ MP \
|
||||||
|
|\ @shoghicp /|
|
||||||
|
|. \ / .|
|
||||||
|
| .. \ / .. |
|
||||||
|
| .. | .. |
|
||||||
|
| .. | .. |
|
||||||
|
\ | /
|
||||||
|
\ | /
|
||||||
|
\ | /
|
||||||
|
\ | /
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Level{
|
||||||
|
public $entities, $tileEntities;
|
||||||
|
private $level, $time, $startCheck, $startTime, $server;
|
||||||
|
|
||||||
|
public function __construct(PMFLevel $level, Config $entities, Config $tileEntities){
|
||||||
|
$this->server = ServerAPI::request();
|
||||||
|
$this->level = $level;
|
||||||
|
$this->entities = $entities;
|
||||||
|
$this->tileEntities = $tileEntities;
|
||||||
|
$this->startTime = $this->time = (int) $this->level->getData("time");
|
||||||
|
$this->startCheck = microtime(true);
|
||||||
|
$this->server->schedule(15, array($this, "checkThings"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct(){
|
||||||
|
$this->save();
|
||||||
|
unset($this->level);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save(){
|
||||||
|
$this->level->setData("time", $this->time);
|
||||||
|
$this->level->doSaveRound();
|
||||||
|
$this->level->saveData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBlock(Vector3 $pos){
|
||||||
|
if(($pos instanceof Position) and $pos->level !== $this){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$b = $this->level->getBlock($pos->x, $pos->y, $pos->z);
|
||||||
|
return BlockAPI::get($b[0], $b[1], new Position($pos->x, $pos->y, $pos->z, $this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBlock(Position $pos, Block $block, $update = true, $tiles = false){
|
||||||
|
if((($pos instanceof Position) and $pos->level !== $this) or $pos->x < 0 or $pos->y < 0 or $pos->z < 0){
|
||||||
|
return false;
|
||||||
|
}elseif($this->server->api->dhandle("block.change", array(
|
||||||
|
"position" => $pos,
|
||||||
|
"block" => $block,
|
||||||
|
)) !== false){
|
||||||
|
$ret = $this->level->setBlock($pos->x, $pos->y, $pos->z, $block->getID(), $block->getMetadata());
|
||||||
|
if($update === true){
|
||||||
|
$this->server->api->block->blockUpdate($pos, BLOCK_UPDATE_NORMAL); //????? water?
|
||||||
|
$this->server->api->block->blockUpdateAround($pos, BLOCK_UPDATE_NORMAL);
|
||||||
|
}
|
||||||
|
if($tiles === true){
|
||||||
|
if(($t = $this->server->api->tileentity->get($pos)) !== false){
|
||||||
|
$t[0]->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMiniChunk($X, $Z){
|
||||||
|
return $this->level->getMiniChunk($X, $Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMiniChunk($X, $Z, $data){
|
||||||
|
return $this->level->setMiniChunk($X, $Z, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadChunk($X, $Z){
|
||||||
|
return $this->level->loadChunk($X, $Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unloadChunk($X, $Z){
|
||||||
|
return $this->level->unloadChunk($X, $Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOrderedMiniChunk($X, $Z, $Y, $MTU){
|
||||||
|
$raw = $this->map->getMiniChunk($X, $Z, $Y);
|
||||||
|
$ordered = array();
|
||||||
|
$i = 0;
|
||||||
|
$ordered[$i] = "";
|
||||||
|
$cnt = 0;
|
||||||
|
$flag = chr(1 << $Y);
|
||||||
|
for($j = 0; $j < 256; ++$j){
|
||||||
|
if((strlen($ordered[$i]) + 16 + 8 + 1) > $MTU){
|
||||||
|
++$i;
|
||||||
|
$ordered[$i] = str_repeat("\x00", $cnt);
|
||||||
|
}
|
||||||
|
$index = $j << 5;
|
||||||
|
$ordered[$i] .= $flag;
|
||||||
|
$ordered[$i] .= substr($raw, $index, 16);
|
||||||
|
$ordered[$i] .= substr($raw, $index + 16, 8);
|
||||||
|
++$cnt;
|
||||||
|
}
|
||||||
|
return $ordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSpawn(){
|
||||||
|
return new Position($this->level->getData("spawnX"), $this->level->getData("spawnY"), $this->level->getData("spawnZ"), $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSpawn(Vector3 $pos){
|
||||||
|
$this->level->setData("spawnX", $pos->x);
|
||||||
|
$this->level->setData("spawnY", $pos->y);
|
||||||
|
$this->level->setData("spawnZ", $pos->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTime(){
|
||||||
|
return ($this->time);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(){
|
||||||
|
return $this->level->getData("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTime($time){
|
||||||
|
$this->startTime = $this->time = (int) $time;
|
||||||
|
$this->startCheck = microtime(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkThings(){
|
||||||
|
$now = microtime(true);
|
||||||
|
$this->time = $this->startTime + ($now - $this->startCheck) * 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSeed(){
|
||||||
|
return (int) $this->level->getData("seed");
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,8 @@ class LevelImport{
|
|||||||
|
|
||||||
public function import(){
|
public function import(){
|
||||||
if(file_exists($this->path."tileEntities.dat")){ //OldPM
|
if(file_exists($this->path."tileEntities.dat")){ //OldPM
|
||||||
|
$level = unserialize(file_get_contents($this->path."level.dat"));
|
||||||
|
console("[INFO] Importing OldPM level \"".$level["LevelName"]."\" to PMF format");
|
||||||
$entities = new Config($this->path."entities.yml", CONFIG_YAML, unserialize(file_get_contents($this->path."entities.dat")));
|
$entities = new Config($this->path."entities.yml", CONFIG_YAML, unserialize(file_get_contents($this->path."entities.dat")));
|
||||||
$entities->save();
|
$entities->save();
|
||||||
$tileEntities = new Config($this->path."tileEntities.yml", CONFIG_YAML, unserialize(file_get_contents($this->path."tileEntities.dat")));
|
$tileEntities = new Config($this->path."tileEntities.yml", CONFIG_YAML, unserialize(file_get_contents($this->path."tileEntities.dat")));
|
||||||
@ -43,9 +45,8 @@ class LevelImport{
|
|||||||
if($level["LevelName"] == ""){
|
if($level["LevelName"] == ""){
|
||||||
$level["LevelName"] = "world".time();
|
$level["LevelName"] = "world".time();
|
||||||
}
|
}
|
||||||
console("[DEBUG] Importing map \"".$level["LevelName"]."\" gamemode ".$level["GameType"]." with seed ".$level["RandomSeed"], true, true, 2);
|
console("[INFO] Importing Pocket level \"".$level["LevelName"]."\" to PMF format");
|
||||||
unset($level["Player"]);
|
unset($level["Player"]);
|
||||||
$lvName = $level["LevelName"]."/";
|
|
||||||
$entities = parseNBTData($nbt->loadFile($this->path."entities.dat"));
|
$entities = parseNBTData($nbt->loadFile($this->path."entities.dat"));
|
||||||
if(!isset($entities["TileEntities"])){
|
if(!isset($entities["TileEntities"])){
|
||||||
$entities["TileEntities"] = array();
|
$entities["TileEntities"] = array();
|
||||||
@ -56,6 +57,8 @@ class LevelImport{
|
|||||||
$entities->save();
|
$entities->save();
|
||||||
$tileEntities = new Config($this->path."tileEntities.yml", CONFIG_YAML, $tileEntities);
|
$tileEntities = new Config($this->path."tileEntities.yml", CONFIG_YAML, $tileEntities);
|
||||||
$tileEntities->save();
|
$tileEntities->save();
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pmf = new PMFLevel($this->path."level.pmf", array(
|
$pmf = new PMFLevel($this->path."level.pmf", array(
|
||||||
@ -65,6 +68,7 @@ class LevelImport{
|
|||||||
"spawnX" => $level["SpawnX"],
|
"spawnX" => $level["SpawnX"],
|
||||||
"spawnY" => $level["SpawnY"],
|
"spawnY" => $level["SpawnY"],
|
||||||
"spawnZ" => $level["SpawnZ"],
|
"spawnZ" => $level["SpawnZ"],
|
||||||
|
"extra" => "",
|
||||||
"width" => 16,
|
"width" => 16,
|
||||||
"height" => 8
|
"height" => 8
|
||||||
));
|
));
|
||||||
@ -99,16 +103,17 @@ class LevelImport{
|
|||||||
}
|
}
|
||||||
$pmf->saveChunk($X, $Z);
|
$pmf->saveChunk($X, $Z);
|
||||||
}
|
}
|
||||||
|
console("[NOTICE] Importing level ".ceil(($Z + 1)/0.16)."%");
|
||||||
}
|
}
|
||||||
$chunks->map = null;
|
$chunks->map = null;
|
||||||
$chunks = null;
|
$chunks = null;
|
||||||
/*@unlink($this->path."level.dat");
|
@unlink($this->path."level.dat");
|
||||||
@unlink($this->path."level.dat_old");
|
@unlink($this->path."level.dat_old");
|
||||||
@unlink($this->path."player.dat");
|
@unlink($this->path."player.dat");
|
||||||
@unlink($this->path."entities.dat");
|
@unlink($this->path."entities.dat");
|
||||||
@unlink($this->path."chunks.dat");
|
@unlink($this->path."chunks.dat");
|
||||||
@unlink($this->path."chunks.dat.gz");
|
@unlink($this->path."chunks.dat.gz");
|
||||||
@unlink($this->path."tileEntities.dat");*/
|
@unlink($this->path."tileEntities.dat");
|
||||||
unset($chunks, $level, $entities, $tileEntities, $nbt);
|
unset($chunks, $level, $entities, $tileEntities, $nbt);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,17 @@ the Free Software Foundation, either version 3 of the License, or
|
|||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
class BlockIterator implements Iterator{
|
|
||||||
|
|
||||||
|
class Position{
|
||||||
|
public $level;
|
||||||
|
|
||||||
}*/
|
public function __construct($x = 0, $y = 0, $z = 0, Level $level){
|
||||||
|
parent::__construct($x, $y, $z);
|
||||||
|
$this->level = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(){
|
||||||
|
return "Position(level=".$this->level->getName().",x=".$this->x.",y=".$this->y.",z=".$this->z.")";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -32,7 +32,7 @@ define("TILE_CHEST", "Chest");
|
|||||||
define("TILE_FURNACE", "Furnace");
|
define("TILE_FURNACE", "Furnace");
|
||||||
define("FURNACE_SLOTS", 3);
|
define("FURNACE_SLOTS", 3);
|
||||||
|
|
||||||
class TileEntity extends stdClass{
|
class TileEntity extends Position{
|
||||||
public $name;
|
public $name;
|
||||||
public $normal;
|
public $normal;
|
||||||
public $id;
|
public $id;
|
||||||
@ -45,8 +45,9 @@ class TileEntity extends stdClass{
|
|||||||
public $metadata;
|
public $metadata;
|
||||||
public $closed;
|
public $closed;
|
||||||
private $server;
|
private $server;
|
||||||
function __construct($id, $class, $x, $y, $z, $data = array()){
|
function __construct(Level $level, $id, $class, $x, $y, $z, $data = array()){
|
||||||
$this->server = ServerAPI::request();
|
$this->server = ServerAPI::request();
|
||||||
|
$this->level = $level;
|
||||||
$this->normal = true;
|
$this->normal = true;
|
||||||
$this->class = $class;
|
$this->class = $class;
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
@ -59,7 +60,7 @@ class TileEntity extends stdClass{
|
|||||||
$this->x = (int) $x;
|
$this->x = (int) $x;
|
||||||
$this->y = (int) $y;
|
$this->y = (int) $y;
|
||||||
$this->z = (int) $z;
|
$this->z = (int) $z;
|
||||||
$this->server->query("INSERT OR REPLACE INTO tileentities (ID, class, x, y, z) VALUES (".$this->id.", '".$this->class."', ".$this->x.", ".$this->y.", ".$this->z.");");
|
$this->server->query("INSERT OR REPLACE INTO tileentities (ID, level, class, x, y, z) VALUES (".$this->id.", '".$this->level->getName()."', '".$this->class."', ".$this->x.", ".$this->y.", ".$this->z.");");
|
||||||
switch($this->class){
|
switch($this->class){
|
||||||
case TILE_SIGN:
|
case TILE_SIGN:
|
||||||
$this->server->query("UPDATE tileentities SET spawnable = 1 WHERE ID = ".$this->id.";");
|
$this->server->query("UPDATE tileentities SET spawnable = 1 WHERE ID = ".$this->id.";");
|
||||||
@ -148,7 +149,7 @@ class TileEntity extends stdClass{
|
|||||||
public function close(){
|
public function close(){
|
||||||
if($this->closed === false){
|
if($this->closed === false){
|
||||||
$this->closed = true;
|
$this->closed = true;
|
||||||
$this->server->api->entity->remove($this->eid);
|
$this->server->api->tileentity->remove($this->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,17 +161,16 @@ class TileEntity extends stdClass{
|
|||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setName($name){
|
|
||||||
$this->name = $name;
|
|
||||||
$this->server->query("UPDATE entities SET name = '".str_replace("'", "", $this->name)."' WHERE EID = ".$this->eid.";");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public function setPosition(Vector3 $pos){
|
||||||
public function setPosition($x, $y, $z){
|
if($pos instanceof Position){
|
||||||
$this->x = (int) $x;
|
$this->level = $pos->level;
|
||||||
$this->y = (int) $y;
|
$this->server->query("UPDATE tileentities SET level = '".$this->level->getName()."' WHERE ID = ".$this->id.";");
|
||||||
$this->z = (int) $z;
|
}
|
||||||
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE EID = ".$this->eid.";");
|
$this->x = (int) $pos->x;
|
||||||
|
$this->y = (int) $pos->y;
|
||||||
|
$this->z = (int) $pos->z;
|
||||||
|
$this->server->query("UPDATE tileentities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE ID = ".$this->id.";");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
-
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ PocketMine \
|
|
||||||
/ MP \
|
|
||||||
|\ @shoghicp /|
|
|
||||||
|. \ / .|
|
|
||||||
| .. \ / .. |
|
|
||||||
| .. | .. |
|
|
||||||
| .. | .. |
|
|
||||||
\ | /
|
|
||||||
\ | /
|
|
||||||
\ | /
|
|
||||||
\ | /
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
class NormalGenerator{
|
|
||||||
private $config, $spawn, $structure;
|
|
||||||
public function __construct($seed){
|
|
||||||
$this->config = array(
|
|
||||||
"seed" => (int) $seed,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set($name, $value){
|
|
||||||
$this->config[$name] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function init(){
|
|
||||||
$this->spawn = array(128, 128, 128);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSpawn(){
|
|
||||||
return $this->spawn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getColumn($x, $z){
|
|
||||||
$x = (int) $x;
|
|
||||||
$z = (int) $z;
|
|
||||||
$column = $this->structure;
|
|
||||||
if(floor(sqrt(pow($x - $this->spawn[0], 2) + pow($z - $this->spawn[2], 2))) <= $this->config["spawn-radius"]){
|
|
||||||
$column[0]{strlen($column[0])-1} = chr($this->config["spawn-surface"]);
|
|
||||||
}
|
|
||||||
if(($x % 8) === 0 and ($z % 8) === 0 and $this->config["torches"] == "1"){
|
|
||||||
$column[0] .= chr(50);
|
|
||||||
}
|
|
||||||
$column[0] .= str_repeat(chr(0), 128 - strlen($column[0]));
|
|
||||||
$column[1] .= str_repeat(chr(0), 64 - strlen($column[1]));
|
|
||||||
$column[2] .= str_repeat(chr(0), 64 - strlen($column[2]));
|
|
||||||
$column[3] .= str_repeat(chr(0), 64 - strlen($column[3]));
|
|
||||||
return $column;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user