Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate transaction slots #6304

Open
wants to merge 16 commits into
base: minor-next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/inventory/ArmorInventory.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@
namespace pocketmine\inventory;

use pocketmine\entity\Living;
use pocketmine\inventory\transaction\validator\ArmorInventoryValidator;
use pocketmine\item\Item;
use pocketmine\utils\ObjectSet;

class ArmorInventory extends SimpleInventory implements SlotSafeInventory{
use SlotSafeInventoryTrait;

class ArmorInventory extends SimpleInventory{
public const SLOT_HEAD = 0;
public const SLOT_CHEST = 1;
public const SLOT_LEGS = 2;
Expand Down Expand Up @@ -73,4 +77,8 @@
public function setBoots(Item $boots) : void{
$this->setItem(self::SLOT_FEET, $boots);
}

protected static function initSlotValidators(ObjectSet $validators) : void{

Check failure on line 81 in src/inventory/ArmorInventory.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 / PHPStan analysis

Method pocketmine\inventory\ArmorInventory::initSlotValidators() has parameter $validators with generic class pocketmine\utils\ObjectSet but does not specify its types: T

Check failure on line 81 in src/inventory/ArmorInventory.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 / PHPStan analysis

Method pocketmine\inventory\ArmorInventory::initSlotValidators() has parameter $validators with generic class pocketmine\utils\ObjectSet but does not specify its types: T

Check failure on line 81 in src/inventory/ArmorInventory.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 / PHPStan analysis

Method pocketmine\inventory\ArmorInventory::initSlotValidators() has parameter $validators with generic class pocketmine\utils\ObjectSet but does not specify its types: T

Check failure on line 81 in src/inventory/ArmorInventory.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 / PHPStan analysis

Method pocketmine\inventory\ArmorInventory::initSlotValidators() has parameter $validators with generic class pocketmine\utils\ObjectSet but does not specify its types: T

Check failure on line 81 in src/inventory/ArmorInventory.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 / PHPStan analysis

Method pocketmine\inventory\ArmorInventory::initSlotValidators() has parameter $validators with generic class pocketmine\utils\ObjectSet but does not specify its types: T

Check failure on line 81 in src/inventory/ArmorInventory.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 / PHPStan analysis

Method pocketmine\inventory\ArmorInventory::initSlotValidators() has parameter $validators with generic class pocketmine\utils\ObjectSet but does not specify its types: T
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
$validators->add(new ArmorInventoryValidator());
}
}
45 changes: 45 additions & 0 deletions src/inventory/SlotSafeInventory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?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/
*
*
*/

declare(strict_types=1);

namespace pocketmine\inventory;

use pocketmine\inventory\transaction\validator\InventoryTransactionValidator;
use pocketmine\utils\ObjectSet;

/**
* A "slot safe inventory" is an inventory that has a set of rules that determine whether an item can be placed in a
* particular slot. This ensures that the inventory's internal state is always valid and consistent.
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
*/
interface SlotSafeInventory{
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
/**
* Return a set of validators that will be used to determine whether an item can be placed in a particular slot.
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
* All validators need to return true for the transaction to be allowed.
* If one of the validators returns false, the transaction will be cancelled.
*
* There is no guarantee that the validators will be called in any particular order.
* All validators need to be stateless and not depend on the order in which they are called.
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
*
* @phpstan-return ObjectSet<InventoryTransactionValidator>
*/
public static function getSlotValidators() : ObjectSet;
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
}
45 changes: 45 additions & 0 deletions src/inventory/SlotSafeInventoryTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?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/
*
*
*/

declare(strict_types=1);

namespace pocketmine\inventory;

use pocketmine\utils\ObjectSet;

trait SlotSafeInventoryTrait{
private static ObjectSet $validators;

/**
* Initialize the set of validators.
* Put here all the internal validators of the inventory.
*/
abstract protected static function initSlotValidators(ObjectSet $validators) : void;

public static function getSlotValidators() : ObjectSet {
if(!isset(self::$validators)){
self::$validators = new ObjectSet();
self::initSlotValidators(self::$validators);
}

return self::$validators;
}
}
13 changes: 13 additions & 0 deletions src/inventory/transaction/action/SlotChangeAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
namespace pocketmine\inventory\transaction\action;

use pocketmine\inventory\Inventory;
use pocketmine\inventory\SlotSafeInventory;
use pocketmine\inventory\transaction\InventoryTransaction;
use pocketmine\inventory\transaction\TransactionValidationException;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\player\Player;

/**
Expand Down Expand Up @@ -74,6 +76,17 @@ public function validate(Player $source) : void{
if($this->targetItem->getCount() > $this->inventory->getMaxStackSize()){
throw new TransactionValidationException("Target item exceeds inventory max stack size");
}
if($this->inventory instanceof SlotSafeInventory && !$this->targetItem->equals(VanillaItems::AIR())){
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
$result = false;
foreach($this->inventory::getSlotValidators() as $validator){
if(($result = $validator->validate($this->inventory, $this->targetItem, $this->inventorySlot))){
break;
}
}
if(!$result){
throw new TransactionValidationException("Target item is not accepted by the inventory");
}
}
}

/**
Expand Down
44 changes: 44 additions & 0 deletions src/inventory/transaction/validator/ArmorInventoryValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?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/
*
*
*/

declare(strict_types=1);

namespace pocketmine\inventory\transaction\validator;

use pocketmine\block\BlockTypeIds;
use pocketmine\block\MobHead;
use pocketmine\inventory\ArmorInventory;
use pocketmine\inventory\Inventory;
use pocketmine\item\Armor;
use pocketmine\item\Item;
use pocketmine\item\ItemBlock;

class ArmorInventoryValidator implements InventoryTransactionValidator{
public function validate(Inventory $inventory, Item $item, int $slot) : bool{
return $inventory instanceof ArmorInventory && (
ShockedPlot7560 marked this conversation as resolved.
Show resolved Hide resolved
($item instanceof Armor && $item->getArmorSlot() === $slot) ||
($slot === ArmorInventory::SLOT_HEAD && $item instanceof ItemBlock && (
$item->getBlock()->getTypeId() === BlockTypeIds::CARVED_PUMPKIN ||
$item->getBlock() instanceof MobHead
))
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?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/
*
*
*/

declare(strict_types=1);

namespace pocketmine\inventory\transaction\validator;

use pocketmine\inventory\Inventory;
use pocketmine\inventory\SlotSafeInventory;
use pocketmine\item\Item;

/**
* This interface is used to validate the transactions of a "safe" inventory. {@see SlotSafeInventory}
*
* In this way, each inventory can determine whether or not an item has the right to be placed in a particular slot.
*/
interface InventoryTransactionValidator{
/**
* @return bool Return true, if the item CAN be placed in the given slot of the given inventory.
* Otherwise, return false and the transaction will be cancelled.
*/
public function validate(Inventory $inventory, Item $item, int $slot) : bool;
dktapps marked this conversation as resolved.
Show resolved Hide resolved
}