Added CraftItemEvent, Crafting system now uses Transactions

This commit is contained in:
Shoghi Cervantes 2014-05-27 17:49:22 +02:00
parent 3fc1be1262
commit 6746987ce5
14 changed files with 348 additions and 105 deletions

View File

@ -2009,10 +2009,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
break; break;
} }
if($this->currentTransaction === null or $this->currentTransaction->getCreationTime() > (microtime(true) - 1)){
$this->currentTransaction = new SimpleTransactionGroup();
}
if($packet->slot < 0){ if($packet->slot < 0){
break; break;
} }
@ -2029,9 +2025,28 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
break; break;
} }
if($transaction->getSourceItem()->equals($transaction->getTargetItem(), true) and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()){ //No changes!
//No changes, just a local inventory update sent by the server
break;
}
if($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < (microtime(true) - 0.5)){
if($this->currentTransaction instanceof SimpleTransactionGroup){
foreach($this->currentTransaction->getInventories() as $inventory){
$inventory->sendContents($inventory->getViewers());
}
}
$this->currentTransaction = new SimpleTransactionGroup();
}
$this->currentTransaction->addTransaction($transaction); $this->currentTransaction->addTransaction($transaction);
if($this->currentTransaction->canExecute()){ if($this->currentTransaction->canExecute()){
if(!$this->currentTransaction->execute()){
$this->currentTransaction = null;
break;
}
foreach($this->currentTransaction->getTransactions() as $ts){ foreach($this->currentTransaction->getTransactions() as $ts){
$inv = $ts->getInventory(); $inv = $ts->getInventory();
if($inv instanceof FurnaceInventory){ if($inv instanceof FurnaceInventory){
@ -2043,19 +2058,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
} }
} }
} }
$this->currentTransaction = null;
} }
$this->currentTransaction = null;
}elseif($packet->windowid == 0){ //Try crafting }elseif($packet->windowid == 0){ //Try crafting
$craftingGroup = new CraftingTransactionGroup($this->currentTransaction); $craftingGroup = new CraftingTransactionGroup($this->currentTransaction);
if($craftingGroup->canExecute()){ //We can craft! if($craftingGroup->canExecute() and $craftingGroup->execute()){ //We can craft!
//TODO: CraftItemEvent switch($craftingGroup->getResult()->getID()){
//$this->server->getPluginManager($ev = new CraftItemEvent($this, $recipe, $craft, $type));
//if($ev->isCancelled()){
// return false;
//}
/*switch($item->getID()){
case Item::WORKBENCH: case Item::WORKBENCH:
$this->awardAchievement("buildWorkBench"); $this->awardAchievement("buildWorkBench");
break; break;
@ -2072,6 +2081,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->awardAchievement("makeBread"); $this->awardAchievement("makeBread");
break; break;
case Item::CAKE: case Item::CAKE:
//TODO: detect complex recipes like cake that leave remainings
$this->awardAchievement("bakeCake"); $this->awardAchievement("bakeCake");
$this->inventory->addItem(Item::get(Item::BUCKET, 0, 3)); $this->inventory->addItem(Item::get(Item::BUCKET, 0, 3));
break; break;
@ -2087,12 +2097,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
case Item::DIAMOND: case Item::DIAMOND:
$this->awardAchievement("diamond"); $this->awardAchievement("diamond");
break; break;
}*/ }
$craftingGroup->execute();
$this->currentTransaction = null;
} }
$this->currentTransaction = null;
} }
@ -2322,28 +2334,27 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
return $this->windows[$inventory]; return $this->windows[$inventory];
} }
if($forceId === 0 or $inventory->open($this)){ if($forceId === null){
if($forceId === null){ $this->windowCnt = $cnt = max(2, ++$this->windowCnt % 99);
$this->windowCnt = $cnt = max(2, ++$this->windowCnt % 99); }else{
}else{ $cnt = (int) $forceId;
$cnt = (int) $forceId; }
} $this->windowIndex[$cnt] = $inventory;
$this->windowIndex[$cnt] = $inventory; $this->windows->attach($inventory, $cnt);
$this->windows->attach($inventory, $cnt); if($inventory->open($this)){
return $cnt; return $cnt;
}else{ }else{
$this->removeWindow($inventory);
return -1; return -1;
} }
} }
public function removeWindow(Inventory $inventory){ public function removeWindow(Inventory $inventory){
$inventory->close($this); $inventory->close($this);
if($this->windows->contains($inventory)){ if($this->windows->contains($inventory)){
$id = $this->windows[$inventory]; $id = $this->windows[$inventory];
$this->windows->detach($this->windowIndex[$id]);
unset($this->windowIndex[$id]); unset($this->windowIndex[$id]);
$this->windows->detach($this->windows[$inventory]);
} }
} }

View File

@ -38,7 +38,9 @@ use pocketmine\event\HandlerList;
use pocketmine\event\server\PacketReceiveEvent; use pocketmine\event\server\PacketReceiveEvent;
use pocketmine\event\server\PacketSendEvent; use pocketmine\event\server\PacketSendEvent;
use pocketmine\event\server\ServerCommandEvent; use pocketmine\event\server\ServerCommandEvent;
use pocketmine\inventory\CraftingManager;
use pocketmine\inventory\InventoryType; use pocketmine\inventory\InventoryType;
use pocketmine\inventory\Recipe;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\level\format\pmf\LevelFormat; use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\generator\Flat; use pocketmine\level\generator\Flat;
@ -127,6 +129,9 @@ class Server{
/** @var SimpleCommandMap */ /** @var SimpleCommandMap */
private $commandMap = null; private $commandMap = null;
/** @var CraftingManager */
private $craftingManager;
/** @var ConsoleCommandSender */ /** @var ConsoleCommandSender */
private $consoleSender; private $consoleSender;
@ -468,6 +473,13 @@ class Server{
return $this->pluginManager; return $this->pluginManager;
} }
/**
* @return CraftingManager
*/
public function getCraftingManager(){
return $this->craftingManager;
}
/** /**
* @return ServerScheduler * @return ServerScheduler
*/ */
@ -512,6 +524,10 @@ class Server{
return $this->players; return $this->players;
} }
public function addRecipe(Recipe $recipe){
$this->craftingManager->registerRecipe($recipe);
}
/** /**
* @param string $name * @param string $name
* *
@ -1267,6 +1283,13 @@ class Server{
$this->consoleSender = new ConsoleCommandSender(); $this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this); $this->commandMap = new SimpleCommandMap($this);
InventoryType::init();
Block::init();
Item::init();
Crafting::init();
$this->craftingManager = new CraftingManager();
$this->pluginManager = new PluginManager($this, $this->commandMap); $this->pluginManager = new PluginManager($this, $this->commandMap);
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender); $this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
$this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader"); $this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader");
@ -1276,10 +1299,7 @@ class Server{
$this->enablePlugins(PluginLoadOrder::STARTUP); $this->enablePlugins(PluginLoadOrder::STARTUP);
InventoryType::init();
Block::init();
Item::init();
Crafting::init();
Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat"); Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal"); Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");

View File

@ -23,15 +23,24 @@ namespace pocketmine\block;
class Planks extends Solid{ class Planks extends Solid{
const OAK = 0;
const SPRUCE = 1;
const BIRCH = 2;
const JUNGLE = 3;
const ACACIA = 4;
const DARK_OAK = 5;
public function __construct($meta = 0){ public function __construct($meta = 0){
parent::__construct(self::PLANKS, $meta, "Wooden Planks"); parent::__construct(self::PLANKS, $meta, "Wood Planks");
$names = array( $names = array(
Wood::OAK => "Oak Wooden Planks", self::OAK => "Oak Wood Planks",
Wood::SPRUCE => "Spruce Wooden Planks", self::SPRUCE => "Spruce Wood Planks",
Wood::BIRCH => "Birch Wooden Planks", self::BIRCH => "Birch Wood Planks",
Wood::JUNGLE => "Jungle Wooden Planks", self::JUNGLE => "Jungle Wood Planks",
self::ACACIA => "Acacia Wood Planks",
self::DARK_OAK => "Jungle Wood Planks",
); );
$this->name = $names[$this->meta & 0x03]; $this->name = $names[$this->meta & 0x07];
$this->hardness = 15; $this->hardness = 15;
} }

View File

@ -29,6 +29,8 @@ class Wood extends Solid{
const SPRUCE = 1; const SPRUCE = 1;
const BIRCH = 2; const BIRCH = 2;
const JUNGLE = 3; const JUNGLE = 3;
const ACACIA = 4;
const DARK_OAK = 5;
public function __construct($meta = 0){ public function __construct($meta = 0){
parent::__construct(self::WOOD, $meta, "Wood"); parent::__construct(self::WOOD, $meta, "Wood");

View File

@ -0,0 +1,60 @@
<?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/
*
*
*/
namespace pocketmine\event\inventory;
use pocketmine\event\Cancellable;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\CraftingTransactionGroup;
use pocketmine\inventory\Recipe;
use pocketmine\Player;
class CraftItemEvent extends Event implements Cancellable{
public static $handlerList = null;
/** @var CraftingTransactionGroup */
private $ts;
/** @var Recipe */
private $recipe;
/**
* @param CraftingTransactionGroup $ts
*/
public function __construct(CraftingTransactionGroup $ts, Recipe $recipe){
$this->ts = $ts;
$this->recipe = $recipe;
}
/**
* @return CraftingTransactionGroup
*/
public function getTransaction(){
return $this->ts;
}
/**
* @return Recipe
*/
public function getRecipe(){
return $this->recipe;
}
}

View File

@ -390,7 +390,11 @@ abstract class BaseInventory implements Inventory{
} }
foreach($target as $player){ foreach($target as $player){
$pk->windowid = $player->getWindowId($this); if(($id = $player->getWindowId($this)) === -1){
$this->close($player);
continue;
}
$pk->windowid = $id;
$player->dataPacket(clone $pk); $player->dataPacket(clone $pk);
} }
} }
@ -409,7 +413,11 @@ abstract class BaseInventory implements Inventory{
$pk->item = clone $this->getItem($index); $pk->item = clone $this->getItem($index);
foreach($target as $player){ foreach($target as $player){
$pk->windowid = $player->getWindowId($this); if(($id = $player->getWindowId($this)) === -1){
$this->close($player);
continue;
}
$pk->windowid = $id;
$player->dataPacket(clone $pk); $player->dataPacket(clone $pk);
} }
} }

View File

@ -41,6 +41,8 @@ abstract class ContainerInventory extends BaseInventory{
} }
$who->dataPacket($pk); $who->dataPacket($pk);
$this->sendContents($who);
} }
public function onClose(Player $who){ public function onClose(Player $who){

View File

@ -21,19 +21,55 @@
namespace pocketmine\inventory; namespace pocketmine\inventory;
use pocketmine\block\Planks;
use pocketmine\block\Wood;
use pocketmine\item\Item;
class CraftingManager{ class CraftingManager{
/** @var Recipe[] */ /** @var Recipe[] */
public $recipes = []; public $recipes = [];
/** @var Recipe[][] */
protected $recipeLookup = [];
/** @var FurnaceRecipe[] */ /** @var FurnaceRecipe[] */
public $furnaceRecipes = []; public $furnaceRecipes = [];
public function __construct(){ public function __construct(){
//TODO: add crafting recipes //TODO: add crafting recipes
$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::OAK, 4)))->addIngredient(Item::get(Item::WOOD, Wood::OAK, 1)));
$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::SPRUCE, 4)))->addIngredient(Item::get(Item::WOOD, Wood::SPRUCE, 1)));
$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::BIRCH, 4)))->addIngredient(Item::get(Item::WOOD, Wood::BIRCH, 1)));
$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::JUNGLE, 4)))->addIngredient(Item::get(Item::WOOD, Wood::JUNGLE, 1)));
//$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::ACACIA, 4)))->addIngredient(Item::get(Item::WOOD2, Wood2::ACACIA, 1)));
//$this->registerRecipe((new ShapelessRecipe(Item::get(Item::WOODEN_PLANK, Planks::DARK_OAK, 4)))->addIngredient(Item::get(Item::WOOD2, Wood2::DARK_OAK, 1)));
} }
public function sort(){ public function sort(Item $i1, Item $i2){
//TODO: recipe sort if($i1->getID() > $i2->getID()){
return 1;
}elseif($i1->getID() < $i2->getID()){
return -1;
}elseif($i1->getDamage() > $i2->getDamage()){
return 1;
}elseif($i1->getDamage() < $i2->getDamage()){
return -1;
}elseif($i1->getCount() > $i2->getCount()){
return 1;
}elseif($i1->getCount() < $i2->getCount()){
return -1;
}else{
return 0;
}
}
/**
* @return Recipe[]
*/
public function getRecipes(){
return $this->recipes;
} }
/** /**
@ -47,7 +83,15 @@ class CraftingManager{
* @param ShapelessRecipe $recipe * @param ShapelessRecipe $recipe
*/ */
public function registerShapelessRecipe(ShapelessRecipe $recipe){ public function registerShapelessRecipe(ShapelessRecipe $recipe){
$result = $recipe->getResult();
$this->recipes[spl_object_hash($recipe)] = $recipe;
$hash = "";
$ingredients = $recipe->getIngredientList();
usort($ingredients, array($this, "sort"));
foreach($ingredients as $item){
$hash .= $item->getID().":".($item->getDamage() === null ? "?":$item->getDamage())."x".$item->getCount().",";
}
$this->recipeLookup[$result->getID().":".$result->getDamage()][$hash] = $recipe;
} }
/** /**
@ -57,6 +101,38 @@ class CraftingManager{
} }
/**
* @param CraftingTransactionGroup $ts
*
* @return Recipe
*/
public function matchTransaction(CraftingTransactionGroup $ts){
$result = $ts->getResult();
if(!($result instanceof Item)){
return false;
}
$k = $result->getID().":".$result->getDamage();
if(!isset($this->recipeLookup[$k])){
return false;
}
$hash = "";
$input = $ts->getRecipe();
usort($input, array($this, "sort"));
foreach($input as $item){
$hash .= $item->getID().":".($item->getDamage() === null ? "?":$item->getDamage())."x".$item->getCount().",";
}
if(!isset($this->recipeLookup[$k][$hash])){
return false;
}
$checkResult = $this->recipeLookup[$k][$hash]->getResult();
if($checkResult->equals($result, true) and $checkResult->getCount() === $result->getCount()){
return $this->recipeLookup[$k][$hash];
}
return null;
}
/** /**
* @param Recipe $recipe * @param Recipe $recipe
*/ */

View File

@ -21,16 +21,88 @@
namespace pocketmine\inventory; namespace pocketmine\inventory;
class CraftingTransactionGroup extends SimpleTransactionGroup{ use pocketmine\event\inventory\CraftItemEvent;
use pocketmine\item\Item;
use pocketmine\Server;
class CraftingTransactionGroup extends SimpleTransactionGroup{
/** @var Item[] */
protected $input = [];
/** @var Item[] */
protected $output = [];
public function __construct(TransactionGroup $group){ public function __construct(TransactionGroup $group){
parent::__construct(); parent::__construct();
$this->transactions = $group->getTransactions(); $this->transactions = $group->getTransactions();
$this->inventories = $group->getInventories(); $this->inventories = $group->getInventories();
$this->matchItems($this->output, $this->input);
/*$input = "";
$output = "";
foreach($this->input as $item){
$input .= $item->getID().":".$item->getDamage()."(".$item->getCount()."), ";
}
foreach($this->output as $item){
$output .= $item->getID().":".$item->getDamage()."(".$item->getCount()."), ";
}
console("craft_tx#".spl_object_hash($this).": ".substr($input, 0, -2)." => ".substr($output, 0, -2));*/
}
public function addTransaction(Transaction $transaction){
parent::addTransaction($transaction);
$this->input = [];
$this->output = [];
$this->matchItems($this->output, $this->input);
}
/**
* Gets the Items that have been used
*
* @return Item[]
*/
public function getRecipe(){
return $this->input;
}
/**
* @return Item
*/
public function getResult(){
reset($this->output);
return current($this->output);
} }
public function canExecute(){ public function canExecute(){
//TODO: search in crafting recipes if(count($this->output) !== 1 or count($this->input) === 0){
return false; return false;
}
return $this->getMatchingRecipe() instanceof Recipe;
}
/**
* @return Recipe
*/
public function getMatchingRecipe(){
return Server::getInstance()->getCraftingManager()->matchTransaction($this);
}
public function execute(){
if($this->hasExecuted() or !$this->canExecute()){
return false;
}
Server::getInstance()->getPluginManager()->callEvent($ev = new CraftItemEvent($this, $this->getMatchingRecipe()));
if($ev->isCancelled()){
foreach($this->inventories as $inventory){
$inventory->sendContents($inventory->getViewers());
}
return false;
}
foreach($this->transactions as $transaction){
$transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem());
}
$this->hasExecuted = true;
return true;
} }
} }

View File

@ -22,6 +22,7 @@
namespace pocketmine\inventory; namespace pocketmine\inventory;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\Server;
class FurnaceRecipe implements Recipe{ class FurnaceRecipe implements Recipe{
/** @var Item */ /** @var Item */
@ -60,55 +61,7 @@ class FurnaceRecipe implements Recipe{
return clone $this->output; return clone $this->output;
} }
/** public function registerToCraftingManager(){
* @param Item $item Server::getInstance()->getCraftingManager()->registerFurnaceRecipe($this);
*
* @returns ShapelessRecipe
*
* @throws \Exception
*/
public function addIngredient(Item $item){
if(count($this->ingredients) >= 9){
throw new \Exception("Shapeless recipes cannot have more than 9 ingredients");
}
$it = clone $item;
$it->setCount(1);
while($item->getCount() > 0){
$this->ingredients[] = clone $it;
$item->setCount($item->getCount() - 1);
}
return $this;
}
/**
* @param Item $item
*
* @return $this
*/
public function removeIngredient(Item $item){
foreach($this->ingredients as $index => $ingredient){
if($item->getCount() <= 0){
break;
}
if($ingredient->equals($item, $item->getDamage() === null ? false : true)){
unset($this->ingredients[$index]);
$item->setCount($item->getCount() - 1);
}
}
return $this;
}
/**
* @return Item[]
*/
public function getIngredientList(){
$ingredients = [];
foreach($this->ingredients as $ingredient){
$ingredients[] = clone $ingredient;
}
return $ingredients;
} }
} }

View File

@ -335,7 +335,11 @@ class PlayerInventory extends BaseInventory{
$pk->hotbar[] = $index <= -1 ? -1 : $index + 9; $pk->hotbar[] = $index <= -1 ? -1 : $index + 9;
} }
} }
$pk->windowid = $player->getWindowId($this); if(($id = $player->getWindowId($this)) === -1){
$this->close($player);
continue;
}
$pk->windowid = $id;
$player->dataPacket(clone $pk); $player->dataPacket(clone $pk);
} }
} }
@ -355,10 +359,15 @@ class PlayerInventory extends BaseInventory{
foreach($target as $player){ foreach($target as $player){
if($player === $this->getHolder()){ if($player === $this->getHolder()){
/** @var Player $player */
//TODO: Check if Mojang has implemented this (for the player inventory) on Minecraft: PE 0.9.0 //TODO: Check if Mojang has implemented this (for the player inventory) on Minecraft: PE 0.9.0
$this->sendContents($player); $this->sendContents($player);
}else{ }else{
$pk->windowid = $player->getWindowId($this); if(($id = $player->getWindowId($this)) === -1){
$this->close($player);
continue;
}
$pk->windowid = $id;
$player->dataPacket(clone $pk); $player->dataPacket(clone $pk);
} }
} }

View File

@ -22,6 +22,7 @@
namespace pocketmine\inventory; namespace pocketmine\inventory;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\Server;
class ShapedRecipe implements Recipe{ class ShapedRecipe implements Recipe{
/** @var Item */ /** @var Item */
@ -98,4 +99,8 @@ class ShapedRecipe implements Recipe{
public function getShape(){ public function getShape(){
return $this->rows; return $this->rows;
} }
public function registerToCraftingManager(){
Server::getInstance()->getCraftingManager()->registerShapedRecipe($this);
}
} }

View File

@ -22,6 +22,7 @@
namespace pocketmine\inventory; namespace pocketmine\inventory;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\Server;
class ShapelessRecipe implements Recipe{ class ShapelessRecipe implements Recipe{
/** @var Item */ /** @var Item */
@ -89,4 +90,8 @@ class ShapelessRecipe implements Recipe{
} }
return $ingredients; return $ingredients;
} }
public function registerToCraftingManager(){
Server::getInstance()->getCraftingManager()->registerShapelessRecipe($this);
}
} }

View File

@ -59,19 +59,23 @@ class SimpleTransactionGroup implements TransactionGroup{
$this->inventories[spl_object_hash($transaction->getInventory())] = $transaction->getInventory(); $this->inventories[spl_object_hash($transaction->getInventory())] = $transaction->getInventory();
} }
public function canExecute(){ /**
/** @var Item[] $needItems */ * @param Item[] $needItems
$needItems = []; * @param Item[] $haveItems
/** @var Item[] $haveItems */ */
$haveItems = []; protected function matchItems(array &$needItems, array &$haveItems){
foreach($this->transactions as $key => $ts){ foreach($this->transactions as $key => $ts){
$needItems[] = $ts->getTargetItem(); if($ts->getTargetItem()->getID() !== Item::AIR){
$needItems[] = $ts->getTargetItem();
}
$checkSourceItem = $ts->getInventory()->getItem($ts->getSlot()); $checkSourceItem = $ts->getInventory()->getItem($ts->getSlot());
$sourceItem = $ts->getSourceItem(); $sourceItem = $ts->getSourceItem();
if(!$checkSourceItem->equals($sourceItem, true) or $sourceItem->getCount() !== $checkSourceItem->getCount()){ if(!$checkSourceItem->equals($sourceItem, true) or $sourceItem->getCount() !== $checkSourceItem->getCount()){
return false; return false;
} }
$haveItems[] = $sourceItem; if($sourceItem->getID() !== Item::AIR){
$haveItems[] = $sourceItem;
}
} }
foreach($needItems as $i => $needItem){ foreach($needItems as $i => $needItem){
@ -90,7 +94,12 @@ class SimpleTransactionGroup implements TransactionGroup{
} }
} }
} }
}
public function canExecute(){
$haveItems = [];
$needItems = [];
$this->matchItems($haveItems, $needItems);
return count($haveItems) === 0 and count($needItems) === 0 and count($this->transactions) > 0; return count($haveItems) === 0 and count($needItems) === 0 and count($this->transactions) > 0;
} }
@ -111,6 +120,8 @@ class SimpleTransactionGroup implements TransactionGroup{
$transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem()); $transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem());
} }
$this->hasExecuted = true;
return true; return true;
} }