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)
)),
"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)
)),
"Rotation" => new Enum("Rotation", array(
0 => new Float(0, 0.0),
1 => 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 Enum("Pos", array(
new Double(0, $spawn->x),
new Double(1, $spawn->y),
new Double(2, $spawn->z)
)),
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)
)),
new Enum("Rotation", array(
new Float(0, 0.0),
new Float(1, 0.0)
)),
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){
if(!isset($id)){
$id = $tag->getType();
} elseif($id !== $tag->getType()){
return false;
foreach($this as $tag){
if($tag instanceof Tag){
if(!isset($id)){
$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){
$tag->write($nbt);
$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!