PMF & Multiworld [part 1]

This commit is contained in:
Shoghi Cervantes Pueyo
2013-04-28 23:44:43 +02:00
parent bbbc54f606
commit db8f50f408
18 changed files with 626 additions and 548 deletions

View File

@ -45,7 +45,7 @@ define("ENTITY_OBJECT", 2);
define("ENTITY_ITEM", 3);
class Entity extends stdClass{
class Entity extends Position{
public $age;
public $air;
public $spawntime;
@ -74,7 +74,9 @@ class Entity extends stdClass{
private $tickCounter;
private $speedMeasure = array(0, 0, 0, 0, 0);
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->fallStart = false;
$this->server = ServerAPI::request();
@ -97,7 +99,7 @@ class Entity extends stdClass{
$this->closed = false;
$this->name = "";
$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->y = isset($this->data["y"]) ? $this->data["y"]:0;
$this->z = isset($this->data["z"]) ? $this->data["z"]:0;
@ -107,7 +109,7 @@ class Entity extends stdClass{
$this->speed = 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);
$this->position = array("level" => $this->level, "x" => &$this->x, "y" => &$this->y, "z" => &$this->z, "yaw" => &$this->yaw, "pitch" => &$this->pitch);
switch($this->class){
case ENTITY_PLAYER:
$this->player = $this->data["player"];
@ -175,7 +177,7 @@ class Entity extends stdClass{
private function spawnDrops(){
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
return false;
}
if(($time - $this->spawntime) >= 2){
$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);
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 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"]);
if($player instanceof Entity){
$player = $player->player;
@ -439,7 +441,7 @@ class Entity extends stdClass{
if(!($player instanceof 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;
}
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.";");
}
public function setCoords($x, $y, $z){
$this->x = $x;
$this->y = $y;
$this->z = $z;
public function setCoords(Vector3 $pos){
if($pos instanceof Position){
$this->level = $pos->level;
$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.";");
}
public function move($x, $y, $z, $yaw = 0, $pitch = 0){
$this->x += $x;
$this->y += $y;
$this->z += $z;
public function move(Vector3 $pos, $yaw = 0, $pitch = 0){
$this->x += $pos->x;
$this->y += $pos->y;
$this->z += $pos->z;
$this->yaw += $yaw;
$this->yaw %= 360;
$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.";");
}
public function setPosition($x, $y, $z, $yaw, $pitch){
$this->x = $x;
$this->y = $y;
$this->z = $z;
public function setPosition(Vector3 $pos, $yaw, $pitch){
if($pos instanceof Position){
$this->level = $pos->level;
$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.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
}
public function inBlock($x, $y, $z, $radius = 0.8){
$block = new Vector3($x, $y, $z);
public function inBlock(Vector3 $block, $radius = 0.8){
$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){
return true;
@ -566,8 +577,7 @@ class Entity extends stdClass{
return false;
}
public function touchingBlock($x, $y, $z, $radius = 0.9){
$block = new Vector3($x, $y, $z);
public function touchingBlock(Vector3 $block, $radius = 0.9){
$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){
return true;

151
src/world/Level.php Normal file
View 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");
}
}

View File

@ -33,6 +33,8 @@ class LevelImport{
public function import(){
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->save();
$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"] == ""){
$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"]);
$lvName = $level["LevelName"]."/";
$entities = parseNBTData($nbt->loadFile($this->path."entities.dat"));
if(!isset($entities["TileEntities"])){
$entities["TileEntities"] = array();
@ -56,6 +57,8 @@ class LevelImport{
$entities->save();
$tileEntities = new Config($this->path."tileEntities.yml", CONFIG_YAML, $tileEntities);
$tileEntities->save();
}else{
return false;
}
$pmf = new PMFLevel($this->path."level.pmf", array(
@ -65,6 +68,7 @@ class LevelImport{
"spawnX" => $level["SpawnX"],
"spawnY" => $level["SpawnY"],
"spawnZ" => $level["SpawnZ"],
"extra" => "",
"width" => 16,
"height" => 8
));
@ -99,16 +103,17 @@ class LevelImport{
}
$pmf->saveChunk($X, $Z);
}
console("[NOTICE] Importing level ".ceil(($Z + 1)/0.16)."%");
}
$chunks->map = null;
$chunks = null;
/*@unlink($this->path."level.dat");
@unlink($this->path."level.dat");
@unlink($this->path."level.dat_old");
@unlink($this->path."player.dat");
@unlink($this->path."entities.dat");
@unlink($this->path."chunks.dat");
@unlink($this->path."chunks.dat.gz");
@unlink($this->path."tileEntities.dat");*/
@unlink($this->path."tileEntities.dat");
unset($chunks, $level, $entities, $tileEntities, $nbt);
return true;
}

40
src/world/Position.php Normal file
View File

@ -0,0 +1,40 @@
<?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 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.")";
}
}

View File

@ -32,7 +32,7 @@ define("TILE_CHEST", "Chest");
define("TILE_FURNACE", "Furnace");
define("FURNACE_SLOTS", 3);
class TileEntity extends stdClass{
class TileEntity extends Position{
public $name;
public $normal;
public $id;
@ -45,8 +45,9 @@ class TileEntity extends stdClass{
public $metadata;
public $closed;
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->level = $level;
$this->normal = true;
$this->class = $class;
$this->data = $data;
@ -59,7 +60,7 @@ class TileEntity extends stdClass{
$this->x = (int) $x;
$this->y = (int) $y;
$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){
case TILE_SIGN:
$this->server->query("UPDATE tileentities SET spawnable = 1 WHERE ID = ".$this->id.";");
@ -148,7 +149,7 @@ class TileEntity extends stdClass{
public function close(){
if($this->closed === false){
$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;
}
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($x, $y, $z){
$this->x = (int) $x;
$this->y = (int) $y;
$this->z = (int) $z;
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE EID = ".$this->eid.";");
public function setPosition(Vector3 $pos){
if($pos instanceof Position){
$this->level = $pos->level;
$this->server->query("UPDATE tileentities SET level = '".$this->level->getName()."' WHERE ID = ".$this->id.";");
}
$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.";");
}
}

View File

@ -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;
}
}