PocketMine-MP  1.4 - API 1.10.0
 All Classes Namespaces Functions Variables Pages
tile/Furnace.php
1 <?php
2 
3 /*
4  *
5  * ____ _ _ __ __ _ __ __ ____
6  * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7  * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8  * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9  * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * @author PocketMine Team
17  * @link http://www.pocketmine.net/
18  *
19  *
20 */
21 
22 namespace pocketmine\tile;
23 
38 
39 class Furnace extends Tile implements InventoryHolder, Container{
41  protected $inventory;
42 
43  public function __construct(FullChunk $chunk, Compound $nbt){
44  parent::__construct($chunk, $nbt);
45  $this->inventory = new FurnaceInventory($this);
46 
47  if(!isset($this->namedtag->Items) or !($this->namedtag->Items instanceof Enum)){
48  $this->namedtag->Items = new Enum("Inventory", []);
49  $this->namedtag->Items->setTagType(NBT::TAG_Compound);
50  }
51 
52  for($i = 0; $i < $this->getSize(); ++$i){
53  $this->inventory->setItem($i, $this->getItem($i));
54  }
55 
56  if(!isset($this->namedtag->BurnTime) or $this->namedtag["BurnTime"] < 0){
57  $this->namedtag->BurnTime = new Short("BurnTime", 0);
58  }
59  if(!isset($this->namedtag->CookTime) or $this->namedtag["CookTime"] < 0 or ($this->namedtag["BurnTime"] === 0 and $this->namedtag["CookTime"] > 0)){
60  $this->namedtag->CookTime = new Short("CookTime", 0);
61  }
62  if(!isset($this->namedtag->MaxTime)){
63  $this->namedtag->MaxTime = new Short("BurnTime", $this->namedtag["BurnTime"]);
64  $this->namedtag->BurnTicks = new Short("BurnTicks", 0);
65  }
66  if($this->namedtag["BurnTime"] > 0){
67  $this->scheduleUpdate();
68  }
69  }
70 
71  public function close(){
72  if($this->closed === false){
73  foreach($this->getInventory()->getViewers() as $player){
74  $player->removeWindow($this->getInventory());
75  }
76  parent::close();
77  }
78  }
79 
80  public function saveNBT(){
81  $this->namedtag->Items = new Enum("Inventory", []);
82  $this->namedtag->Items->setTagType(NBT::TAG_Compound);
83  for($index = 0; $index < $this->getSize(); ++$index){
84  $this->setItem($index, $this->inventory->getItem($index));
85  }
86  }
87 
91  public function getSize(){
92  return 3;
93  }
94 
100  protected function getSlotIndex($index){
101  foreach($this->namedtag->Items as $i => $slot){
102  if($slot["Slot"] === $index){
103  return $i;
104  }
105  }
106 
107  return -1;
108  }
109 
117  public function getItem($index){
118  $i = $this->getSlotIndex($index);
119  if($i < 0){
120  return Item::get(Item::AIR, 0, 0);
121  }else{
122  return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]);
123  }
124  }
125 
134  public function setItem($index, Item $item){
135  $i = $this->getSlotIndex($index);
136 
137  $d = new Compound(false, [
138  new Byte("Count", $item->getCount()),
139  new Byte("Slot", $index),
140  new Short("id", $item->getId()),
141  new Short("Damage", $item->getDamage()),
142  ]);
143 
144  if($item->getId() === Item::AIR or $item->getCount() <= 0){
145  if($i >= 0){
146  unset($this->namedtag->Items[$i]);
147  }
148  }elseif($i < 0){
149  for($i = 0; $i <= $this->getSize(); ++$i){
150  if(!isset($this->namedtag->Items[$i])){
151  break;
152  }
153  }
154  $this->namedtag->Items[$i] = $d;
155  }else{
156  $this->namedtag->Items[$i] = $d;
157  }
158 
159  return true;
160  }
161 
165  public function getInventory(){
166  return $this->inventory;
167  }
168 
169  protected function checkFuel(Item $fuel){
170  $this->server->getPluginManager()->callEvent($ev = new FurnaceBurnEvent($this, $fuel, $fuel->getFuelTime()));
171 
172  if($ev->isCancelled()){
173  return;
174  }
175 
176  $this->namedtag->MaxTime = new Short("MaxTime", $ev->getBurnTime());
177  $this->namedtag->BurnTime = new Short("BurnTime", $ev->getBurnTime());
178  $this->namedtag->BurnTicks = new Short("BurnTicks", 0);
179  if($this->getBlock()->getId() === Item::FURNACE){
180  $this->getLevel()->setBlock($this, Block::get(Item::BURNING_FURNACE, $this->getBlock()->getDamage()), true);
181  }
182 
183  if($this->namedtag["BurnTime"] > 0 and $ev->isBurning()){
184  $fuel->setCount($fuel->getCount() - 1);
185  if($fuel->getCount() === 0){
186  $fuel = Item::get(Item::AIR, 0, 0);
187  }
188  $this->inventory->setFuel($fuel);
189  }
190  }
191 
192  public function onUpdate(){
193  if($this->closed === true){
194  return false;
195  }
196 
197  $this->timings->startTiming();
198 
199  $ret = false;
200 
201  $fuel = $this->inventory->getFuel();
202  $raw = $this->inventory->getSmelting();
203  $product = $this->inventory->getResult();
204  $smelt = $this->server->getCraftingManager()->matchFurnaceRecipe($raw);
205  $canSmelt = ($smelt instanceof FurnaceRecipe and $raw->getCount() > 0 and (($smelt->getResult()->equals($product, true) and $product->getCount() < $product->getMaxStackSize()) or $product->getId() === Item::AIR));
206 
207  if($this->namedtag["BurnTime"] <= 0 and $canSmelt and $fuel->getFuelTime() !== null and $fuel->getCount() > 0){
208  $this->checkFuel($fuel);
209  }
210 
211  if($this->namedtag["BurnTime"] > 0){
212  $this->namedtag->BurnTime = new Short("BurnTime", $this->namedtag["BurnTime"] - 1);
213  $this->namedtag->BurnTicks = new Short("BurnTicks", ceil(($this->namedtag["BurnTime"] / $this->namedtag["MaxTime"] * 200)));
214 
215  if($smelt instanceof FurnaceRecipe and $canSmelt){
216  $this->namedtag->CookTime = new Short("CookTime", $this->namedtag["CookTime"] + 1);
217  if($this->namedtag["CookTime"] >= 200){ //10 seconds
218  $product = Item::get($smelt->getResult()->getId(), $smelt->getResult()->getDamage(), $product->getCount() + 1);
219 
220  $this->server->getPluginManager()->callEvent($ev = new FurnaceSmeltEvent($this, $raw, $product));
221 
222  if(!$ev->isCancelled()){
223  $this->inventory->setResult($ev->getResult());
224  $raw->setCount($raw->getCount() - 1);
225  if($raw->getCount() === 0){
226  $raw = Item::get(Item::AIR, 0, 0);
227  }
228  $this->inventory->setSmelting($raw);
229  }
230 
231  $this->namedtag->CookTime = new Short("CookTime", $this->namedtag["CookTime"] - 200);
232  }
233  }elseif($this->namedtag["BurnTime"] <= 0){
234  $this->namedtag->BurnTime = new Short("BurnTime", 0);
235  $this->namedtag->CookTime = new Short("CookTime", 0);
236  $this->namedtag->BurnTicks = new Short("BurnTicks", 0);
237  }else{
238  $this->namedtag->CookTime = new Short("CookTime", 0);
239  }
240  $ret = true;
241  }else{
242  ;
243  if($this->getBlock()->getId() === Item::BURNING_FURNACE){
244  $this->getLevel()->setBlock($this, Block::get(Item::FURNACE, $this->getBlock()->getDamage()), true);
245  }
246  $this->namedtag->BurnTime = new Short("BurnTime", 0);
247  $this->namedtag->CookTime = new Short("CookTime", 0);
248  $this->namedtag->BurnTicks = new Short("BurnTicks", 0);
249  }
250 
251  foreach($this->getInventory()->getViewers() as $player){
252  $windowId = $player->getWindowId($this->getInventory());
253  if($windowId > 0){
254  $pk = new ContainerSetDataPacket();
255  $pk->windowid = $windowId;
256  $pk->property = 0; //Smelting
257  $pk->value = floor($this->namedtag["CookTime"]);
258  $player->dataPacket($pk);
259 
260  $pk = new ContainerSetDataPacket();
261  $pk->windowid = $windowId;
262  $pk->property = 1; //Fire icon
263  $pk->value = $this->namedtag["BurnTicks"];
264  $player->dataPacket($pk);
265  }
266 
267  }
268 
269  $this->lastUpdate = microtime(true);
270 
271  $this->timings->stopTiming();
272 
273  return $ret;
274  }
275 }
setItem($index, Item $item)
static get($id, $meta=0, Position $pos=null)
Definition: Block.php:782