New PMF level (uses NBT Entity and TileEntity)

This commit is contained in:
Shoghi Cervantes 2014-02-26 17:15:31 +01:00
parent 38c5174da7
commit 3864630bcd
9 changed files with 82 additions and 44 deletions

View File

@ -38,10 +38,10 @@ class BanAPI{
} }
public function init(){ public function init(){
$this->whitelist = new Config(DATA_PATH."white-list.txt", Config::LIST);//Open whitelist list file $this->whitelist = new Config(DATA_PATH."white-list.txt", Config::ENUM);//Open whitelist list file
$this->bannedIPs = new Config(DATA_PATH."banned-ips.txt", Config::LIST);//Open Banned IPs list file $this->bannedIPs = new Config(DATA_PATH."banned-ips.txt", Config::ENUM);//Open Banned IPs list file
$this->banned = new Config(DATA_PATH."banned.txt", Config::LIST);//Open Banned Usernames list file $this->banned = new Config(DATA_PATH."banned.txt", Config::ENUM);//Open Banned Usernames list file
$this->ops = new Config(DATA_PATH."ops.txt", Config::LIST);//Open list of OPs $this->ops = new Config(DATA_PATH."ops.txt", Config::ENUM);//Open list of OPs
$this->server->api->console->register("banip", "<add|remove|list|reload> [IP|player]", array($this, "commandHandler")); $this->server->api->console->register("banip", "<add|remove|list|reload> [IP|player]", array($this, "commandHandler"));
$this->server->api->console->register("ban", "<add|remove|list|reload> [username]", array($this, "commandHandler")); $this->server->api->console->register("ban", "<add|remove|list|reload> [username]", array($this, "commandHandler"));
$this->server->api->console->register("kick", "<player> [reason ...]", array($this, "commandHandler")); $this->server->api->console->register("kick", "<player> [reason ...]", array($this, "commandHandler"));
@ -211,7 +211,7 @@ class BanAPI{
$output .= "Player \"$user\" added to white-list\n"; $output .= "Player \"$user\" added to white-list\n";
break; break;
case "reload": case "reload":
$this->whitelist = new Config(DATA_PATH."white-list.txt", Config::LIST); $this->whitelist = new Config(DATA_PATH."white-list.txt", Config::ENUM);
break; break;
case "list": case "list":
$output .= "White-list: ".implode(", ", $this->whitelist->getAll(true))."\n"; $output .= "White-list: ".implode(", ", $this->whitelist->getAll(true))."\n";
@ -256,7 +256,7 @@ class BanAPI{
$output .= "IP \"$ip\" added to ban list\n"; $output .= "IP \"$ip\" added to ban list\n";
break; break;
case "reload": case "reload":
$this->bannedIPs = new Config(DATA_PATH."banned-ips.txt", Config::LIST); $this->bannedIPs = new Config(DATA_PATH."banned-ips.txt", Config::ENUM);
break; break;
case "list": case "list":
$output .= "IP ban list: ".implode(", ", $this->bannedIPs->getAll(true))."\n"; $output .= "IP ban list: ".implode(", ", $this->bannedIPs->getAll(true))."\n";
@ -294,7 +294,7 @@ class BanAPI{
$output .= "Player \"$user\" added to ban list\n"; $output .= "Player \"$user\" added to ban list\n";
break; break;
case "reload": case "reload":
$this->banned = new Config(DATA_PATH."banned.txt", Config::LIST); $this->banned = new Config(DATA_PATH."banned.txt", Config::ENUM);
break; break;
case "list": case "list":
$output .= "Ban list: ".implode(", ", $this->banned->getAll(true))."\n"; $output .= "Ban list: ".implode(", ", $this->banned->getAll(true))."\n";

View File

@ -96,7 +96,7 @@ require_once(FILE_PATH."/src/math/Vector3.php");
require_once(FILE_PATH."/src/world/Position.php"); require_once(FILE_PATH."/src/world/Position.php");
require_once(FILE_PATH."/src/pmf/PMF.php"); require_once(FILE_PATH."/src/pmf/PMF.php");
require_all(FILE_PATH . "src/"); require_all(FILE_PATH . "src/", array("entity", "Entity.php")); //REMOVE LATER!!!!
$inc = get_included_files(); $inc = get_included_files();
$inc[] = array_shift($inc); $inc[] = array_shift($inc);

View File

@ -80,11 +80,11 @@ function kill($pid){
} }
} }
function require_all($path, &$count = 0){ function require_all($path, array $ignore = array(), &$count = 0){
$dir = dir($path."/"); $dir = dir($path."/");
$dirs = array(); $dirs = array();
while(false !== ($file = $dir->read())){ while(false !== ($file = $dir->read())){
if($file !== "." and $file !== ".."){ if($file !== "." and $file !== ".." and !in_array($file, $ignore, true)){
if(!is_dir($path.$file) and strtolower(substr($file, -3)) === "php"){ if(!is_dir($path.$file) and strtolower(substr($file, -3)) === "php"){
require_once($path.$file); require_once($path.$file);
++$count; ++$count;
@ -94,7 +94,7 @@ function require_all($path, &$count = 0){
} }
} }
foreach($dirs as $dir){ foreach($dirs as $dir){
require_all($dir, $count); require_all($dir, $ignore, $count);
} }
} }
@ -134,7 +134,7 @@ function arg($name, $default = false){
} }
} }
function arguments ( $args ){ function arguments($args){
if(!is_array($args)){ if(!is_array($args)){
$args = array(); $args = array();
} }

View File

@ -57,6 +57,7 @@ class NBT{
$this->offset = 0; $this->offset = 0;
$this->buffer = $buffer; $this->buffer = $buffer;
$this->data = $this->readTag(); $this->data = $this->readTag();
$this->buffer = b"";
} }
public function write(){ public function write(){
@ -221,5 +222,4 @@ class NBT{
$this->data = $data; $this->data = $data;
} }
} }
>>>>>>> origin/master

View File

@ -49,7 +49,7 @@ class NBTTag_Compound extends NamedNBTTag{
$tag = $nbt->readTag(); $tag = $nbt->readTag();
if($tag instanceof NamedNBTTag and $tag->getName() !== ""){ if($tag instanceof NamedNBTTag and $tag->getName() !== ""){
$this->value[$tag->getName()] = $tag; $this->value[$tag->getName()] = $tag;
}else{ }elseif(!($tag instanceof NBTTag_End)){
$this->value[] = $tag; $this->value[] = $tag;
} }
}while(!($tag instanceof NBTTag_End) and !$nbt->feof()); }while(!($tag instanceof NBTTag_End) and !$nbt->feof());
@ -57,7 +57,10 @@ class NBTTag_Compound extends NamedNBTTag{
public function write(NBT $nbt){ public function write(NBT $nbt){
foreach($this->value as $tag){ foreach($this->value as $tag){
$nbt->writeTag($tag); if(!($tag instanceof NBTTag_End)){
$nbt->writeTag($tag);
}
} }
$nbt->writeTag(new NBTTag_End);
} }
} }

View File

@ -20,8 +20,9 @@
*/ */
class PMFLevel extends PMF{ class PMFLevel extends PMF{
const VERSION = 0x01; const VERSION = 2;
const DEFLATE_LEVEL = 9; const ZLIB_LEVEL = 6;
const ZLIB_ENCODING = 15; //15 = zlib, -15 = raw deflate, 31 = gzip
public $level; public $level;
public $levelData = array(); public $levelData = array();
@ -90,7 +91,7 @@ class PMFLevel extends PMF{
$this->write(Utils::writeShort(strlen($this->levelData["generator"])).$this->levelData["generator"]); $this->write(Utils::writeShort(strlen($this->levelData["generator"])).$this->levelData["generator"]);
$settings = serialize($this->levelData["generatorSettings"]); $settings = serialize($this->levelData["generatorSettings"]);
$this->write(Utils::writeShort(strlen($settings)).$settings); $this->write(Utils::writeShort(strlen($settings)).$settings);
$extra = gzdeflate($this->levelData["extra"], PMFLevel::DEFLATE_LEVEL); $extra = zlib_encode($this->levelData["extra"], PMFLevel::ZLIB_ENCODING, PMFLevel::ZLIB_LEVEL);
$this->write(Utils::writeShort(strlen($extra)).$extra); $this->write(Utils::writeShort(strlen($extra)).$extra);
} }
@ -135,11 +136,14 @@ class PMFLevel extends PMF{
$this->levelData["generatorSettings"] = unserialize($this->read(Utils::readShort($this->read(2), false))); $this->levelData["generatorSettings"] = unserialize($this->read(Utils::readShort($this->read(2), false)));
} }
$this->levelData["extra"] = @gzinflate($this->read(Utils::readShort($this->read(2), false))); $this->levelData["extra"] = @zlib_decode($this->read(Utils::readShort($this->read(2), false)));
if($this->levelData["version"] === 0){ if($this->levelData["version"] === 0){
$this->upgrade_From0_To1(); $this->upgrade_From0_To1();
} }
if($this->levelData["version"] === 1){
$this->upgrade_From1_To2();
}
} }
private function upgrade_From0_To1(){ private function upgrade_From0_To1(){
@ -162,12 +166,32 @@ class PMFLevel extends PMF{
gzclose($chunkOld); gzclose($chunkOld);
@unlink($oldPath); @unlink($oldPath);
} }
$this->levelData["version"] = 0x01; $this->levelData["version"] = 1;
$this->levelData["generator"] = "NormalGenerator"; $this->levelData["generator"] = "NormalGenerator";
$this->levelData["generatorSettings"] = ""; $this->levelData["generatorSettings"] = "";
$this->saveData(); $this->saveData();
} }
private function upgrade_From1_To2(){
console("[NOTICE] Old PMF Level format version #1 detected, upgrading to version #2");
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->setData(new NBTTag_Compound("", array(
new NBTTag_Compound("Entities", array()),
new NBTTag_Compound("TileEntities", array())
)));
$namedtag = $nbt->write();
$namedtag = Utils::writeInt(strlen($namedtag)) . $namedtag;
foreach(glob(dirname($this->file)."/chunks/*/*.*.pmc") as $chunkFile){
$oldChunk = zlib_decode(file_get_contents($chunkFile));
$newChunk = substr($oldChunk, 0, 5);
$newChunk .= $namedtag;
$newChunk .= substr($oldChunk, 5);
file_put_contents($chunkFile, zlib_encode($newChunk, PMFLevel::ZLIB_ENCODING, PMFLevel::ZLIB_LEVEL));
}
$this->levelData["version"] = 2;
$this->saveData();
}
public static function getIndex($X, $Z){ public static function getIndex($X, $Z){
return ($Z << 16) | ($X < 0 ? (~--$X & 0x7fff) | 0x8000 : $X & 0x7fff); return ($Z << 16) | ($X < 0 ? (~--$X & 0x7fff) | 0x8000 : $X & 0x7fff);
} }
@ -233,29 +257,39 @@ class PMFLevel extends PMF{
return true; return true;
} }
$chunk = @gzopen($path, "rb"); $chunk = file_get_contents($path);
if($chunk === false){ if($chunk === false){
return false; return false;
} }
$chunk = zlib_decode($chunk);
$offset = 0;
$this->chunkInfo[$index] = array( $this->chunkInfo[$index] = array(
0 => ord(gzread($chunk, 1)), 0 => ord($chunk{0}),
1 => Utils::readInt(gzread($chunk, 4)), 1 => Utils::readInt(substr($chunk, 1, 4)),
); );
$offset += 5;
$len = Utils::readInt(substr($chunk, $offset, 4));
$offset += 4;
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->read(substr($chunk, $offset, $len));
$this->chunkInfo[2] = $nbt;
$offset += $len;
$this->chunks[$index] = array(); $this->chunks[$index] = array();
$this->chunkChange[$index] = array(-1 => false); $this->chunkChange[$index] = array(-1 => false);
for($Y = 0; $Y < $this->chunkInfo[$index][0]; ++$Y){ for($Y = 0; $Y < $this->chunkInfo[$index][0]; ++$Y){
$t = 1 << $Y; $t = 1 << $Y;
if(($this->chunkInfo[$index][0] & $t) === $t){ if(($this->chunkInfo[$index][0] & $t) === $t){
// 4096 + 2048 + 2048, Block Data, Meta, Light // 4096 + 2048 + 2048, Block Data, Meta, Light
if(strlen($this->chunks[$index][$Y] = gzread($chunk, 8192)) < 8192){ if(strlen($this->chunks[$index][$Y] = substr($chunk, $offset, 8192)) < 8192){
console("[NOTICE] Empty corrupt chunk detected [$X,$Z,:$Y], recovering contents", true, true, 2); console("[NOTICE] Empty corrupt chunk detected [$X,$Z,:$Y], recovering contents", true, true, 2);
$this->fillMiniChunk($X, $Z, $Y); $this->fillMiniChunk($X, $Z, $Y);
} }
$offset += 8192;
}else{ }else{
$this->chunks[$index][$Y] = false; $this->chunks[$index][$Y] = false;
} }
} }
@gzclose($chunk);
if($this->isGenerating === 0 and !$this->isPopulated($X, $Z)){ if($this->isGenerating === 0 and !$this->isPopulated($X, $Z)){
$this->populateChunk($X, $Z); $this->populateChunk($X, $Z);
} }
@ -561,16 +595,18 @@ class PMFLevel extends PMF{
} }
$this->chunkChange[$index][$Y] = 0; $this->chunkChange[$index][$Y] = 0;
} }
$chunk = @gzopen($path, "wb".PMFLevel::DEFLATE_LEVEL); $chunk = b"";
gzwrite($chunk, chr($bitmap)); $chunk .= chr($bitmap);
gzwrite($chunk, Utils::writeInt($this->chunkInfo[$index][1])); $chunk .= Utils::writeInt($this->chunkInfo[$index][1]);
$namedtag = $this->chunkInfo[$index][2]->write();
$chunk .= Utils::writeInt(strlen($namedtag)).$namedtag;
for($Y = 0; $Y < 8; ++$Y){ for($Y = 0; $Y < 8; ++$Y){
$t = 1 << $Y; $t = 1 << $Y;
if(($bitmap & $t) === $t){ if(($bitmap & $t) === $t){
gzwrite($chunk, $this->chunks[$index][$Y]); $chunk .= $this->chunks[$index][$Y];
} }
} }
gzclose($chunk); file_put_contents($path, zlib_encode($chunk, PMFLevel::ZLIB_ENCODING, PMFLevel::ZLIB_LEVEL));
$this->chunkChange[$index][-1] = false; $this->chunkChange[$index][-1] = false;
$this->chunkInfo[$index][0] = $bitmap; $this->chunkInfo[$index][0] = $bitmap;
return true; return true;

View File

@ -29,12 +29,13 @@
class Config{ class Config{
const DETECT = -1; //Detect by file extension const DETECT = -1; //Detect by file extension
const PROPERTIES = 0; // .properties const PROPERTIES = 0; // .properties
const CNF = PROPERTIES; // .cnf const CNF = Config::PROPERTIES; // .cnf
const JSON = 1; // .js, .json const JSON = 1; // .js, .json
const YAML = 2; // .yml, .yaml const YAML = 2; // .yml, .yaml
//const EXPORT = 3; // .export, .xport //const EXPORT = 3; // .export, .xport
const SERIALIZED = 4; // .sl const SERIALIZED = 4; // .sl
const LIST = 5; // .txt, .list const ENUM = 5; // .txt, .list, .enum
const ENUMERATION = Config::ENUM;
/** /**
* @var array * @var array
@ -66,8 +67,9 @@ class Config{
//"xport" => Config::EXPORT, //"xport" => Config::EXPORT,
"sl" => Config::SERIALIZED, "sl" => Config::SERIALIZED,
"serialize" => Config::SERIALIZED, "serialize" => Config::SERIALIZED,
"txt" => Config::LIST, "txt" => Config::ENUM,
"list" => Config::LIST, "list" => Config::ENUM,
"enum" => Config::ENUM,
); );
/** /**
@ -136,7 +138,7 @@ class Config{
case Config::SERIALIZED: case Config::SERIALIZED:
$this->config = @unserialize($content); $this->config = @unserialize($content);
break; break;
case Config::LIST: case Config::ENUM:
$this->parseList($content); $this->parseList($content);
break; break;
default: default:
@ -182,7 +184,7 @@ class Config{
case Config::SERIALIZED: case Config::SERIALIZED:
$content = @serialize($this->config); $content = @serialize($this->config);
break; break;
case Config::LIST: case Config::ENUM:
$content = implode("\r\n", array_keys($this->config)); $content = implode("\r\n", array_keys($this->config));
break; break;
} }

View File

@ -122,7 +122,7 @@ LICENSE;
if($op === ""){ if($op === ""){
echo "[!] ".$this->lang->op_warning."\n"; echo "[!] ".$this->lang->op_warning."\n";
}else{ }else{
$ops = new Config(DATA_PATH."ops.txt", Config::LIST); $ops = new Config(DATA_PATH."ops.txt", Config::ENUM);
$ops->set($op, true); $ops->set($op, true);
$ops->save(); $ops->save();
} }

View File

@ -364,16 +364,14 @@ class Tile extends Position{
new NBTTag_Int("y", (int) $this->y), new NBTTag_Int("y", (int) $this->y),
new NBTTag_Int("z", (int) $this->z), new NBTTag_Int("z", (int) $this->z),
new NBTTag_Int("pairx", (int) $this->data["pairx"]), new NBTTag_Int("pairx", (int) $this->data["pairx"]),
new NBTTag_Int("pairz", (int) $this->data["pairz"]), new NBTTag_Int("pairz", (int) $this->data["pairz"])
new NBTTag_End
))); )));
}else{ }else{
$nbt->setData(new NBTTag_Compound("", array( $nbt->setData(new NBTTag_Compound("", array(
new NBTTag_String("id", $this->class), new NBTTag_String("id", $this->class),
new NBTTag_Int("x", (int) $this->x), new NBTTag_Int("x", (int) $this->x),
new NBTTag_Int("y", (int) $this->y), new NBTTag_Int("y", (int) $this->y),
new NBTTag_Int("z", (int) $this->z), new NBTTag_Int("z", (int) $this->z)
new NBTTag_End
))); )));
} }
@ -394,8 +392,7 @@ class Tile extends Position{
new NBTTag_String("id", $this->class), new NBTTag_String("id", $this->class),
new NBTTag_Int("x", (int) $this->x), new NBTTag_Int("x", (int) $this->x),
new NBTTag_Int("y", (int) $this->y), new NBTTag_Int("y", (int) $this->y),
new NBTTag_Int("z", (int) $this->z), new NBTTag_Int("z", (int) $this->z)
new NBTTag_End
))); )));
$pk = new EntityDataPacket; $pk = new EntityDataPacket;
$pk->x = $this->x; $pk->x = $this->x;