diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index f9341c833..9f72b21c3 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -2011,6 +2011,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ break; } $this->craftingType = 0; + $this->currentTransaction = null; if(isset($this->windowIndex[$packet->windowid])){ $this->server->getPluginManager()->callEvent(new InventoryCloseEvent($this->windowIndex[$packet->windowid], $this)); $this->removeWindow($this->windowIndex[$packet->windowid]); @@ -2046,13 +2047,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ } - if($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < (microtime(true) - 0.5)){ + if($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < (microtime(true) - 0.4)){ if($this->currentTransaction instanceof SimpleTransactionGroup){ foreach($this->currentTransaction->getInventories() as $inventory){ $inventory->sendContents($inventory->getViewers()); } } - $this->currentTransaction = new SimpleTransactionGroup(); + $this->currentTransaction = new SimpleTransactionGroup($this); } $this->currentTransaction->addTransaction($transaction); @@ -2062,6 +2063,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ $this->currentTransaction = null; break; } + console("tx#".spl_object_hash($this->currentTransaction)." EXECUTED"); foreach($this->currentTransaction->getTransactions() as $ts){ $inv = $ts->getInventory(); if($inv instanceof FurnaceInventory){ diff --git a/src/pocketmine/inventory/BaseInventory.php b/src/pocketmine/inventory/BaseInventory.php index b5408bb29..21311c7e9 100644 --- a/src/pocketmine/inventory/BaseInventory.php +++ b/src/pocketmine/inventory/BaseInventory.php @@ -44,7 +44,7 @@ abstract class BaseInventory implements Inventory{ protected $title; /** @var Item[] */ protected $slots = []; - /** @var \SplObjectStorage */ + /** @var Player[] */ protected $viewers = []; /** @var InventoryHolder */ protected $holder; @@ -58,7 +58,6 @@ abstract class BaseInventory implements Inventory{ */ public function __construct(InventoryHolder $holder, InventoryType $type, array $items = [], $overrideSize = null, $overrideTitle = null){ $this->holder = $holder; - $this->viewers = new \SplObjectStorage(); $this->type = $type; if($overrideSize !== null){ @@ -121,12 +120,12 @@ abstract class BaseInventory implements Inventory{ } } - public function setItem($index, Item $item){ + public function setItem($index, Item $item, $source = null){ $item = clone $item; if($index < 0 or $index >= $this->size){ return false; }elseif($item->getID() === 0){ - $this->clear($index); + $this->clear($index, $source); } $holder = $this->getHolder(); @@ -141,7 +140,7 @@ abstract class BaseInventory implements Inventory{ $old = $this->getItem($index); $this->slots[$index] = clone $item; - $this->onSlotChange($index, $old); + $this->onSlotChange($index, $old, $source); return true; } @@ -296,7 +295,7 @@ abstract class BaseInventory implements Inventory{ return $slots; } - public function clear($index){ + public function clear($index, $source = null){ if(isset($this->slots[$index])){ $item = Item::get(Item::AIR, null, 0); $old = $this->slots[$index]; @@ -316,7 +315,7 @@ abstract class BaseInventory implements Inventory{ unset($this->slots[$index]); } - $this->onSlotChange($index, $old); + $this->onSlotChange($index, $old, $source); } return true; @@ -328,9 +327,12 @@ abstract class BaseInventory implements Inventory{ } } - public function getViewers(){ + public function getViewers($source = null){ $viewers = []; foreach($this->viewers as $viewer){ + if($viewer === $source){ + continue; + } $viewers[] = $viewer; } @@ -359,15 +361,15 @@ abstract class BaseInventory implements Inventory{ } public function onOpen(Player $who){ - $this->viewers->attach($who); + $this->viewers[spl_object_hash($who)] = $who; } public function onClose(Player $who){ - $this->viewers->detach($who); + unset($this->viewers[spl_object_hash($who)]); } - public function onSlotChange($index, $before){ - $this->sendSlot($index, $this->getViewers()); + public function onSlotChange($index, $before, $source = null){ + $this->sendSlot($index, $this->getViewers($source)); } diff --git a/src/pocketmine/inventory/BaseTransaction.php b/src/pocketmine/inventory/BaseTransaction.php index e769a4d24..904132ffa 100644 --- a/src/pocketmine/inventory/BaseTransaction.php +++ b/src/pocketmine/inventory/BaseTransaction.php @@ -32,6 +32,8 @@ class BaseTransaction implements Transaction{ protected $sourceItem; /** @var Item */ protected $targetItem; + /** @var float */ + protected $creationTime; /** * @param Inventory $inventory @@ -44,6 +46,11 @@ class BaseTransaction implements Transaction{ $this->slot = (int) $slot; $this->sourceItem = clone $sourceItem; $this->targetItem = clone $targetItem; + $this->creationTime = microtime(true); + } + + public function getCreationTime(){ + return $this->creationTime; } public function getInventory(){ diff --git a/src/pocketmine/inventory/ChestInventory.php b/src/pocketmine/inventory/ChestInventory.php index 3180d43e6..c5efeec72 100644 --- a/src/pocketmine/inventory/ChestInventory.php +++ b/src/pocketmine/inventory/ChestInventory.php @@ -53,8 +53,6 @@ class ChestInventory extends ContainerInventory{ } public function onClose(Player $who){ - parent::onClose($who); - if(count($this->getViewers()) === 1){ $pk = new TileEventPacket; $pk->x = $this->getHolder()->getX(); @@ -64,5 +62,6 @@ class ChestInventory extends ContainerInventory{ $pk->case2 = 0; Server::getInstance()->broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk); } + parent::onClose($who); } } \ No newline at end of file diff --git a/src/pocketmine/inventory/ContainerInventory.php b/src/pocketmine/inventory/ContainerInventory.php index 7dc092822..a9db23553 100644 --- a/src/pocketmine/inventory/ContainerInventory.php +++ b/src/pocketmine/inventory/ContainerInventory.php @@ -28,6 +28,7 @@ use pocketmine\math\Vector3; abstract class ContainerInventory extends BaseInventory{ public function onOpen(Player $who){ + parent::onOpen($who); $pk = new ContainerOpenPacket; $pk->windowid = $who->getWindowId($this); $pk->type = $this->getType()->getNetworkType(); @@ -49,5 +50,6 @@ abstract class ContainerInventory extends BaseInventory{ $pk = new ContainerClosePacket; $pk->windowid = $who->getWindowId($this); $who->dataPacket($pk); + parent::onClose($who); } } \ No newline at end of file diff --git a/src/pocketmine/inventory/CraftingTransactionGroup.php b/src/pocketmine/inventory/CraftingTransactionGroup.php index b90665ef1..14b7109f7 100644 --- a/src/pocketmine/inventory/CraftingTransactionGroup.php +++ b/src/pocketmine/inventory/CraftingTransactionGroup.php @@ -34,10 +34,11 @@ class CraftingTransactionGroup extends SimpleTransactionGroup{ /** @var Recipe */ protected $recipe = null; - public function __construct(TransactionGroup $group){ + public function __construct(SimpleTransactionGroup $group){ parent::__construct(); $this->transactions = $group->getTransactions(); $this->inventories = $group->getInventories(); + $this->source = $group->getSource(); $this->matchItems($this->output, $this->input); } @@ -97,7 +98,7 @@ class CraftingTransactionGroup extends SimpleTransactionGroup{ } foreach($this->transactions as $transaction){ - $transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem()); + $transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem(), $this->getSource()); } $this->hasExecuted = true; diff --git a/src/pocketmine/inventory/DoubleChestInventory.php b/src/pocketmine/inventory/DoubleChestInventory.php index b52765761..e56056336 100644 --- a/src/pocketmine/inventory/DoubleChestInventory.php +++ b/src/pocketmine/inventory/DoubleChestInventory.php @@ -50,12 +50,12 @@ class DoubleChestInventory extends ChestInventory implements InventoryHolder{ return $index < $this->left->getSize() ? $this->left->getItem($index) : $this->right->getItem($index - $this->right->getSize()); } - public function setItem($index, Item $item){ - return $index < $this->left->getSize() ? $this->left->setItem($index, $item) : $this->right->setItem($index - $this->right->getSize(), $item); + public function setItem($index, Item $item, $source = null){ + return $index < $this->left->getSize() ? $this->left->setItem($index, $item, $source) : $this->right->setItem($index - $this->right->getSize(), $item, $source); } - public function clear($index){ - return $index < $this->left->getSize() ? $this->left->clear($index) : $this->right->clear($index - $this->right->getSize()); + public function clear($index, $source = null){ + return $index < $this->left->getSize() ? $this->left->clear($index, $source) : $this->right->clear($index - $this->right->getSize(), $source); } public function getContents(){ diff --git a/src/pocketmine/inventory/Inventory.php b/src/pocketmine/inventory/Inventory.php index 6bc3421d9..a61baae75 100644 --- a/src/pocketmine/inventory/Inventory.php +++ b/src/pocketmine/inventory/Inventory.php @@ -53,13 +53,15 @@ interface Inventory{ /** * Puts an Item in a slot. * If a plugin refuses the update or $index is invalid, it'll return false + * If a source Player is specified, it won't send a Inventory update to it * - * @param int $index - * @param Item $item + * @param int $index + * @param Item $item + * @param Player $source * * @return bool */ - public function setItem($index, Item $item); + public function setItem($index, Item $item, $source = null); /** * Stores the given Items in the inventory. This will try to fill @@ -160,11 +162,12 @@ interface Inventory{ /** * Will clear a specific slot * - * @param int $index + * @param int $index + * @param Player $source * * @return bool */ - public function clear($index); + public function clear($index, $source = null); /** * Clears all the slots @@ -175,9 +178,11 @@ interface Inventory{ * Gets all the Players viewing the inventory * Players will be viewing their inventory at all times, even when not open. * + * @param Player $source + * * @return Player[] */ - public function getViewers(); + public function getViewers($source = null); /** * @return InventoryType @@ -211,8 +216,9 @@ interface Inventory{ public function onClose(Player $who); /** - * @param int $index - * @param Item|null $before + * @param int $index + * @param Item $before + * @param Player $source */ - public function onSlotChange($index, $before); + public function onSlotChange($index, $before, $source = null); } diff --git a/src/pocketmine/inventory/PlayerInventory.php b/src/pocketmine/inventory/PlayerInventory.php index 0d40ca40c..1a831e439 100644 --- a/src/pocketmine/inventory/PlayerInventory.php +++ b/src/pocketmine/inventory/PlayerInventory.php @@ -144,7 +144,7 @@ class PlayerInventory extends BaseInventory{ } } - public function onSlotChange($index, $before){ + public function onSlotChange($index, $before, $source = null){ parent::onSlotChange($index, $before); if($index >= $this->getSize()){ @@ -196,7 +196,7 @@ class PlayerInventory extends BaseInventory{ return $this->setItem($this->getSize(), $boots); } - public function setItem($index, Item $item){ + public function setItem($index, Item $item, $source = null){ if($index < 0 or $index >= $this->size){ return false; } @@ -211,15 +211,18 @@ class PlayerInventory extends BaseInventory{ } $item = $ev->getNewItem(); } - - $old = $this->getItem($index); - $this->slots[$index] = clone $item; - $this->onSlotChange($index, $old); + if($item->getID() === 0){ + $this->clear($index, $source); + }else{ + $old = $this->getItem($index); + $this->slots[$index] = clone $item; + $this->onSlotChange($index, $old, $source); + } return true; } - public function clear($index){ + public function clear($index, $source = null){ if(isset($this->slots[$index])){ $item = Item::get(Item::AIR, null, 0); $old = $this->slots[$index]; @@ -239,7 +242,7 @@ class PlayerInventory extends BaseInventory{ unset($this->slots[$index]); } - $this->onSlotChange($index, $old); + $this->onSlotChange($index, $old, $source); } } diff --git a/src/pocketmine/inventory/SimpleTransactionGroup.php b/src/pocketmine/inventory/SimpleTransactionGroup.php index 60af227c4..9d6c85e54 100644 --- a/src/pocketmine/inventory/SimpleTransactionGroup.php +++ b/src/pocketmine/inventory/SimpleTransactionGroup.php @@ -23,6 +23,7 @@ namespace pocketmine\inventory; use pocketmine\event\inventory\InventoryTransactionEvent; use pocketmine\item\Item; +use pocketmine\Player; use pocketmine\Server; /** @@ -31,6 +32,8 @@ use pocketmine\Server; class SimpleTransactionGroup implements TransactionGroup{ private $creationTime; protected $hasExecuted = false; + /** @var Player */ + protected $source = null; /** @var Inventory[] */ protected $inventories = []; @@ -38,8 +41,19 @@ class SimpleTransactionGroup implements TransactionGroup{ /** @var Transaction[] */ protected $transactions = []; - public function __construct(){ + /** + * @param Player $source + */ + public function __construct(Player $source = null){ $this->creationTime = microtime(true); + $this->source = $source; + } + + /** + * @return Player + */ + public function getSource(){ + return $this->source; } public function getCreationTime(){ @@ -55,6 +69,18 @@ class SimpleTransactionGroup implements TransactionGroup{ } public function addTransaction(Transaction $transaction){ + if(isset($this->transactions[spl_object_hash($transaction)])){ + return; + } + foreach($this->transactions as $hash => $tx){ + if($tx->getInventory() === $transaction->getInventory() and $tx->getSlot() === $transaction->getSlot()){ + if($transaction->getCreationTime() >= $tx->getCreationTime()){ + unset($this->transactions[$hash]); + }else{ + return; + } + } + } $this->transactions[spl_object_hash($transaction)] = $transaction; $this->inventories[spl_object_hash($transaction->getInventory())] = $transaction->getInventory(); } @@ -100,9 +126,6 @@ class SimpleTransactionGroup implements TransactionGroup{ $haveItems = []; $needItems = []; $this->matchItems($haveItems, $needItems); - $input = ""; - $output = ""; - return count($haveItems) === 0 and count($needItems) === 0 and count($this->transactions) > 0; } @@ -120,7 +143,7 @@ class SimpleTransactionGroup implements TransactionGroup{ } foreach($this->transactions as $transaction){ - $transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem()); + $transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem(), $this->getSource()); } $this->hasExecuted = true; diff --git a/src/pocketmine/inventory/Transaction.php b/src/pocketmine/inventory/Transaction.php index ca95a5f2a..edfe9acb9 100644 --- a/src/pocketmine/inventory/Transaction.php +++ b/src/pocketmine/inventory/Transaction.php @@ -44,4 +44,9 @@ interface Transaction{ * @return Item */ public function getTargetItem(); + + /** + * @return float + */ + public function getCreationTime(); } \ No newline at end of file