Reworked Level things to handle new NBT structure

This commit is contained in:
Shoghi Cervantes 2014-02-27 00:03:53 +01:00
parent 398fbbfb31
commit 4a2852bb90
10 changed files with 179 additions and 518 deletions

View File

@ -128,14 +128,14 @@ class LevelAPI{
foreach($this->server->api->player->getAll($level) as $player){
$player->teleport($this->server->spawn);
}
foreach($this->server->api->entity->getAll($level) as $entity){
/*foreach($this->server->api->entity->getAll($level) as $entity){
if($entity->class !== ENTITY_PLAYER){
$entity->close();
}
}
foreach($this->server->api->tile->getAll($level) as $tile){
}*/
/*foreach($this->server->api->tile->getAll($level) as $tile){
$tile->close();
}
}*/
$level->close();
unset($this->levels[$name]);
return true;
@ -159,9 +159,8 @@ class LevelAPI{
if(file_exists($path."tileEntities.yml")){
@rename($path."tileEntities.yml", $path."tiles.yml");
}
$tiles = new Config($path."tiles.yml", Config::YAML);
$blockUpdates = new Config($path."bupdates.yml", Config::YAML);
$this->levels[$name] = new Level($level, $entities, $tiles, $blockUpdates, $name);
$this->levels[$name] = new Level($level, $name);
foreach($entities->getAll() as $entity){
if(!isset($entity["id"])){
break;
@ -191,11 +190,68 @@ class LevelAPI{
}
}
if(file_exists($path ."tiles.yml")){
$tiles = new Config($path."tiles.yml", Config::YAML);
foreach($tiles->getAll() as $tile){
if(!isset($tile["id"])){
continue;
}
$this->levels[$name]->loadChunk($tile["x"] >> 4, $tile["z"] >> 4);
$nbt = new NBTTag_Compound(false, array());
foreach($tile as $index => $data){
switch($index){
case "Items":
$tag = new NBTTag_List("Items", array());
$tag->setTagType(NBTTag::TAG_Compound);
foreach($data as $slot => $fields){
$tag->{$slot} = new NBTTag_Compound(false, array(
"Count" => new NBTTag_Byte("Count", $fields["Count"]),
"Slot" => new NBTTag_Short("Slot", $fields["Slot"]),
"Damage" => new NBTTag_Short("Damage", $fields["Damage"]),
"id" => new NBTTag_String("id", $fields["id"])
));
}
$nbt["Items"] = $tag;
break;
case "id":
case "Text1":
case "Text2":
case "Text3":
case "Text4":
$nbt[$index] = new NBTTag_String($index, $data);
break;
case "x":
case "y":
case "z":
case "pairx":
case "pairz":
$nbt[$index] = new NBTTag_Int($index, $data);
break;
case "BurnTime":
case "CookTime":
case "MaxTime":
$nbt[$index] = new NBTTag_Short($index, $data);
break;
}
$t = $this->server->api->tile->add($this->levels[$name], $tile["id"], $tile["x"], $tile["y"], $tile["z"], $tile);
}
switch($tile["id"]){
case Tile::FURNACE:
new FurnaceTile($this->levels[$name], $nbt);
break;
case Tile::CHEST:
new ChestTile($this->levels[$name], $nbt);
break;
case Tile::SIGN:
new SignTile($this->levels[$name], $nbt);
break;
}
}
unlink($path ."tiles.yml");
$this->levels[$name]->save(true, true);
}
foreach($blockUpdates->getAll() as $bupdate){

View File

@ -73,11 +73,6 @@ class ServerAPI{
*/
public $player;
/**
* @var TileAPI
*/
public $tile;
/**
* @return MainServer
*/
@ -212,7 +207,6 @@ class ServerAPI{
$this->loadAPI("chat", "ChatAPI");
$this->loadAPI("ban", "BanAPI");
$this->loadAPI("entity", "EntityAPI");
$this->loadAPI("tile", "TileAPI");
$this->loadAPI("player", "PlayerAPI");
$this->loadAPI("time", "TimeAPI");

View File

@ -562,7 +562,7 @@ class Player{
switch($event){
case "tile.update":
if($data->level === $this->level){
if($data->class === TILE_FURNACE){
if($data->class === Tile::FURNACE){
foreach($this->windows as $id => $w){
if($w === $data){
$pk = new ContainerSetDataPacket;
@ -2058,7 +2058,7 @@ class Player{
$pk->case2 = 0;
$this->server->api->player->broadcastPacket($this->level->players, $pk);
}
}elseif($this->windows[$packet->windowid]->class === TILE_CHEST){
}elseif($this->windows[$packet->windowid]->class === Tile::CHEST){
$pk = new TileEventPacket;
$pk->x = $this->windows[$packet->windowid]->x;
$pk->y = $this->windows[$packet->windowid]->y;
@ -2136,14 +2136,14 @@ class Player{
if(is_array($this->windows[$packet->windowid])){
$tiles = $this->windows[$packet->windowid];
if($packet->slot >= 0 and $packet->slot < CHEST_SLOTS){
if($packet->slot >= 0 and $packet->slot < ChestTile::SLOTS){
$tile = $tiles[0];
$slotn = $packet->slot;
$offset = 0;
}elseif($packet->slot >= CHEST_SLOTS and $packet->slot <= (CHEST_SLOTS << 1)){
}elseif($packet->slot >= ChestTile::SLOTS and $packet->slot <= (ChestTile::SLOTS << 1)){
$tile = $tiles[1];
$slotn = $packet->slot - CHEST_SLOTS;
$offset = CHEST_SLOTS;
$slotn = $packet->slot - ChestTile::SLOTS;
$offset = ChestTile::SLOTS;
}else{
break;
}
@ -2185,7 +2185,7 @@ class Player{
$tile->setSlot($slotn, $item, true, $offset);
}else{
$tile = $this->windows[$packet->windowid];
if(($tile->class !== TILE_CHEST and $tile->class !== TILE_FURNACE) or $packet->slot < 0 or ($tile->class === TILE_CHEST and $packet->slot >= CHEST_SLOTS) or ($tile->class === TILE_FURNACE and $packet->slot >= FURNACE_SLOTS)){
if(($tile->class !== Tile::CHEST and $tile->class !== Tile::FURNACE) or $packet->slot < 0 or ($tile->class === Tile::CHEST and $packet->slot >= ChestTile::SLOTS) or ($tile->class === Tile::FURNACE and $packet->slot >= FurnaceTile::SLOTS)){
break;
}
$item = BlockAPI::getItem($packet->item->getID(), $packet->item->getMetadata(), $packet->item->count);
@ -2206,7 +2206,7 @@ class Player{
break;
}
if($tile->class === TILE_FURNACE and $packet->slot == 2){
if($tile->class === Tile::FURNACE and $packet->slot == 2){
switch($slot->getID()){
case IRON_INGOT:
AchievementAPI::grantAchievement($this, "acquireIron");
@ -2245,13 +2245,13 @@ class Player{
$this->craftingItems = array();
$this->toCraft = array();
$t = $this->server->api->tile->get(new Position($packet->x, $packet->y, $packet->z, $this->level));
if(($t instanceof Tile) and $t->class === TILE_SIGN){
if(($t instanceof Tile) and $t->class === Tile::SIGN){
if($t->data["creator"] !== $this->username){
$t->spawn($this);
}else{
$nbt = new NBT();
$nbt->read($packet->namedtag);
if($nbt->id !== TILE_SIGN){
if($nbt->id !== Tile::SIGN){
$t->spawn($this);
}else{
$t->setText($nbt->Text1, $nbt->Text2, $nbt->Text3, $nbt->Text4);

View File

@ -69,11 +69,3 @@ define("ENTITY_ITEM", 4);
define("ENTITY_FALLING", 5);
define("FALLING_SAND", 66);
//TileEntities
define("TILE_SIGN", "Sign");
define("TILE_CHEST", "Chest");
define("CHEST_SLOTS", 27);
define("TILE_FURNACE", "Furnace");
define("FURNACE_SLOTS", 3);

View File

@ -93,7 +93,7 @@ if($errors > 0){
$sha1sum = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
/***REM_START***/
require_once(FILE_PATH."/src/math/Vector3.php");
require_once(FILE_PATH."/src/world/Position.php");
require_once(FILE_PATH."/src/math/Position.php");
require_once(FILE_PATH."/src/pmf/PMF.php");
require_all(FILE_PATH . "src/", array("entity", "Entity.php")); //REMOVE LATER!!!!

View File

@ -224,9 +224,11 @@ function getTrace($start = 1){
$j = 0;
for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){
$params = "";
if(isset($trace[$i]["args"])){
foreach($trace[$i]["args"] as $name => $value){
$params .= (is_object($value) ? get_class($value)." ".(method_exists($value, "__toString") ? $value->__toString() : "object"):gettype($value)." ".@strval($value)).", ";
}
}
$messages[] = "#$j ".(isset($trace[$i]["file"]) ? $trace[$i]["file"]:"")."(".(isset($trace[$i]["line"]) ? $trace[$i]["line"]:"")."): ".(isset($trace[$i]["class"]) ? $trace[$i]["class"].$trace[$i]["type"]:"").$trace[$i]["function"]."(".substr($params, 0, -2).")";
}
return $messages;

View File

@ -176,9 +176,11 @@ class PMFLevel extends PMF{
console("[NOTICE] Old PMF Level format version #1 detected, upgrading to version #2");
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->setData(new NBTTag_Compound("", array(
new NBTTag_Compound("Entities", array()),
new NBTTag_Compound("TileEntities", array())
"Entities" => new NBTTag_List("Entities", array()),
"TileEntities" => new NBTTag_List("TileEntities", array())
)));
$nbt->Entities->setTagType(NBTTag::TAG_Compound);
$nbt->TileEntities->setTagType(NBTTag::TAG_Compound);
$namedtag = $nbt->write();
$namedtag = Utils::writeInt(strlen($namedtag)) . $namedtag;
foreach(glob(dirname($this->file)."/chunks/*/*.*.pmc") as $chunkFile){
@ -273,7 +275,7 @@ class PMFLevel extends PMF{
$offset += 4;
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->read(substr($chunk, $offset, $len));
$this->chunkInfo[2] = $nbt;
$this->chunkInfo[$index][2] = $nbt;
$offset += $len;
$this->chunks[$index] = array();
$this->chunkChange[$index] = array(-1 => false);
@ -571,14 +573,31 @@ class PMFLevel extends PMF{
return false;
}
public function saveChunk($X, $Z){
public function getChunkNBT($X, $Z){
if(!$this->isChunkLoaded($X, $Z) and $this->loadChunk($X, $Z) === false){
return false;
}
$index = self::getIndex($X, $Z);
return $this->chunkInfo[$index][2];
}
public function setChunkNBT($X, $Z, NBT $nbt){
if(!$this->isChunkLoaded($X, $Z) and $this->loadChunk($X, $Z) === false){
return false;
}
$index = self::getIndex($X, $Z);
$this->chunkChange[$index][-1] = true;
$this->chunkInfo[$index][2] = $nbt;
}
public function saveChunk($X, $Z, $force = false){
$X = (int) $X;
$Z = (int) $Z;
if(!$this->isChunkLoaded($X, $Z)){
return false;
}
$index = self::getIndex($X, $Z);
if(!isset($this->chunkChange[$index]) or $this->chunkChange[$index][-1] === false){//No changes in chunk
if($force !== true and (!isset($this->chunkChange[$index]) or $this->chunkChange[$index][-1] === false)){//No changes in chunk
return true;
}
@ -640,10 +659,10 @@ class PMFLevel extends PMF{
return file_exists($this->getChunkPath($X, $Z));
}
public function doSaveRound(){
public function doSaveRound($force = false){
foreach($this->chunks as $index => $chunk){
self::getXZ($index, $X, $Z);
$this->saveChunk($X, $Z);
$this->saveChunk($X, $Z, $force);
}
}

View File

@ -24,21 +24,15 @@ class Level{
public $chunkEntities = array();
public $tiles = array();
public $entitiesConfig;
public $tilesConfig;
public $blockUpdatesConfig;
public $chunkTiles = array();
public $nextSave, $players = array(), $level;
private $time, $startCheck, $startTime, $server, $name, $usedChunks, $changedBlocks, $changedCount, $stopTime, $generator;
public function __construct(PMFLevel $level, Config $entities, Config $tiles, Config $blockUpdates, $name){
public function __construct(PMFLevel $level, $name){
$this->server = ServerAPI::request();
$this->level = $level;
$this->level->level = $this;
$this->entitiesConfig = $entities;
$this->tilesConfig = $tiles;
$this->blockUpdatesConfig = $blockUpdates;
$this->startTime = $this->time = (int) $this->level->getData("time");
$this->nextSave = $this->startCheck = microtime(true);
$this->nextSave += 90;
@ -60,6 +54,7 @@ class Level{
}
}
$this->generator->init($this, new Random($this->level->levelData["seed"]));
$this->loadChunk(8, 8);
}
public function close(){
@ -69,12 +64,9 @@ class Level{
public function useChunk($X, $Z, Player $player){
$index = PMFLevel::getIndex($X, $Z);
if(!isset($this->usedChunks[$index])){
$this->usedChunks[$index] = array();
$this->loadChunk($X, $Z);
}
$this->usedChunks[$index][$player->CID] = true;
if(isset($this->level)){
$this->level->loadChunk($X, $Z);
}
}
public function freeAllChunks(Player $player){
@ -193,16 +185,38 @@ class Level{
}
if($extra !== false){
$this->doSaveRoundExtra();
}
$this->level->setData("time", (int) $this->time);
$this->level->doSaveRound();
$this->level->doSaveRound($force);
$this->level->saveData();
$this->nextSave = microtime(true) + 45;
}
protected function doSaveRoundExtra(){
foreach($this->usedChunks as $index => $d){
PMFLevel::getXZ($index, $X, $Z);
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->setData(new NBTTag_Compound("", array(
"Entities" => new NBTTag_List("Entities", array()),
"TileEntities" => new NBTTag_List("TileEntities", array()),
)));
$nbt->Entities->setTagType(NBTTag::TAG_Compound);
$nbt->TileEntities->setTagType(NBTTag::TAG_Compound);
$i = 0;
foreach($this->chunkTiles[$index] as $tile){
if($tile->closed !== true){
$nbt->TileEntities[$i] = $tile->namedtag;
++$i;
}
}
$this->level->setChunkNBT($X, $Z, $nbt);
}
}
public function getBlockRaw(Vector3 $pos){
$b = $this->level->getBlock($pos->x, $pos->y, $pos->z);
return BlockAPI::get($b[0], $b[1], new Position($pos->x, $pos->y, $pos->z, $this));
@ -310,11 +324,48 @@ class Level{
return $this->level->setMiniChunk($X, $Z, $Y, $data);
}
public function getChunkEntities($X, $Z){
$index = PMFLevel::getIndex($X, $Z);
if(isset($this->usedChunks[$index]) or $this->level->loadChunk($X, $Z) === true){
return $this->chunkEntities[$index];
}
return array();
}
public function getChunkTiles($X, $Z){
$index = PMFLevel::getIndex($X, $Z);
if(isset($this->usedChunks[$index]) or $this->level->loadChunk($X, $Z) === true){
return $this->chunkTiles[$index];
}
return array();
}
public function loadChunk($X, $Z){
if(!isset($this->level)){
return false;
}
return $this->level->loadChunk($X, $Z);
$index = PMFLevel::getIndex($X, $Z);
if(isset($this->usedChunks[$index])){
return true;
}elseif($this->level->loadChunk($X, $Z) !== false){
$this->usedChunks[$index] = array();
$this->chunkTiles[$index] = array();
$this->chunkEntities[$index] = array();
foreach($this->level->getChunkNBT($X, $Z)->TileEntities as $nbt){
switch($nbt->id){
case Tile::CHEST:
new ChestTile($this, $nbt);
break;
case Tile::FURNACE:
new FurnaceTile($this, $nbt);
break;
case Tile::SIGN:
new SignTile($this, $nbt);
break;
}
}
}
return false;
}
public function unloadChunk($X, $Z, $force = false){
@ -325,6 +376,9 @@ class Level{
if($force !== true and $this->isSpawnChunk($X, $Z)){
return false;
}
unset($this->usedChunks[$index]);
unset($this->chunkEntities[$index]);
unset($this->chunkTiles[$index]);
Cache::remove("world:{$this->name}:$X:$Z");
return $this->level->unloadChunk($X, $Z, $this->server->saveEnabled);
}

View File

@ -1,456 +0,0 @@
<?php
/**
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
class Tile extends Position{
public $name;
public $normal;
public $id;
public $x;
public $y;
public $z;
public $data;
public $class;
public $attach;
public $metadata;
public $closed;
private $lastUpdate;
private $scheduledUpdate;
private $server;
function __construct(Level $level, $id, $class, $x, $y, $z, $data = array()){
$this->server = ServerAPI::request();
$this->level = $level;
$this->normal = true;
$this->class = $class;
$this->data = $data;
$this->closed = false;
if($class === false){
$this->closed = true;
}
$this->name = "";
$this->lastUpdate = microtime(true);
$this->scheduledUpdate = false;
$this->id = (int) $id;
$this->x = (int) $x;
$this->y = (int) $y;
$this->z = (int) $z;
$this->server->query("INSERT OR REPLACE INTO tiles (ID, level, class, x, y, z) VALUES (".$this->id.", '".$this->level->getName()."', '".$this->class."', ".$this->x.", ".$this->y.", ".$this->z.");");
switch($this->class){
case TILE_CHEST:
case TILE_SIGN:
$this->server->query("UPDATE tiles SET spawnable = 1 WHERE ID = ".$this->id.";");
break;
case TILE_FURNACE:
if(!isset($this->data["BurnTime"]) or $this->data["BurnTime"] < 0){
$this->data["BurnTime"] = 0;
}
if(!isset($this->data["CookTime"]) or $this->data["CookTime"] < 0 or ($this->data["BurnTime"] === 0 and $this->data["CookTime"] > 0)){
$this->data["CookTime"] = 0;
}
if(!isset($this->data["MaxTime"])){
$this->data["MaxTime"] = $this->data["BurnTime"];
$this->data["BurnTicks"] = 0;
}
if($this->data["BurnTime"] > 0){
$this->update();
}
break;
}
}
public function isPaired(){
if($this->class !== TILE_CHEST){
return false;
}
if(!isset($this->data["pairx"]) or !isset($this->data["pairz"])){
return false;
}
return true;
}
public function getPair(){
if($this->isPaired()){
return $this->server->api->tile->get(new Position((int) $this->data["pairx"], $this->y, (int) $this->data["pairz"], $this->level));
}
return false;
}
public function pairWith(Tile $tile){
if($this->isPaired()or $tile->isPaired()){
return false;
}
$this->data["pairx"] = $tile->x;
$this->data["pairz"] = $tile->z;
$tile->data["pairx"] = $this->x;
$tile->data["pairz"] = $this->z;
$this->server->api->tile->spawnToAll($this);
$this->server->api->tile->spawnToAll($tile);
$this->server->handle("tile.update", $this);
$this->server->handle("tile.update", $tile);
}
public function unpair(){
if(!$this->isPaired()){
return false;
}
$tile = $this->getPair();
unset($this->data["pairx"], $this->data["pairz"], $tile->data["pairx"], $tile->data["pairz"]);
$this->server->api->tile->spawnToAll($this);
$this->server->handle("tile.update", $this);
if($tile instanceof Tile){
$this->server->api->tile->spawnToAll($tile);
$this->server->handle("tile.update", $tile);
}
}
public function openInventory(Player $player){
if($this->class === TILE_CHEST){
$player->windowCnt++;
$player->windowCnt = $id = max(2, $player->windowCnt % 99);
if(($pair = $this->getPair()) !== false){
if(($pair->x + ($pair->z << 13)) > ($this->x + ($this->z << 13))){ //Order them correctly
$player->windows[$id] = array(
$pair,
$this
);
}else{
$player->windows[$id] = array(
$this,
$pair
);
}
}else{
$player->windows[$id] = $this;
}
$pk = new ContainerOpenPacket;
$pk->windowid = $id;
$pk->type = WINDOW_CHEST;
$pk->slots = is_array($player->windows[$id]) ? CHEST_SLOTS << 1:CHEST_SLOTS;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$player->dataPacket($pk);
$slots = array();
if(is_array($player->windows[$id])){
$all = $this->server->api->player->getAll($this->level);
foreach($player->windows[$id] as $ob){
$pk = new TileEventPacket;
$pk->x = $ob->x;
$pk->y = $ob->y;
$pk->z = $ob->z;
$pk->case1 = 1;
$pk->case2 = 2;
$this->server->api->player->broadcastPacket($all, $pk);
for($s = 0; $s < CHEST_SLOTS; ++$s){
$slot = $ob->getSlot($s);
if($slot->getID() > AIR and $slot->count > 0){
$slots[] = $slot;
}else{
$slots[] = BlockAPI::getItem(AIR, 0, 0);
}
}
}
}else{
$pk = new TileEventPacket;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->case1 = 1;
$pk->case2 = 2;
$this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), $pk);
for($s = 0; $s < CHEST_SLOTS; ++$s){
$slot = $this->getSlot($s);
if($slot->getID() > AIR and $slot->count > 0){
$slots[] = $slot;
}else{
$slots[] = BlockAPI::getItem(AIR, 0, 0);
}
}
}
$pk = new ContainerSetContentPacket;
$pk->windowid = $id;
$pk->slots = $slots;
$player->dataPacket($pk);
return true;
}elseif($this->class === TILE_FURNACE){
$player->windowCnt++;
$player->windowCnt = $id = max(2, $player->windowCnt % 99);
$player->windows[$id] = $this;
$pk = new ContainerOpenPacket;
$pk->windowid = $id;
$pk->type = WINDOW_FURNACE;
$pk->slots = FURNACE_SLOTS;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$player->dataPacket($pk);
$slots = array();
for($s = 0; $s < FURNACE_SLOTS; ++$s){
$slot = $this->getSlot($s);
if($slot->getID() > AIR and $slot->count > 0){
$slots[] = $slot;
}else{
$slots[] = BlockAPI::getItem(AIR, 0, 0);
}
}
$pk = new ContainerSetContentPacket;
$pk->windowid = $id;
$pk->slots = $slots;
$player->dataPacket($pk);
return true;
}
}
public function update(){
if($this->closed === true){
return false;
}
if($this->class === TILE_FURNACE){
$fuel = $this->getSlot(1);
$raw = $this->getSlot(0);
$product = $this->getSlot(2);
$smelt = $raw->getSmeltItem();
$canSmelt = ($smelt !== false and $raw->count > 0 and (($product->getID() === $smelt->getID() and $product->getMetadata() === $smelt->getMetadata() and $product->count < $product->getMaxStackSize()) or $product->getID() === AIR));
if($this->data["BurnTime"] <= 0 and $canSmelt and $fuel->getFuelTime() !== false and $fuel->count > 0){
$this->lastUpdate = microtime(true);
$this->data["MaxTime"] = $this->data["BurnTime"] = floor($fuel->getFuelTime() * 20);
$this->data["BurnTicks"] = 0;
--$fuel->count;
if($fuel->count === 0){
$fuel = BlockAPI::getItem(AIR, 0, 0);
}
$this->setSlot(1, $fuel, false);
$current = $this->level->getBlock($this);
if($current->getID() === FURNACE){
$this->level->setBlock($this, BlockAPI::get(BURNING_FURNACE, $current->getMetadata()), true, false, true);
}
}
if($this->data["BurnTime"] > 0){
$ticks = (microtime(true) - $this->lastUpdate) * 20;
$this->data["BurnTime"] -= $ticks;
$this->data["BurnTicks"] = ceil(($this->data["BurnTime"] / $this->data["MaxTime"]) * 200);
if($smelt !== false and $canSmelt){
$this->data["CookTime"] += $ticks;
if($this->data["CookTime"] >= 200){ //10 seconds
$product = BlockAPI::getItem($smelt->getID(), $smelt->getMetadata(), $product->count + 1);
$this->setSlot(2, $product, false);
--$raw->count;
if($raw->count === 0){
$raw = BlockAPI::getItem(AIR, 0, 0);
}
$this->setSlot(0, $raw, false);
$this->data["CookTime"] -= 200;
}
}elseif($this->data["BurnTime"] <= 0){
$this->data["BurnTime"] = 0;
$this->data["CookTime"] = 0;
$this->data["BurnTicks"] = 0;
}else{
$this->data["CookTime"] = 0;
}
$this->server->schedule(2, array($this, "update"));
$this->scheduledUpdate = true;
}else{
$current = $this->level->getBlock($this);
if($current->getID() === BURNING_FURNACE){
$this->level->setBlock($this, BlockAPI::get(FURNACE, $current->getMetadata()), true, false, true);
}
$this->data["CookTime"] = 0;
$this->data["BurnTime"] = 0;
$this->data["BurnTicks"] = 0;
$this->scheduledUpdate = false;
}
}
$this->server->handle("tile.update", $this);
$this->lastUpdate = microtime(true);
}
public function getSlotIndex($s){
if($this->class !== TILE_CHEST and $this->class !== TILE_FURNACE){
return false;
}
foreach($this->data["Items"] as $i => $slot){
if($slot["Slot"] === $s){
return $i;
}
}
return -1;
}
public function getSlot($s){
$i = $this->getSlotIndex($s);
if($i === false or $i < 0){
return BlockAPI::getItem(AIR, 0, 0);
}else{
return BlockAPI::getItem($this->data["Items"][$i]["id"], $this->data["Items"][$i]["Damage"], $this->data["Items"][$i]["Count"]);
}
}
public function setSlot($s, Item $item, $update = true, $offset = 0){
$i = $this->getSlotIndex($s);
$d = array(
"Count" => $item->count,
"Slot" => $s,
"id" => $item->getID(),
"Damage" => $item->getMetadata(),
);
if($i === false){
return false;
}elseif($item->getID() === AIR or $item->count <= 0){
if($i >= 0){
unset($this->data["Items"][$i]);
}
}elseif($i < 0){
$this->data["Items"][] = $d;
}else{
$this->data["Items"][$i] = $d;
}
$this->server->api->dhandle("tile.container.slot", array(
"tile" => $this,
"slot" => $s,
"offset" => $offset,
"slotdata" => $item,
));
if($update === true and $this->scheduledUpdate === false){
$this->update();
}
return true;
}
public function spawn($player){
if($this->closed){
return false;
}
if(!($player instanceof Player)){
$player = $this->server->api->player->get($player);
}
switch($this->class){
case TILE_CHEST:
$nbt = new NBT(NBT::LITTLE_ENDIAN);
if($this->isPaired()){
$nbt->setData(new NBTTag_Compound("", array(
new NBTTag_String("id", $this->class),
new NBTTag_Int("x", (int) $this->x),
new NBTTag_Int("y", (int) $this->y),
new NBTTag_Int("z", (int) $this->z),
new NBTTag_Int("pairx", (int) $this->data["pairx"]),
new NBTTag_Int("pairz", (int) $this->data["pairz"])
)));
}else{
$nbt->setData(new NBTTag_Compound("", array(
new NBTTag_String("id", $this->class),
new NBTTag_Int("x", (int) $this->x),
new NBTTag_Int("y", (int) $this->y),
new NBTTag_Int("z", (int) $this->z)
)));
}
$pk = new EntityDataPacket;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->namedtag = $nbt->write();
$player->dataPacket($pk);
break;
case TILE_SIGN:
$nbt = new NBT(NBT::LITTLE_ENDIAN);
$nbt->setData(new NBTTag_Compound("", array(
new NBTTag_String("Text1", $this->data["Text1"]),
new NBTTag_String("Text2", $this->data["Text2"]),
new NBTTag_String("Text3", $this->data["Text3"]),
new NBTTag_String("Text4", $this->data["Text4"]),
new NBTTag_String("id", $this->class),
new NBTTag_Int("x", (int) $this->x),
new NBTTag_Int("y", (int) $this->y),
new NBTTag_Int("z", (int) $this->z)
)));
$pk = new EntityDataPacket;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->namedtag = $nbt->write();
$player->dataPacket($pk);
break;
}
}
public function setText($line1 = "", $line2 = "", $line3 = "", $line4 = ""){
if($this->class !== TILE_SIGN){
return false;
}
$this->data["Text1"] = $line1;
$this->data["Text2"] = $line2;
$this->data["Text3"] = $line3;
$this->data["Text4"] = $line4;
$this->server->api->tile->spawnToAll($this);
$this->server->handle("tile.update", $this);
return true;
}
public function getText(){
return array(
$this->data["Text1"],
$this->data["Text2"],
$this->data["Text3"],
$this->data["Text4"]
);
}
public function close(){
if($this->closed === false){
$this->closed = true;
$this->server->api->tile->remove($this->id);
}
}
public function __destruct(){
$this->close();
}
public function getName(){
return $this->name;
}
public function setPosition(Vector3 $pos){
if($pos instanceof Position){
$this->level = $pos->level;
$this->server->query("UPDATE tiles SET level = '".$this->level->getName()."' WHERE ID = ".$this->id.";");
}
$this->x = (int) $pos->x;
$this->y = (int) $pos->y;
$this->z = (int) $pos->z;
$this->server->query("UPDATE tiles SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE ID = ".$this->id.";");
}
}