Updated NBT library to remove read overhead

This commit is contained in:
Shoghi Cervantes 2014-03-12 22:40:19 +01:00
parent cc5a30a0c2
commit 63542a2f13
32 changed files with 446 additions and 500 deletions

View File

@ -333,7 +333,7 @@ $this->updateMetadata();
}else{
$hasUpdate = true;
}
if(($this->player instanceof Player) and ($this->player->gamemode & 0x01) === CREATIVE){ //Remove fire effects in next tick
if(($this->player instanceof Player) and ($this->player->gamemode & 0x01) === 1){ //Remove fire effects in next tick
$this->fire = 1;
}
}

View File

@ -21,7 +21,7 @@
namespace PocketMine;
use PocketMine\Block\Block;
use PocketMine\Block;
use PocketMine\Item\Item;
use PocketMine\Level\Level;
use PocketMine\Level\Position;
@ -196,10 +196,12 @@ class BlockAPI{
[Item::CLOCK, 0],
[Item::COMPASS, 0],
[Item::MINECART, 0],
[Item::SPAWN_EGG, MOB_CHICKEN],
[Item::SPAWN_EGG, MOB_COW],
[Item::SPAWN_EGG, MOB_PIG],
[Item::SPAWN_EGG, MOB_SHEEP],
[Item::SPAWN_EGG, 10], //Chicken
[Item::SPAWN_EGG, 11], //Cow
[Item::SPAWN_EGG, 12], //Pig
[Item::SPAWN_EGG, 13], //Sheep
//TODO: Replace with Entity constants
//Seeds
[Item::SUGARCANE, 0],
@ -230,35 +232,6 @@ class BlockAPI{
);
public static function fromString($str, $multiple = false){
if($multiple === true){
$blocks = array();
foreach(explode(",", $str) as $b){
$blocks[] = BlockAPI::fromString($b, false);
}
return $blocks;
} else{
$b = explode(":", str_replace(" ", "_", trim($str)));
if(!isset($b[1])){
$meta = 0;
} else{
$meta = ((int) $b[1]) & 0xFFFF;
}
if(defined(strtoupper($b[0]))){
$item = Item::get(constant(strtoupper($b[0])), $meta);
if($item->getID() === AIR and strtoupper($b[0]) !== "AIR"){
$item = Item::get(((int) $b[0]) & 0xFFFF, $meta);
}
} else{
$item = Item::get(((int) $b[0]) & 0xFFFF, $meta);
}
return $item;
}
}
function __construct(){
$this->server = ServerAPI::request();
}
@ -306,7 +279,7 @@ class BlockAPI{
return $output;
}
private function cancelAction(Block $block, Player $player, $send = true){
private function cancelAction(Block\Block $block, Player $player, $send = true){
$pk = new UpdateBlockPacket;
$pk->x = $block->x;
$pk->y = $block->y;
@ -321,7 +294,7 @@ class BlockAPI{
return false;
}
public function playerBlockBreak(Player $player, Math\Math\Vector3 $vector){
public function playerBlockBreak(Player $player, Math\Vector3 $vector){
$target = $player->level->getBlock($vector);
$item = $player->getSlot($player->slot);
@ -345,7 +318,7 @@ class BlockAPI{
return $this->cancelAction($target, $player, false);
}
if(($player->gamemode & 0x01) === 0 and $item->useOn($target) and $item->getMetadata() >= $item->getMaxDurability()){
$player->setSlot($player->slot, new Item(AIR, 0, 0));
$player->setSlot($player->slot, new Item(Item::AIR, 0, 0));
}
} else{
return $this->cancelAction($target, $player, false);
@ -362,7 +335,7 @@ class BlockAPI{
return false;
}
public function playerBlockAction(Player $player, Math\Math\Vector3 $vector, $face, $fx, $fy, $fz){
public function playerBlockAction(Player $player, Math\Vector3 $vector, $face, $fx, $fy, $fz){
if($face < 0 or $face > 5){
return false;
}
@ -375,7 +348,7 @@ class BlockAPI{
$item = Item::get(BlockAPI::$creative[$player->slot][0], BlockAPI::$creative[$player->slot][1], 1);
}
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() === Item::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($this->server->api->dhandle("player.block.place.bypass", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) !== true){
$this->cancelAction($target, $player);
@ -408,7 +381,7 @@ class BlockAPI{
if($item->isActivable === true and $item->onActivate($player->level, $player, $block, $target, $face, $fx, $fy, $fz) === true){
if($item->getCount() <= 0){
$player->setSlot($player->slot, Item::get(AIR, 0, 0));
$player->setSlot($player->slot, Item::get(Item::AIR, 0, 0));
}
return false;
@ -417,15 +390,15 @@ class BlockAPI{
if($item->isPlaceable()){
$hand = $item->getBlock();
$hand->position($block);
} elseif($block->getID() === FIRE){
$player->level->setBlock($block, new Block\AirBlock(), true, false, true);
} elseif($block->getID() === Item::FIRE){
$player->level->setBlock($block, new Block\Air(), true, false, true);
return false;
} else{
return $this->cancelAction($block, $player, false);
}
if(!($block->isReplaceable === true or ($hand->getID() === SLAB and $block->getID() === SLAB))){
if(!($block->isReplaceable === true or ($hand->getID() === Item::SLAB and $block->getID() === Item::SLAB))){
return $this->cancelAction($block, $player, false);
}
@ -445,24 +418,24 @@ class BlockAPI{
} elseif($hand->place($item, $player, $block, $target, $face, $fx, $fy, $fz) === false){
return $this->cancelAction($block, $player, false);
}
if($hand->getID() === SIGN_POST or $hand->getID() === WALL_SIGN){
if($hand->getID() === Item::SIGN_POST or $hand->getID() === Item::WALL_SIGN){
new Sign($player->level, new Compound(false, array(
"id" => new String("id", Tile::Sign),
"x" => new Int("x", $block->x),
"y" => new Int("y", $block->y),
"z" => new Int("z", $block->z),
"Text1" => new String("Text1", ""),
"Text2" => new String("Text2", ""),
"Text3" => new String("Text3", ""),
"Text4" => new String("Text4", ""),
"creator" => new String("creator", $player->getUsername())
new String("id", Tile\Tile::SIGN),
new Int("x", $block->x),
new Int("y", $block->y),
new Int("z", $block->z),
new String("Text1", ""),
new String("Text2", ""),
new String("Text3", ""),
new String("Text4", ""),
new String("creator", $player->getUsername())
)));
}
if(($player->getGamemode() & 0x01) === 0){
$item->setCount($item->getCount() - 1);
if($item->getCount() <= 0){
$player->setSlot($player->slot, Item::get(AIR, 0, 0));
$player->setSlot($player->slot, Item::get(Item::AIR, 0, 0));
}
}
@ -488,7 +461,7 @@ class BlockAPI{
}
public function blockUpdate(Position $pos, $type = Level::BLOCK_UPDATE_NORMAL){
if(!($pos instanceof Block)){
if(!($pos instanceof BLock\Block)){
$block = $pos->level->getBlock($pos);
} else{
$pos = new Position($pos->x, $pos->y, $pos->z, $pos->level);

View File

@ -64,20 +64,20 @@ class ConsoleAPI{
switch($cmd){
case "defaultgamemode":
$gms = array(
"0" => SURVIVAL,
"survival" => SURVIVAL,
"s" => SURVIVAL,
"1" => CREATIVE,
"creative" => CREATIVE,
"c" => CREATIVE,
"2" => ADVENTURE,
"adventure" => ADVENTURE,
"a" => ADVENTURE,
"3" => VIEW,
"view" => VIEW,
"viewer" => VIEW,
"spectator" => VIEW,
"v" => VIEW,
"0" => 0,
"survival" => 0,
"s" => 0,
"1" => 1,
"creative" => 1,
"c" => 1,
"2" => 2,
"adventure" => 2,
"a" => 2,
"3" => 3,
"view" => 3,
"viewer" => 3,
"spectator" => 3,
"v" => 3,
);
if(!isset($gms[strtolower($params[0])])){
$output .= "Usage: /$cmd <mode>\n";

View File

@ -178,36 +178,35 @@ class Player extends RealHuman{
if(!file_exists(\PocketMine\DATA . "players/" . $iname . ".dat")){
$spawn = Level::getDefault()->getSafeSpawn();
$nbt = new Compound(false, array(
"Pos" => new Enum("Pos", array(
0 => new Double(0, $spawn->x),
1 => new Double(1, $spawn->y),
2 => new Double(2, $spawn->z)
new Enum("Pos", array(
new Double(0, $spawn->x),
new Double(1, $spawn->y),
new Double(2, $spawn->z)
)),
"Level" => new String("Level", Level::getDefault()->getName()),
"SpawnLevel" => new String("SpawnLevel", Level::getDefault()->getName()),
"SpawnX" => new Int("SpawnX", (int) $spawn->x),
"SpawnY" => new Int("SpawnY", (int) $spawn->y),
"SpawnZ" => new Int("SpawnZ", (int) $spawn->z),
"SpawnForced" => new Byte("SpawnForced", 1), //TODO
"Inventory" => new Enum("Inventory", array()),
"Achievements" => new Compound("Achievements", array()),
"playerGameType" => new Int("playerGameType", $server->gamemode),
"Motion" => new Enum("Motion", array(
0 => new Double(0, 0.0),
1 => new Double(1, 0.0),
2 => new Double(2, 0.0)
new String("Level", Level::getDefault()->getName()),
new String("SpawnLevel", Level::getDefault()->getName()),
new Int("SpawnX", (int) $spawn->x),
new Int("SpawnY", (int) $spawn->y),
new Int("SpawnZ", (int) $spawn->z),
new Byte("SpawnForced", 1), //TODO
new Enum("Inventory", array()),
new Compound("Achievements", array()),
new Int("playerGameType", $server->gamemode),
new Enum("Motion", array(
new Double(0, 0.0),
new Double(1, 0.0),
new Double(2, 0.0)
)),
"Rotation" => new Enum("Rotation", array(
0 => new Float(0, 0.0),
1 => new Float(1, 0.0)
new Enum("Rotation", array(
new Float(0, 0.0),
new Float(1, 0.0)
)),
"FallDistance" => new Float("FallDistance", 0.0),
"Fire" => new Short("Fire", 0),
"Air" => new Short("Air", 0),
"OnGround" => new Byte("OnGround", 1),
"Invulnerable" => new Byte("Invulnerable", 0),
"NameTag" => new String("NameTag", $name),
new Float("FallDistance", 0.0),
new Short("Fire", 0),
new Short("Air", 0),
new Byte("OnGround", 1),
new Byte("Invulnerable", 0),
new String("NameTag", $name),
));
$nbt->Pos->setTagType(NBT::TAG_Double);
$nbt->Inventory->setTagType(NBT::TAG_Compound);
@ -215,24 +214,24 @@ class Player extends RealHuman{
$nbt->Rotation->setTagType(NBT::TAG_Float);
if(file_exists(\PocketMine\DATA . "players/" . $iname . ".yml")){
$data = new Config(\PocketMine\DATA . "players/" . $iname . ".yml", Config::YAML, array());
$nbt->playerGameType = (int) $data->get("gamemode");
$nbt->Level = $data->get("position")["level"];
$nbt->Pos[0] = $data->get("position")["x"];
$nbt->Pos[1] = $data->get("position")["y"];
$nbt->Pos[2] = $data->get("position")["z"];
$nbt->SpawnLevel = $data->get("spawn")["level"];
$nbt->SpawnX = (int) $data->get("spawn")["x"];
$nbt->SpawnY = (int) $data->get("spawn")["y"];
$nbt->SpawnZ = (int) $data->get("spawn")["z"];
$nbt["playerGameType"] = (int) $data->get("gamemode");
$nbt["Level"] = $data->get("position")["level"];
$nbt["Pos"][0] = $data->get("position")["x"];
$nbt["Pos"][1] = $data->get("position")["y"];
$nbt["Pos"][2] = $data->get("position")["z"];
$nbt["SpawnLevel"] = $data->get("spawn")["level"];
$nbt["SpawnX"] = (int) $data->get("spawn")["x"];
$nbt["SpawnY"] = (int) $data->get("spawn")["y"];
$nbt["SpawnZ"] = (int) $data->get("spawn")["z"];
console("[NOTICE] Old Player data found for \"" . $iname . "\", upgrading profile");
foreach($data->get("inventory") as $slot => $item){
if(count($item) === 3){
$nbt->Inventory[$slot + 9] = new Compound(false, array(
"id" => new Short("id", $item[0]),
"Damage" => new Short("Damage", $item[1]),
"Count" => new Byte("Count", $item[2]),
"Slot" => new Byte("Slot", $slot + 9),
"TrueSlot" => new Byte("TrueSlot", $slot + 9)
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", $item[2]),
new Byte("Slot", $slot + 9),
new Byte("TrueSlot", $slot + 9)
));
}
}
@ -240,21 +239,21 @@ class Player extends RealHuman{
if(isset($nbt->Inventory[$itemSlot + 9])){
$item = $nbt->Inventory[$itemSlot + 9];
$nbt->Inventory[$slot] = new Compound(false, array(
"id" => new Short("id", $item->id),
"Damage" => new Short("Damage", $item->Damage),
"Count" => new Byte("Count", $item->Count),
"Slot" => new Byte("Slot", $slot),
"TrueSlot" => new Byte("TrueSlot", $item->TrueSlot)
new Short("id", $item->id),
new Short("Damage", $item->Damage),
new Byte("Count", $item->Count),
new Byte("Slot", $slot),
new Byte("TrueSlot", $item->TrueSlot)
));
}
}
foreach($data->get("armor") as $slot => $item){
if(count($item) === 2){
$nbt->Inventory[$slot + 100] = new Compound(false, array(
"id" => new Short("id", $item[0]),
"Damage" => new Short("Damage", $item[1]),
"Count" => new Byte("Count", 1),
"Slot" => new Byte("Slot", $slot + 100)
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", 1),
new Byte("Slot", $slot + 100)
));
}
}
@ -269,12 +268,11 @@ class Player extends RealHuman{
} else{
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->read(file_get_contents(\PocketMine\DATA . "players/" . $iname . ".dat"));
$nbt->readCompressed(file_get_contents(\PocketMine\DATA . "players/" . $iname . ".dat"));
$nbt = $nbt->getData();
}
$server->handle("player.offline.get", $nbt);
return $nbt;
}
@ -282,7 +280,7 @@ class Player extends RealHuman{
ServerAPI::request()->handle("player.offline.save", $nbtTag);
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->setData($nbtTag);
file_put_contents(\PocketMine\DATA . "players/" . strtolower($name) . ".dat", $nbt->write());
file_put_contents(\PocketMine\DATA . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed());
}
public static function broadcastPacket(array $players, DataPacket $packet){
@ -558,18 +556,17 @@ class Player extends RealHuman{
public function save(){
parent::saveNBT();
unset($this->namedtag->NameTag);
$this->namedtag->Level = $this->level->getName();
$this->namedtag->SpawnLevel = $this->level->getName();
$this->namedtag->SpawnX = (int) $this->spawnPosition->x;
$this->namedtag->SpawnY = (int) $this->spawnPosition->y;
$this->namedtag->SpawnZ = (int) $this->spawnPosition->z;
$this->namedtag["Level"] = $this->level->getName();
$this->namedtag["SpawnLevel"] = $this->level->getName();
$this->namedtag["SpawnX"] = (int) $this->spawnPosition->x;
$this->namedtag["SpawnY"] = (int) $this->spawnPosition->y;
$this->namedtag["SpawnZ"] = (int) $this->spawnPosition->z;
foreach($this->achievements as $achievement => $status){
$this->namedtag->Achievements[$achievement] = new Byte($achievement, $status === true ? 1 : 0);
}
$this->namedtag->playerGameType = $this->gamemode;
$this->namedtag["playerGameType"] = $this->gamemode;
//$this->data->set("health", $this->getHealth());
}
@ -677,7 +674,7 @@ class Player extends RealHuman{
$pk = new ContainerSetSlotPacket;
$pk->windowid = 0;
$pk->slot = (int) $s;
$pk->item = Item::get(AIR, 0, 0);
$pk->item = Item::get(Item::AIR, 0, 0);
$this->dataPacket($pk);
}
@ -1000,13 +997,13 @@ class Player extends RealHuman{
public function getGamemodeString(){
switch($this->gamemode){
case SURVIVAL:
case 0:
return "survival";
case CREATIVE:
case 1:
return "creative";
case ADVENTURE:
case 2:
return "adventure";
case VIEW:
case 3:
return "view";
}
}
@ -1322,14 +1319,18 @@ class Player extends RealHuman{
}
$nbt = Player::getOffline($this->username);
$nbt->NameTag = $this->username;
$this->gamemode = $nbt->playerGameType & 0x03;
if(($this->level = Level::get($nbt->Level)) === false){
if(!isset($nbt->NameTag)){
$nbt->NameTag = new String("NameTag", $this->username);
}else{
$nbt["NameTag"] = $this->username;
}
$this->gamemode = $nbt["playerGameType"] & 0x03;
if(($this->level = Level::get($nbt["Level"])) === false){
$this->level = Level::getDefault();
$nbt->Level = $this->level->getName();
$nbt->Pos[0] = $this->level->getSpawn()->x;
$nbt->Pos[1] = $this->level->getSpawn()->y;
$nbt->Pos[2] = $this->level->getSpawn()->z;
$nbt["Level"] = $this->level->getName();
$nbt["Pos"][0] = $this->level->getSpawn()->x;
$nbt["Pos"][1] = $this->level->getSpawn()->y;
$nbt["Pos"][2] = $this->level->getSpawn()->z;
}
if($this->server->api->handle("player.join", $this) === false){
@ -1376,8 +1377,8 @@ class Player extends RealHuman{
$this->dataPacket($pk);
if(($level = Level::get($this->namedtag->SpawnLevel)) !== false){
$this->spawnPosition = new Position($this->namedtag->SpawnX, $this->namedtag->SpawnY, $this->namedtag->SpawnZ, $level);
if(($level = Level::get($this->namedtag["SpawnLevel"])) !== false){
$this->spawnPosition = new Position($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
$pk = new SetSpawnPositionPacket;
$pk->x = (int) $this->spawnPosition->x;
@ -1476,7 +1477,7 @@ class Player extends RealHuman{
$packet->slot -= 9;
}
if(($this->gamemode & 0x01) === CREATIVE){
if(($this->gamemode & 0x01) === 1){
$packet->slot = false;
foreach(BlockAPI::$creative as $i => $d){
if($d[0] === $packet->item and $d[1] === $packet->meta){
@ -1494,7 +1495,7 @@ class Player extends RealHuman{
} else{
$this->setEquipmentSlot(0, $packet->slot);
$this->setCurrentEquipmentSlot(0);
if(($this->gamemode & 0x01) === SURVIVAL){
if(($this->gamemode & 0x01) === 0){
if(!in_array($this->slot, $this->hotbar)){
array_pop($this->hotbar);
array_unshift($this->hotbar, $this->slot);
@ -2195,7 +2196,7 @@ class Player extends RealHuman{
}
public function sendInventory(){
if(($this->gamemode & 0x01) === CREATIVE){
if(($this->gamemode & 0x01) === 1){
return;
}
$hotbar = array();

View File

@ -189,20 +189,20 @@ class PlayerAPI{
$player = false;
$setgm = false;
$gms = array(
"0" => SURVIVAL,
"survival" => SURVIVAL,
"s" => SURVIVAL,
"1" => CREATIVE,
"creative" => CREATIVE,
"c" => CREATIVE,
"2" => ADVENTURE,
"adventure" => ADVENTURE,
"a" => ADVENTURE,
"3" => VIEW,
"view" => VIEW,
"viewer" => VIEW,
"spectator" => VIEW,
"v" => VIEW,
"0" => 0,
"survival" => 0,
"s" => 0,
"1" => 1,
"creative" => 1,
"c" => 1,
"2" => 2,
"adventure" => 2,
"a" => 2,
"3" => 3,
"view" => 3,
"viewer" => 3,
"spectator" => 3,
"v" => 3,
);
if(isset($params[1])){
if(Player::get($params[1]) instanceof Player){

View File

@ -370,9 +370,9 @@ namespace PocketMine {
$gitsha1 = false;
if(file_exists(\PocketMine\PATH . ".git/refs/heads/master")){ //Found Git information!
define("PocketMine\GIT_COMMIT", strtolower(trim(file_get_contents(\PocketMine\PATH . ".git/refs/heads/master"))));
define("PocketMine\\GIT_COMMIT", strtolower(trim(file_get_contents(\PocketMine\PATH . ".git/refs/heads/master"))));
} else{ //Unknown :(
define("PocketMine\GIT_COMMIT", str_repeat("00", 20));
define("PocketMine\\GIT_COMMIT", str_repeat("00", 20));
}
ini_set("opcache.mmap_base", bin2hex(Utils\Utils::getRandomBytes(8, false))); //Fix OPCache address errors
@ -380,7 +380,7 @@ namespace PocketMine {
require_once(\PocketMine\PATH . "src/pthreads.php");
if(!file_exists(\PocketMine\DATA . "server.properties") and !isset($opts["no-wizard"])){
$installer = new Wizard\Installer();
new Wizard\Installer();
}
if(!defined("PARENT_API_EXISTENT")){

View File

@ -83,7 +83,7 @@ class Server{
}
}
function __construct($name, $gamemode = SURVIVAL, $seed = false, $port = 19132, $serverip = "0.0.0.0"){
function __construct($name, $gamemode = 0, $seed = false, $port = 19132, $serverip = "0.0.0.0"){
$this->port = (int) $port;
$this->doTick = true;
$this->gamemode = (int) $gamemode;
@ -368,17 +368,18 @@ class Server{
}
/**
* TODO
* @return string
*/
public function getGamemode(){
switch($this->gamemode){
case SURVIVAL:
case 0:
return "survival";
case CREATIVE:
case 1:
return "creative";
case ADVENTURE:
case 2:
return "adventure";
case VIEW:
case 3:
return "view";
}
}

View File

@ -128,7 +128,7 @@ class ServerAPI{
"allow-flight" => false,
"spawn-animals" => true,
"spawn-mobs" => true,
"gamemode" => SURVIVAL,
"gamemode" => 0,
"hardcore" => false,
"pvp" => true,
"difficulty" => 1,
@ -158,7 +158,7 @@ class ServerAPI{
$this->server = new Server($this->getProperty("server-name"), $this->getProperty("gamemode"), ($seed = $this->getProperty("level-seed")) != "" ? (int) $seed : false, $this->getProperty("server-port"), ($ip = $this->getProperty("server-ip")) != "" ? $ip : "0.0.0.0");
$this->server->api = $this;
self::$serverRequest = $this->server;
console("[INFO] This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . VERSION . TextFormat::RESET . " \"" . CODENAME . "\" (MCPE: " . MINECRAFT_VERSION . ") (API " . API_VERSION . ")", true, true, 0);
console("[INFO] This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . VERSION . TextFormat::RESET . " \"" . CODENAME . "\" (API " . API_VERSION . ")", true, true, 0);
console("[INFO] PocketMine-MP is distributed under the LGPL License", true, true, 0);
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){

View File

@ -21,7 +21,7 @@
namespace PocketMine;
use PocketMine\Level;
use PocketMine\Level\Level;
class TimeAPI{
public static $phases = array(

View File

@ -378,6 +378,11 @@ abstract class Block extends Position{
return $block;
}
/**
* @param int $id
* @param int $meta
* @param string $name
*/
public function __construct($id, $meta = 0, $name = "Unknown"){
$this->id = (int) $id;
$this->meta = (int) $meta;
@ -442,7 +447,7 @@ abstract class Block extends Position{
* @return array
*/
public function getDrops(Item $item, PocketMine\Player $player){
if(!isset(self::$class[$this->id])){ //Unknown blocks
if(!isset(self::$list[$this->id])){ //Unknown blocks
return array();
} else{
return array(
@ -459,7 +464,6 @@ abstract class Block extends Position{
*
* @return float
*/
public function getBreakTime(Item $item, PocketMine\Player $player){
if(($player->gamemode & 0x01) === 0x01){
return 0.15;
@ -484,6 +488,9 @@ abstract class Block extends Position{
return $v;
}
/**
* @return string
*/
final public function __toString(){
return "Block " . $this->name . " (" . $this->id . ":" . $this->meta . ")";
}

View File

@ -29,6 +29,7 @@ use PocketMine\NBT\Tag\String;
use PocketMine\Tile\Furnace;
use PocketMine\Tile\Tile;
use PocketMine;
use PocketMine\NBT\NBT;
class BurningFurnace extends Solid{
public function __construct($meta = 0){
@ -47,14 +48,14 @@ class BurningFurnace extends Solid{
$this->meta = $faces[$player->getDirection()];
$this->level->setBlock($block, $this, true, false, true);
$nbt = new Compound(false, array(
"Items" => new Enum("Items", array()),
"id" => new String("id", Tile::FURNACE),
"x" => new Int("x", $this->x),
"y" => new Int("y", $this->y),
"z" => new Int("z", $this->z)
new Enum("Items", array()),
new String("id", Tile::FURNACE),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
$nbt->Items->setTagType(NBT\Tag_Compound);
$furnace = new Furnace($this->level, $nbt);
$nbt->Items->setTagType(NBT::Tag_Compound);
new Furnace($this->level, $nbt);
return true;
}
@ -73,13 +74,13 @@ class BurningFurnace extends Solid{
$furnace = $t;
} else{
$nbt = new Compound(false, array(
"Items" => new Enum("Items", array()),
"id" => new String("id", Tile::FURNACE),
"x" => new Int("x", $this->x),
"y" => new Int("y", $this->y),
"z" => new Int("z", $this->z)
new Enum("Items", array()),
new String("id", Tile::FURNACE),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
$nbt->Items->setTagType(NBT\Tag_Compound);
$nbt->Items->setTagType(NBT::Tag_Compound);
$furnace = new Furnace($this->level, $nbt);
}
@ -115,13 +116,13 @@ class BurningFurnace extends Solid{
public function getDrops(Item $item, PocketMine\Player $player){
$drops = array();
if($item->isPickaxe() >= 1){
$drops[] = array(FURNACE, 0, 1);
$drops[] = array(Item::FURNACE, 0, 1);
}
$t = $this->level->getTile($this);
if($t instanceof Furnace){
for($s = 0; $s < Furnace::SLOTS; ++$s){
$slot = $t->getSlot($s);
if($slot->getID() > AIR and $slot->getCount() > 0){
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$drops[] = array($slot->getID(), $slot->getMetadata(), $slot->getCount());
}
}

View File

@ -29,6 +29,7 @@ use PocketMine\NBT\Tag\String;
use PocketMine\Tile\Chest as TileChest;
use PocketMine\Tile\Tile;
use PocketMine;
use PocketMine\NBT\NBT;
class Chest extends Transparent{
public function __construct($meta = 0){
@ -65,13 +66,13 @@ class Chest extends Transparent{
$this->level->setBlock($block, $this, true, false, true);
$nbt = new Compound(false, array(
"Items" => new Enum("Items", array()),
"id" => new String("id", Tile::CHEST),
"x" => new Int("x", $this->x),
"y" => new Int("y", $this->y),
"z" => new Int("z", $this->z)
new Enum("Items", array()),
new String("id", Tile::CHEST),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
$nbt->Items->setTagType(NBT\Tag_Compound);
$nbt->Items->setTagType(NBT::Tag_Compound);
$tile = new TileChest($this->level, $nbt);
if($chest instanceof TileChest){
@ -104,13 +105,13 @@ class Chest extends Transparent{
$chest = $t;
} else{
$nbt = new Compound(false, array(
"Items" => new Enum("Items", array()),
"id" => new String("id", Tile::CHEST),
"x" => new Int("x", $this->x),
"y" => new Int("y", $this->y),
"z" => new Int("z", $this->z)
new Enum("Items", array()),
new String("id", Tile::CHEST),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
$nbt->Items->setTagType(NBT\Tag_Compound);
$nbt->Items->setTagType(NBT::Tag_Compound);
$chest = new TileChest($this->level, $nbt);
}

View File

@ -21,14 +21,6 @@
namespace PocketMine;
//Gamemodes
const SURVIVAL = 0;
const CREATIVE = 1;
const ADVENTURE = 2;
const VIEW = 3;
const VIEWER = 3;
//Entities
const ENTITY_PLAYER = 1;

View File

@ -40,6 +40,7 @@ use PocketMine\Network\Protocol\RemoveEntityPacket;
use PocketMine\Network\Protocol\SetEntityMotionPacket;
use PocketMine\Player;
use PocketMine\PMF\LevelFormat;
use PocketMine\ServerAPI;
use PocketMine;
abstract class Entity extends Position{
@ -112,14 +113,14 @@ abstract class Entity extends Position{
$this->level = $level;
$this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
$this->setPositionAndRotation(new Vector3($this->namedtag->Pos[0], $this->namedtag->Pos[1], $this->namedtag->Pos[2]), $this->namedtag->Rotation[0], $this->namedtag->Rotation[1]);
$this->setMotion(new Vector3($this->namedtag->Motion[0], $this->namedtag->Motion[1], $this->namedtag->Motion[2]));
$this->setPositionAndRotation(new Vector3($this->namedtag["Pos"][0], $this->namedtag["Pos"][1], $this->namedtag["Pos"][2]), $this->namedtag->Rotation[0], $this->namedtag->Rotation[1]);
$this->setMotion(new Vector3($this->namedtag["Motion"][0], $this->namedtag["Motion"][1], $this->namedtag["Motion"][2]));
$this->fallDistance = $this->namedtag->FallDistance;
$this->fireTicks = $this->namedtag->Fire;
$this->airTicks = $this->namedtag->Air;
$this->onGround = $this->namedtag->OnGround > 0 ? true : false;
$this->invulnerable = $this->namedtag->Invulnerable > 0 ? true : false;
$this->fallDistance = $this->namedtag["FallDistance"];
$this->fireTicks = $this->namedtag["Fire"];
$this->airTicks = $this->namedtag["Air"];
$this->onGround = $this->namedtag["OnGround"] > 0 ? true : false;
$this->invulnerable = $this->namedtag["Invulnerable"] > 0 ? true : false;
$index = LevelFormat::getIndex($this->x >> 4, $this->z >> 4);
$this->chunkIndex = $index;
@ -128,26 +129,26 @@ abstract class Entity extends Position{
$this->level->chunkEntities[$this->chunkIndex][$this->id] = $this;
$this->lastUpdate = microtime(true);
$this->initEntity();
$this->server->api->dhandle("entity.add", $this);
ServerAPI::request()->api->dhandle("entity.add", $this);
}
public function saveNBT(){
$this->namedtag->Pos[0] = $this->x;
$this->namedtag->Pos[1] = $this->y;
$this->namedtag->Pos[2] = $this->z;
$this->namedtag["Pos"][0] = $this->x;
$this->namedtag["Pos"][1] = $this->y;
$this->namedtag["Pos"][2] = $this->z;
$this->namedtag->Motion[0] = $this->motionX;
$this->namedtag->Motion[1] = $this->motionY;
$this->namedtag->Motion[2] = $this->motionZ;
$this->namedtag["Motion"][0] = $this->motionX;
$this->namedtag["Motion"][1] = $this->motionY;
$this->namedtag["Motion"][2] = $this->motionZ;
$this->namedtag->Rotation[0] = $this->yaw;
$this->namedtag->Rotation[1] = $this->pitch;
$this->namedtag["Rotation"][0] = $this->yaw;
$this->namedtag["Rotation"][1] = $this->pitch;
$this->namedtag->FallDistance = $this->fallDistance;
$this->namedtag->Fire = $this->fireTicks;
$this->namedtag->Air = $this->airTicks;
$this->namedtag->OnGround = $this->onGround == true ? 1 : 0;
$this->namedtag->Invulnerable = $this->invulnerable == true ? 1 : 0;
$this->namedtag["FallDistance"] = $this->fallDistance;
$this->namedtag["Fire"] = $this->fireTicks;
$this->namedtag["Air"] = $this->airTicks;
$this->namedtag["OnGround"] = $this->onGround == true ? 1 : 0;
$this->namedtag["Invulnerable"] = $this->invulnerable == true ? 1 : 0;
}
protected abstract function initEntity();

View File

@ -48,7 +48,7 @@ class Human extends Creature implements ProjectileSource, InventorySource{
protected function initEntity(){
if(isset($this->namedtag->NameTag)){
$this->nameTag = $this->namedtag->NameTag;
$this->nameTag = $this->namedtag["NameTag"];
}
$this->hotbar = array(-1, -1, -1, -1, -1, -1, -1, -1, -1);
$this->armor = array(
@ -59,12 +59,12 @@ class Human extends Creature implements ProjectileSource, InventorySource{
);
foreach($this->namedtag->Inventory as $item){
if($item->Slot >= 0 and $item->Slot < 9){ //Hotbar
$this->hotbar[$item->Slot] = isset($item->TrueSlot) ? $item->TrueSlot : -1;
} elseif($item->Slot >= 100 and $item->Slot < 104){ //Armor
$this->armor[$item->Slot - 100] = Item::get($item->id, $item->Damage, $item->Count);
if($item["Slot"] >= 0 and $item["Slot"] < 9){ //Hotbar
$this->hotbar[$item["Slot"]] = isset($item["TrueSlot"]) ? $item["TrueSlot"] : -1;
} elseif($item["Slot"] >= 100 and $item["Slot"] < 104){ //Armor
$this->armor[$item["Slot"] - 100] = Item::get($item["id"], $item["Damage"], $item["Count"]);
} else{
$this->inventory[$item->Slot - 9] = Item::get($item->id, $item->Damage, $item->Count);
$this->inventory[$item["Slot"] - 9] = Item::get($item["id"], $item["Damage"], $item["Count"]);
}
}
$this->slot = $this->hotbar[0];
@ -78,35 +78,35 @@ class Human extends Creature implements ProjectileSource, InventorySource{
for($slot = 0; $slot < 9; ++$slot){
if(isset($this->hotbar[$slot]) and $this->hotbar[$slot] !== -1){
$item = $this->getSlot($this->hotbar[$slot]);
if($item->getID() !== AIR and $item->getCount() > 0){
if($item->getID() !== 0 and $item->getCount() > 0){
$this->namedtag->Inventory[$slot] = new Compound(false, array(
"Count" => new Byte("Count", $item->getCount()),
"Damage" => new Short("Damage", $item->getMetadata()),
"Slot" => new Byte("Slot", $slot),
"TrueSlot" => new Byte("TrueSlot", $this->hotbar[$slot]),
"id" => new Short("id", $item->getID()),
new Byte("Count", $item->getCount()),
new Short("Damage", $item->getMetadata()),
new Byte("Slot", $slot),
new Byte("TrueSlot", $this->hotbar[$slot]),
new Short("id", $item->getID()),
));
continue;
}
}
$this->namedtag->Inventory[$slot] = new Compound(false, array(
"Count" => new Byte("Count", 0),
"Damage" => new Short("Damage", 0),
"Slot" => new Byte("Slot", $slot),
"TrueSlot" => new Byte("Slot", -1),
"id" => new Short("id", 0),
new Byte("Count", 0),
new Short("Damage", 0),
new Byte("Slot", $slot),
new Byte("Slot", -1),
new Short("id", 0),
));
}
//Normal inventory
$slotCount = (($this->gamemode & 0x01) === 0 ? Player::SURVIVAL_SLOTS : Player::CREATIVE_SLOTS) + 9;
$slotCount = (($this instanceof Player and ($this->gamemode & 0x01) === 1) ? Player::CREATIVE_SLOTS : Player::SURVIVAL_SLOTS) + 9;
for($slot = 9; $slot < $slotCount; ++$slot){
$item = $this->getSlot($slot);
$this->namedtag->Inventory[$slot] = new Compound(false, array(
"Count" => new Byte("Count", $item->getCount()),
"Damage" => new Short("Damage", $item->getMetadata()),
"Slot" => new Byte("Slot", $slot),
"id" => new Short("id", $item->getID()),
new Byte("Count", $item->getCount()),
new Short("Damage", $item->getMetadata()),
new Byte("Slot", $slot),
new Short("id", $item->getID()),
));
}
@ -115,10 +115,10 @@ class Human extends Creature implements ProjectileSource, InventorySource{
$item = $this->armor[$slot - 100];
if($item instanceof Item){
$this->namedtag->Inventory[$slot] = new Compound(false, array(
"Count" => new Byte("Count", $item->getCount()),
"Damage" => new Short("Damage", $item->getMetadata()),
"Slot" => new Byte("Slot", $slot),
"id" => new Short("id", $item->getID()),
new Byte("Count", $item->getCount()),
new Short("Damage", $item->getMetadata()),
new Byte("Slot", $slot),
new Short("id", $item->getID()),
));
}
}
@ -383,6 +383,11 @@ class Human extends Creature implements ProjectileSource, InventorySource{
return true;
}
/**
* @param int $slot
*
* @return Item
*/
public function getSlot($slot){
$slot = (int) $slot;
if(!isset($this->inventory[$slot])){

View File

@ -25,7 +25,7 @@
namespace PocketMine\Event\Tile;
use PocketMine;
use PocketMine\Event;
use PocketMine\Event\Event;
abstract class TileEvent extends Event{
protected $tile;

View File

@ -25,6 +25,7 @@ use PocketMine\Event;
use PocketMine\Item\Item;
use PocketMine;
use PocketMine\Tile\Tile;
use PocketMine\Event\CancellableEvent;
class TileInventoryChangeEvent extends TileEvent implements CancellableEvent{
public static $handlers;

View File

@ -48,6 +48,9 @@ use PocketMine\Utils\Config;
use PocketMine\Utils\Random;
use PocketMine\Utils\Utils;
use PocketMine;
use PocketMine\NBT\Tag\Byte;
use PocketMine\NBT\Tag\String;
use PocketMine\NBT\Tag\Int;
/**
* Class Level
@ -130,7 +133,7 @@ class Level{
* @return bool|Level
*/
public static function get($name){
if(isset(self::$list[$name])){
if($name !== "" and isset(self::$list[$name])){
return self::$list[$name];
}
@ -553,8 +556,8 @@ class Level{
LevelFormat::getXZ($index, $X, $Z);
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->setData(new Compound("", array(
"Entities" => new Enum("Entities", array()),
"TileEntities" => new Enum("TileEntities", array()),
new Enum("Entities", array()),
new Enum("TileEntities", array()),
)));
$nbt->Entities->setTagType(NBT::TAG_Compound);
$nbt->TileEntities->setTagType(NBT::TAG_Compound);
@ -562,7 +565,7 @@ class Level{
$i = 0;
foreach($this->chunkEntities[$index] as $entity){
if($entity->closed !== true){
$nbt->Entities[$i]->saveNBT();
$entity->saveNBT();
$nbt->Entities[$i] = $entity->namedtag;
++$i;
}
@ -759,14 +762,14 @@ class Level{
$tags = $this->level->getChunkNBT($X, $Z);
if(isset($tags->Entities)){
foreach($tags->Entities as $nbt){
switch($nbt->id){
switch($nbt["id"]){
//TODO: spawn entities
}
}
}
if(isset($tags->TileEntities)){
foreach($tags->TileEntities as $nbt){
switch($nbt->id){
switch($nbt["id"]){
case Tile::CHEST:
new Chest($this, $nbt);
break;

View File

@ -44,8 +44,8 @@ class LevelImport{
$nbt = new NBT(NBT::LITTLE_ENDIAN);
$nbt->read(substr(file_get_contents($this->path . "level.dat"), 8));
$level = $nbt->getData();
if($level->LevelName == ""){
$level->LevelName = "world" . time();
if($level["LevelName"] == ""){
$level["LevelName"] = "world" . time();
}
console("[INFO] Importing Pocket level \"" . $level->LevelName . "\" to PMF format");
unset($level->Player);

View File

@ -41,7 +41,13 @@ use PocketMine\NBT\Tag\Tag;
use PocketMine\Utils\Utils;
use PocketMine;
class NBT implements \ArrayAccess{
/**
* Named Binary Tag encoder/decoder
*
* Class NBT
* @package PocketMine\NBT
*/
class NBT{
const LITTLE_ENDIAN = 0;
const BIG_ENDIAN = 1;
const TAG_End = 0;
@ -63,7 +69,7 @@ class NBT implements \ArrayAccess{
private $data;
public function get($len){
if($len <= 0){
if($len < 0){
$this->offset = strlen($this->buffer) - 1;
return "";
@ -99,6 +105,10 @@ class NBT implements \ArrayAccess{
$this->buffer = "";
}
public function readCompressed($buffer){
$this->read(\gzdecode($buffer));
}
public function write(){
$this->offset = 0;
if($this->data instanceof Compound){
@ -110,6 +120,13 @@ class NBT implements \ArrayAccess{
}
}
public function writeCompressed(){
if(($write = $this->write()) !== false){
return \gzencode($write, 9);
}
return false;
}
public function readTag(){
switch($this->getByte()){
case NBT::TAG_Byte:
@ -230,40 +247,6 @@ class NBT implements \ArrayAccess{
$this->buffer .= $v;
}
public function &__get($name){
$ret = $this->data instanceof Compound ? $this->data[$name] : false;
return $ret;
}
public function __isset($name){
return $this->data instanceof Compound ? isset($this->data[$name]) : false;
}
public function __unset($name){
if($this->data instanceof Compound){
unset($this->data[$name]);
}
}
public function offsetExists($name){
return $this->__isset($name);
}
public function &offsetGet($name){
return $this->__get($name);
}
public function offsetSet($name, $value){
if($this->data instanceof Compound){
$this->data[$name] = $value;
}
}
public function offsetUnset($name){
$this->__unset($name);
}
public function getData(){
return $this->data;
}

View File

@ -24,101 +24,59 @@ namespace PocketMine\NBT\Tag;
use PocketMine;
use PocketMine\NBT\NBT;
class Compound extends NamedTag implements \ArrayAccess, \Iterator{
protected $value = array();
class Compound extends NamedTag implements \ArrayAccess{
public function __construct($name = "", $value = array()){
$this->name = $name;
$this->value = $value;
foreach($value as $tag){
$this->{$tag->getName()} = $tag;
}
}
public function offsetExists($offset){
return isset($this->{$offset});
}
public function offsetGet($offset){
if($this->{$offset} instanceof Tag){
if($this->{$offset} instanceof \ArrayAccess){
return $this->{$offset};
}else{
return $this->{$offset}->getValue();
}
}
return null;
}
public function offsetSet($offset, $value){
if($value instanceof Tag){
$this->{$offset} = $value;
}elseif($this->{$offset} instanceof Tag){
$this->{$offset}->setValue($value);
}
}
public function offsetUnset($offset){
unset($this->{$offset});
}
public function getType(){
return NBT::TAG_Compound;
}
public function rewind(){
reset($this->value);
}
public function current(){
return current($this->value);
}
public function key(){
return key($this->value);
}
public function next(){
return next($this->value);
}
public function valid(){
$key = key($this->value);
return $key !== null and $key !== false;
}
public function offsetExists($name){
return $this->__isset($name);
}
public function &offsetGet($name){
return $this->__get($name);
}
public function offsetSet($name, $value){
$this->value[$name] = $value;
}
public function offsetUnset($name){
$this->__unset($name);
}
public function &__get($name){
$ret = isset($this->value[$name]) ? $this->value[$name] : false;
if(!is_object($ret) or $ret instanceof \ArrayAccess){
return $ret;
} else{
return $ret->getValue();
}
}
/*public function __set($name, $value){
if($value instanceof Tag){
if($value instanceof NamedTag and $value->getName() !== "" and $value->getName() !== false){
$this->value[$value->getName()] = $value;
} else{
$this->value[$name] = $value;
}
}elseif(isset($this->value[$name])){
$this->value[$name]->setValue($value);
}
}*/
public function __isset($name){
return isset($this->value[$name]);
}
public function __unset($name){
unset($this->value[$name]);
}
public function read(NBT $nbt){
$this->value = array();
do{
$tag = $nbt->readTag();
if($tag instanceof NamedTag and $tag->getName() !== ""){
$this->value[$tag->getName()] = $tag;
} elseif(!($tag instanceof End)){
$this->value[] = $tag;
$this->{$tag->getName()} = $tag;
}
} while(!($tag instanceof End) and !$nbt->feof());
}
public function write(NBT $nbt){
foreach($this->value as $tag){
if(!($tag instanceof End)){
foreach($this as $tag){
if($tag instanceof Tag and !($tag instanceof End)){
$nbt->writeTag($tag);
}
}

View File

@ -25,14 +25,42 @@ use PocketMine\NBT\NBT;
use PocketMine;
use PocketMine\NBT\Tag\Enum as TagEnum;
class Enum extends NamedTag implements \ArrayAccess, \Iterator{
class Enum extends NamedTag implements \ArrayAccess{
private $tagType;
protected $value = array();
public function __construct($name = "", $value = array()){
$this->name = $name;
$this->value = $value;
foreach($value as $k => $v){
$this->{$k} = $v;
}
}
public function offsetExists($offset){
return isset($this->{$offset});
}
public function offsetGet($offset){
if($this->{$offset} instanceof Tag){
if($this->{$offset} instanceof \ArrayAccess){
return $this->{$offset};
}else{
return $this->{$offset}->getValue();
}
}
return null;
}
public function offsetSet($offset, $value){
if($value instanceof Tag){
$this->{$offset} = $value;
}elseif($this->{$offset} instanceof Tag){
$this->{$offset}->setValue($value);
}
}
public function offsetUnset($offset){
unset($this->{$offset});
}
public function getType(){
@ -47,61 +75,6 @@ class Enum extends NamedTag implements \ArrayAccess, \Iterator{
return $this->tagType;
}
public function rewind(){
reset($this->value);
}
public function current(){
return current($this->value);
}
public function key(){
return key($this->value);
}
public function next(){
return next($this->value);
}
public function valid(){
$key = key($this->value);
return $key !== null and $key !== false;
}
public function offsetExists($name){
return $this->__isset($name);
}
public function &offsetGet($name){
return $this->__get($name);
}
public function offsetSet($name, $value){
$this->value[$name] = $value;
}
public function offsetUnset($name){
$this->__unset($name);
}
public function &__get($name){
$ret = isset($this->value[$name]) ? $this->value[$name] : false;
if(!is_object($ret) or $ret instanceof \ArrayAccess){
return $ret;
} else{
return $ret->getValue();
}
}
public function __isset($name){
return isset($this->value[$name]);
}
public function __unset($name){
unset($this->value[$name]);
}
public function read(NBT $nbt){
$this->value = array();
$this->tagType = $nbt->getByte();
@ -111,57 +84,57 @@ class Enum extends NamedTag implements \ArrayAccess, \Iterator{
case NBT::TAG_Byte:
$tag = new Byte(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Short:
$tag = new Short(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Int:
$tag = new Int(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Long:
$tag = new Long(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Float:
$tag = new Float(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Double:
$tag = new Double(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Byte_Array:
$tag = new Byte_Array(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_String:
$tag = new String(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Enum:
$tag = new TagEnum(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Compound:
$tag = new Compound(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
case NBT::TAG_Int_Array:
$tag = new Int_Array(false);
$tag->read($nbt);
$this->value[] = $tag;
$this->{$i} = $tag;
break;
}
}
@ -169,22 +142,29 @@ class Enum extends NamedTag implements \ArrayAccess, \Iterator{
public function write(NBT $nbt){
if(!isset($this->tagType)){
foreach($this->value as $tag){
foreach($this as $tag){
if($tag instanceof Tag){
if(!isset($id)){
$id = $tag->getType();
} elseif($id !== $tag->getType()){
}elseif($id !== $tag->getType()){
return false;
}
}
$this->tagType = $id;
}
$this->tagType = @$id;
}
$nbt->putByte($this->tagType);
$nbt->putInt(count($this->value));
foreach($this->value as $tag){
$tags = array();
foreach($this as $tag){
if($tag instanceof Tag){
$tags[] = $tag;
}
}
$nbt->putInt(count($tags));
foreach($tags as $tag){
$tag->write($nbt);
}
}
}
}

View File

@ -64,6 +64,10 @@ class LevelFormat extends PMF{
$this->close();
}
/**
* @param string $file
* @param bool|array $blank default false
*/
public function __construct($file, $blank = false){
$this->chunks = array();
$this->chunkChange = array();
@ -186,8 +190,8 @@ class LevelFormat extends PMF{
console("[NOTICE] Old PMF Level format version #1 detected, upgrading to version #2");
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->setData(new Compound("", array(
"Entities" => new Enum("Entities", array()),
"TileEntities" => new Enum("TileEntities", array())
new Enum("Entities", array()),
new Enum("TileEntities", array())
)));
$nbt->Entities->setTagType(NBT::TAG_Compound);
$nbt->TileEntities->setTagType(NBT::TAG_Compound);
@ -417,8 +421,8 @@ class LevelFormat extends PMF{
);
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->setData(new Compound("", array(
"Entities" => new Enum("Entities", array()),
"TileEntities" => new Enum("TileEntities", array())
new Enum("Entities", array()),
new Enum("TileEntities", array())
)));
$nbt->Entities->setTagType(NBT::TAG_Compound);
$nbt->TileEntities->setTagType(NBT::TAG_Compound);

View File

@ -24,7 +24,6 @@
*/
namespace PocketMine\Recipes;
use PocketMine\BlockAPI;
use PocketMine\Item\Item;
use PocketMine\ServerAPI;
use PocketMine;
@ -241,7 +240,7 @@ abstract class Crafting{
$meta = array_pop($id);
$id = $id[0];
$it = BlockAPI::fromString($id);
$it = Item::fromString($id);
$craftItem = array($it->getID(), intval($meta) & 0xFFFF, intval($item[1]));

View File

@ -35,7 +35,7 @@ class Chest extends Spawnable{
const SLOTS = 27;
public function __construct(Level $level, Compound $nbt){
$nbt->id = Tile::CHEST;
$nbt["id"] = Tile::CHEST;
parent::__construct($level, $nbt);
}

View File

@ -29,6 +29,7 @@ use PocketMine\NBT\Tag\Byte;
use PocketMine\NBT\Tag\Compound;
use PocketMine\NBT\Tag\Short;
use PocketMine\Player;
use PocketMine\Network;
use PocketMine;
trait Container{
@ -52,9 +53,9 @@ trait Container{
$player->windows[$id] = $this;
}
$pk = new ContainerOpenPacket;
$pk = new Network\Protocol\ContainerOpenPacket;
$pk->windowid = $id;
$pk->type = WINDOW_CHEST;
$pk->type = 0;
$pk->slots = is_array($player->windows[$id]) ? Chest::SLOTS << 1 : Chest::SLOTS;
$pk->x = $this->x;
$pk->y = $this->y;
@ -65,7 +66,7 @@ trait Container{
if(is_array($player->windows[$id])){
$all = $this->level->getPlayers();
foreach($player->windows[$id] as $ob){
$pk = new TileEventPacket;
$pk = new Network\Protocol\TileEventPacket;
$pk->x = $ob->x;
$pk->y = $ob->y;
$pk->z = $ob->z;
@ -74,15 +75,15 @@ trait Container{
Player::broadcastPacket($all, $pk);
for($s = 0; $s < Chest::SLOTS; ++$s){
$slot = $ob->getSlot($s);
if($slot->getID() > AIR and $slot->getCount() > 0){
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$slots[] = $slot;
} else{
$slots[] = Item::get(AIR, 0, 0);
$slots[] = Item::get(Item::AIR, 0, 0);
}
}
}
} else{
$pk = new TileEventPacket;
$pk = new Network\Protocol\TileEventPacket;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
@ -91,15 +92,15 @@ trait Container{
Player::broadcastPacket($this->level->getPlayers(), $pk);
for($s = 0; $s < Chest::SLOTS; ++$s){
$slot = $this->getSlot($s);
if($slot->getID() > AIR and $slot->getCount() > 0){
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$slots[] = $slot;
} else{
$slots[] = Item::get(AIR, 0, 0);
$slots[] = Item::get(Item::AIR, 0, 0);
}
}
}
$pk = new ContainerSetContentPacket;
$pk = new Network\Protocol\ContainerSetContentPacket;
$pk->windowid = $id;
$pk->slots = $slots;
$player->dataPacket($pk);
@ -110,9 +111,9 @@ trait Container{
$player->windowCnt = $id = max(2, $player->windowCnt % 99);
$player->windows[$id] = $this;
$pk = new ContainerOpenPacket;
$pk = new Network\Protocol\ContainerOpenPacket;
$pk->windowid = $id;
$pk->type = WINDOW_FURNACE;
$pk->type = 2;
$pk->slots = Furnace::SLOTS;
$pk->x = $this->x;
$pk->y = $this->y;
@ -122,13 +123,13 @@ trait Container{
$slots = array();
for($s = 0; $s < Furnace::SLOTS; ++$s){
$slot = $this->getSlot($s);
if($slot->getID() > AIR and $slot->getCount() > 0){
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$slots[] = $slot;
} else{
$slots[] = Item::get(AIR, 0, 0);
$slots[] = Item::get(Item::AIR, 0, 0);
}
}
$pk = new ContainerSetContentPacket;
$pk = new Network\Protocol\ContainerSetContentPacket;
$pk->windowid = $id;
$pk->slots = $slots;
$player->dataPacket($pk);
@ -139,7 +140,7 @@ trait Container{
public function getSlotIndex($s){
foreach($this->namedtag->Items as $i => $slot){
if($slot->Slot === $s){
if($slot["Slot"] === $s){
return $i;
}
}
@ -150,9 +151,9 @@ trait Container{
public function getSlot($s){
$i = $this->getSlotIndex($s);
if($i === false or $i < 0){
return Item::get(AIR, 0, 0);
return Item::get(Item::AIR, 0, 0);
} else{
return Item::get($this->namedtag->Items[$i]->id, $this->namedtag->Items[$i]->Damage, $this->namedtag->Items[$i]->Count);
return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]);
}
}
@ -165,13 +166,13 @@ trait Container{
$item = $ev->getNewItem();
$d = new Compound(false, array(
"Count" => new Byte("Count", $item->getCount()),
"Slot" => new Byte("Slot", $s),
"id" => new Short("id", $item->getID()),
"Damage" => new Short("Damage", $item->getMetadata()),
new Byte("Count", $item->getCount()),
new Byte("Slot", $s),
new Short("id", $item->getID()),
new Short("Damage", $item->getMetadata()),
));
if($item->getID() === AIR or $item->getCount() <= 0){
if($item->getID() === Item::AIR or $item->getCount() <= 0){
if($i >= 0){
unset($this->namedtag->Items[$i]);
}

View File

@ -33,7 +33,7 @@ class Furnace extends Tile{
const SLOTS = 3;
public function __construct(Level $level, Compound $nbt){
$nbt->id = Tile::FURNACE;
$nbt["id"] = Tile::FURNACE;
parent::__construct($level, $nbt);
if(!isset($this->namedtag->BurnTime) or $this->namedtag->BurnTime < 0){
$this->namedtag->BurnTime = 0;

View File

@ -32,7 +32,7 @@ use PocketMine;
class Sign extends Spawnable{
public function __construct(Level $level, Compound $nbt){
$nbt->id = Tile::SIGN;
$nbt["id"] = Tile::SIGN;
parent::__construct($level, $nbt);
}

View File

@ -33,7 +33,7 @@ class Installer{
const DEFAULT_PORT = 19132;
const DEFAULT_MEMORY = 128;
const DEFAULT_PLAYERS = 20;
const DEFAULT_GAMEMODE = SURVIVAL;
const DEFAULT_GAMEMODE = 0;
private $lang, $config;

View File

@ -46,6 +46,7 @@ COMPILE_OPENSSL="no"
COMPILE_CURL="default"
COMPILE_LIBEDIT="no"
IS_CROSSCOMPILE="no"
IS_WINDOWS="no"
DO_OPTIMIZE="no"
DO_STATIC="no"
while getopts "::t:oj:scxff:" OPTION; do
@ -99,7 +100,27 @@ while getopts "::t:oj:scxff:" OPTION; do
done
if [ "$IS_CROSSCOMPILE" == "yes" ]; then
if [ "$COMPILE_TARGET" == "android" ] || [ "$COMPILE_TARGET" == "android-armv6" ]; then
if [ "$COMPILE_TARGET" == "win" ] || [ "$COMPILE_TARGET" == "win32" ]; then
TOOLCHAIN_PREFIX="i686-w64-mingw32"
[ -z "$march" ] && march=i686;
[ -z "$mtune" ] && mtune=pentium4;
CFLAGS="$CFLAGS -mconsole"
export CC="$TOOLCHAIN_PREFIX-gcc"
CONFIGURE_FLAGS="--host=$TOOLCHAIN_PREFIX --target=$TOOLCHAIN_PREFIX --build=$TOOLCHAIN_PREFIX"
OPENSSL_TARGET="mingw"
IS_WINDOWS="yes"
echo "[INFO] Cross-compiling for Windows 32-bit"
elif [ "$COMPILE_TARGET" == "win64" ]; then
TOOLCHAIN_PREFIX="x86_64-w64-mingw32"
[ -z "$march" ] && march=x86_64;
[ -z "$mtune" ] && mtune=nocona;
CFLAGS="$CFLAGS -mconsole"
export CC="$TOOLCHAIN_PREFIX-gcc"
CONFIGURE_FLAGS="--host=$TOOLCHAIN_PREFIX --target=$TOOLCHAIN_PREFIX --build=$TOOLCHAIN_PREFIX"
OPENSSL_TARGET="mingw"
IS_WINDOWS="yes"
echo "[INFO] Cross-compiling for Windows 64-bit"
elif [ "$COMPILE_TARGET" == "android" ] || [ "$COMPILE_TARGET" == "android-armv6" ]; then
COMPILE_FOR_ANDROID=yes
[ -z "$march" ] && march=armv6;
[ -z "$mtune" ] && mtune=arm1136jf-s;
@ -165,7 +186,7 @@ if [ "$IS_CROSSCOMPILE" == "yes" ]; then
CFLAGS="$CFLAGS -mfpu=neon"
fi
else
echo "Please supply a proper platform [android android-armv6 android-armv7 rpi mac ios ios-armv6 ios-armv7] to cross-compile"
echo "Please supply a proper platform [android android-armv6 android-armv7 rpi mac ios ios-armv6 ios-armv7 win win32 win64] to cross-compile"
exit 1
fi
elif [ "$COMPILE_TARGET" == "rpi" ]; then
@ -444,6 +465,7 @@ RANLIB=$RANLIB ./configure \
--prefix="$DIR/bin/php5" \
$EXTRA_FLAGS \
$CONFIGURE_FLAGS >> "$DIR/install.log" 2>&1
sed -i=".backup" 's/ tests win32/ win32/g' Makefile
echo -n " compiling..."
make -j $THREADS >> "$DIR/install.log" 2>&1
echo -n " installing..."
@ -469,9 +491,22 @@ rm -f ./configure >> "$DIR/install.log" 2>&1
./buildconf --force >> "$DIR/install.log" 2>&1
if [ "$IS_CROSSCOMPILE" == "yes" ]; then
sed -i=".backup" 's/pthreads_working=no/pthreads_working=yes/' ./configure
export LIBS="-lpthread -ldl -lresolv"
if [ "$IS_WINDOWS" != "yes" ]; then
export LIBS="$LIBS -lpthread -ldl -lresolv"
else
export LIBS="$LIBS -lpthread"
fi
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-opcache=no"
fi
if [ "$IS_WINDOWS" != "yes" ]; then
HAVE_PCNTL="--enable-pcntl"
else
HAVE_PCNTL="--disable-pcntl"
cp -f ./win32/build/config.* ./main >> "$DIR/install.log" 2>&1
sed 's:@PREFIX@:$DIR/bin/php5:' ./main/config.w32.h.in > ./wmain/config.w32.h 2>> "$DIR/install.log"
fi
RANLIB=$RANLIB ./configure $PHP_OPTIMIZATION--prefix="$DIR/bin/php5" \
--exec-prefix="$DIR/bin/php5" \
--with-curl="$HAVE_CURL" \
@ -497,10 +532,10 @@ $HAVE_LIBEDIT \
--enable-shared=no \
--enable-static=yes \
--enable-shmop \
--enable-pcntl \
--enable-pthreads \
--enable-maintainer-zts \
--enable-zend-signals \
$HAVE_PCNTL \
$HAVE_MYSQLI \
--enable-embedded-mysqli \
--enable-bcmath \
@ -558,10 +593,10 @@ echo " done!"
cd "$DIR"
echo -n "[INFO] Cleaning up..."
rm -r -f install_data/ >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/curl >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/curl-config >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/c_rehash >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/openssl >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/curl* >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/curl-config* >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/c_rehash* >> "$DIR/install.log" 2>&1
rm -f bin/php5/bin/openssl* >> "$DIR/install.log" 2>&1
rm -r -f bin/php5/man >> "$DIR/install.log" 2>&1
rm -r -f bin/php5/php >> "$DIR/install.log" 2>&1
rm -r -f bin/php5/share >> "$DIR/install.log" 2>&1

View File

@ -57,7 +57,7 @@ class AsyncMultipleQueue extends Thread{
private function get($len){
$str = "";
if($len <= 0){
return $len;
return "";
}
$offset = 0;
while(!isset($str{$len - 1})){

View File

@ -59,7 +59,7 @@ class ServerSuiteTest{
public function hook(){
testCase("event fired", true, true);
$server = \PocketMine\ServerAPI::request();
//testCase("defaultgamemode", $server->getGamemode(), "survival");
testCase("defaultgamemode", $server->getGamemode(), "survival");
//Everything done!