Update ContainerInventory on Transaction refused

This commit is contained in:
Shoghi Cervantes 2014-05-28 17:11:06 +02:00
parent f795a3f565
commit f66560ccd4
11 changed files with 94 additions and 44 deletions

View File

@ -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){

View File

@ -44,7 +44,7 @@ abstract class BaseInventory implements Inventory{
protected $title;
/** @var Item[] */
protected $slots = [];
/** @var \SplObjectStorage<Player> */
/** @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));
}

View File

@ -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(){

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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(){

View File

@ -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 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
@ -161,10 +163,11 @@ interface Inventory{
* Will clear a specific slot
*
* @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
@ -212,7 +217,8 @@ interface Inventory{
/**
* @param int $index
* @param Item|null $before
* @param Item $before
* @param Player $source
*/
public function onSlotChange($index, $before);
public function onSlotChange($index, $before, $source = null);
}

View File

@ -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();
}
if($item->getID() === 0){
$this->clear($index, $source);
}else{
$old = $this->getItem($index);
$this->slots[$index] = clone $item;
$this->onSlotChange($index, $old);
$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);
}
}

View File

@ -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;

View File

@ -44,4 +44,9 @@ interface Transaction{
* @return Item
*/
public function getTargetItem();
/**
* @return float
*/
public function getCreationTime();
}