diff --git a/src/API/LevelAPI.php b/src/API/LevelAPI.php index 9d9b1565d..fe1ca26c4 100644 --- a/src/API/LevelAPI.php +++ b/src/API/LevelAPI.php @@ -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{ } } - foreach($tiles->getAll() as $tile){ - if(!isset($tile["id"])){ - break; + 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; + } + } + 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; + } } - $t = $this->server->api->tile->add($this->levels[$name], $tile["id"], $tile["x"], $tile["y"], $tile["z"], $tile); + unlink($path ."tiles.yml"); + $this->levels[$name]->save(true, true); } foreach($blockUpdates->getAll() as $bupdate){ diff --git a/src/API/ServerAPI.php b/src/API/ServerAPI.php index f0aa5afcd..d3096d041 100644 --- a/src/API/ServerAPI.php +++ b/src/API/ServerAPI.php @@ -73,11 +73,6 @@ class ServerAPI{ */ public $player; - /** - * @var TileAPI - */ - public $tile; - /** * @return MainServer */ @@ -211,8 +206,7 @@ class ServerAPI{ $this->loadAPI("block", "BlockAPI"); $this->loadAPI("chat", "ChatAPI"); $this->loadAPI("ban", "BanAPI"); - $this->loadAPI("entity", "EntityAPI"); - $this->loadAPI("tile", "TileAPI"); + $this->loadAPI("entity", "EntityAPI"); $this->loadAPI("player", "PlayerAPI"); $this->loadAPI("time", "TimeAPI"); diff --git a/src/Player.php b/src/Player.php index 67ce4d822..e0e0b4cb9 100644 --- a/src/Player.php +++ b/src/Player.php @@ -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); diff --git a/src/constants/GeneralConstants.php b/src/constants/GeneralConstants.php index b60b45aca..6a6733643 100644 --- a/src/constants/GeneralConstants.php +++ b/src/constants/GeneralConstants.php @@ -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); \ No newline at end of file diff --git a/src/dependencies.php b/src/dependencies.php index 7d95b79d8..ac3167356 100644 --- a/src/dependencies.php +++ b/src/dependencies.php @@ -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!!!! diff --git a/src/functions.php b/src/functions.php index d669ffb6d..3a13e69e4 100644 --- a/src/functions.php +++ b/src/functions.php @@ -224,8 +224,10 @@ function getTrace($start = 1){ $j = 0; for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){ $params = ""; - 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)).", "; + 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).")"; } diff --git a/src/world/Position.php b/src/math/Position.php similarity index 100% rename from src/world/Position.php rename to src/math/Position.php diff --git a/src/pmf/PMFLevel.php b/src/pmf/PMFLevel.php index f7fecfb0a..5db62028b 100644 --- a/src/pmf/PMFLevel.php +++ b/src/pmf/PMFLevel.php @@ -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); } } diff --git a/src/world/Level.php b/src/world/Level.php index 56948cfe8..1549f5c48 100644 --- a/src/world/Level.php +++ b/src/world/Level.php @@ -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; @@ -58,8 +52,9 @@ class Level{ }else{ $this->generator = new NormalGenerator(); } - } + } $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); } diff --git a/src/world/Tile.php b/src/world/Tile.php deleted file mode 100644 index b44dc20ce..000000000 --- a/src/world/Tile.php +++ /dev/null @@ -1,456 +0,0 @@ -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.";"); - } - -}