mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-05 11:27:07 +00:00
Validate transaction slots (#6304)
This commit is contained in:
parent
8cb2e577a1
commit
f6e2a1ecce
@ -23,8 +23,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\block\BlockTypeIds;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\inventory\transaction\action\validator\CallbackSlotValidator;
|
||||
use pocketmine\inventory\transaction\TransactionValidationException;
|
||||
use pocketmine\item\Armor;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemBlock;
|
||||
|
||||
class ArmorInventory extends SimpleInventory{
|
||||
public const SLOT_HEAD = 0;
|
||||
@ -36,6 +41,8 @@ class ArmorInventory extends SimpleInventory{
|
||||
protected Living $holder
|
||||
){
|
||||
parent::__construct(4);
|
||||
|
||||
$this->validators->add(new CallbackSlotValidator($this->validate(...)));
|
||||
}
|
||||
|
||||
public function getHolder() : Living{
|
||||
@ -73,4 +80,20 @@ class ArmorInventory extends SimpleInventory{
|
||||
public function setBoots(Item $boots) : void{
|
||||
$this->setItem(self::SLOT_FEET, $boots);
|
||||
}
|
||||
|
||||
private function validate(Inventory $inventory, Item $item, int $slot) : ?TransactionValidationException{
|
||||
if($item instanceof Armor){
|
||||
if($item->getArmorSlot() !== $slot){
|
||||
return new TransactionValidationException("Armor item is in wrong slot");
|
||||
}
|
||||
}else{
|
||||
if(!($slot === ArmorInventory::SLOT_HEAD && $item instanceof ItemBlock && (
|
||||
$item->getBlock()->getTypeId() === BlockTypeIds::CARVED_PUMPKIN ||
|
||||
$item->getBlock()->getTypeId() === BlockTypeIds::MOB_HEAD
|
||||
))){
|
||||
return new TransactionValidationException("Item is not accepted in an armor slot");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,10 @@ use function spl_object_id;
|
||||
|
||||
/**
|
||||
* This class provides everything needed to implement an inventory, minus the underlying storage system.
|
||||
*
|
||||
* @phpstan-import-type SlotValidators from SlotValidatedInventory
|
||||
*/
|
||||
abstract class BaseInventory implements Inventory{
|
||||
abstract class BaseInventory implements Inventory, SlotValidatedInventory{
|
||||
protected int $maxStackSize = Inventory::MAX_STACK;
|
||||
/** @var Player[] */
|
||||
protected array $viewers = [];
|
||||
@ -46,9 +48,12 @@ abstract class BaseInventory implements Inventory{
|
||||
* @phpstan-var ObjectSet<InventoryListener>
|
||||
*/
|
||||
protected ObjectSet $listeners;
|
||||
/** @phpstan-var SlotValidators */
|
||||
protected ObjectSet $validators;
|
||||
|
||||
public function __construct(){
|
||||
$this->listeners = new ObjectSet();
|
||||
$this->validators = new ObjectSet();
|
||||
}
|
||||
|
||||
public function getMaxStackSize() : int{
|
||||
@ -398,4 +403,8 @@ abstract class BaseInventory implements Inventory{
|
||||
public function getListeners() : ObjectSet{
|
||||
return $this->listeners;
|
||||
}
|
||||
|
||||
public function getSlotValidators() : ObjectSet{
|
||||
return $this->validators;
|
||||
}
|
||||
}
|
||||
|
46
src/inventory/SlotValidatedInventory.php
Normal file
46
src/inventory/SlotValidatedInventory.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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\action\validator\SlotValidator;
|
||||
use pocketmine\utils\ObjectSet;
|
||||
|
||||
/**
|
||||
* A "slot validated inventory" has validators which may restrict items
|
||||
* from being placed in particular slots of the inventory when transactions are executed.
|
||||
*
|
||||
* @phpstan-type SlotValidators ObjectSet<SlotValidator>
|
||||
*/
|
||||
interface SlotValidatedInventory{
|
||||
/**
|
||||
* Returns a set of validators that will be used to determine whether an item can be placed in a particular slot.
|
||||
* All validators need to return null for the transaction to be allowed.
|
||||
* If one of the validators returns an exception, the transaction will be cancelled.
|
||||
*
|
||||
* There is no guarantee that the validators will be called in any particular order.
|
||||
*
|
||||
* @phpstan-return SlotValidators
|
||||
*/
|
||||
public function getSlotValidators() : ObjectSet;
|
||||
}
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\inventory\transaction\action;
|
||||
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\SlotValidatedInventory;
|
||||
use pocketmine\inventory\transaction\InventoryTransaction;
|
||||
use pocketmine\inventory\transaction\TransactionValidationException;
|
||||
use pocketmine\item\Item;
|
||||
@ -74,6 +75,14 @@ class SlotChangeAction extends InventoryAction{
|
||||
if($this->targetItem->getCount() > $this->inventory->getMaxStackSize()){
|
||||
throw new TransactionValidationException("Target item exceeds inventory max stack size");
|
||||
}
|
||||
if($this->inventory instanceof SlotValidatedInventory && !$this->targetItem->isNull()){
|
||||
foreach($this->inventory->getSlotValidators() as $validator){
|
||||
$ret = $validator->validate($this->inventory, $this->targetItem, $this->inventorySlot);
|
||||
if($ret !== null){
|
||||
throw new TransactionValidationException("Target item is not accepted by the inventory at slot #" . $this->inventorySlot . ": " . $ret->getMessage(), 0, $ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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\action\validator;
|
||||
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\transaction\TransactionValidationException;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class CallbackSlotValidator implements SlotValidator{
|
||||
/**
|
||||
* @phpstan-param \Closure(Inventory, Item, int) : ?TransactionValidationException $validate
|
||||
*/
|
||||
public function __construct(
|
||||
private \Closure $validate
|
||||
){
|
||||
Utils::validateCallableSignature(function(Inventory $inventory, Item $item, int $slot) : ?TransactionValidationException{ return null; }, $validate);
|
||||
}
|
||||
|
||||
public function validate(Inventory $inventory, Item $item, int $slot) : ?TransactionValidationException{
|
||||
return ($this->validate)($inventory, $item, $slot);
|
||||
}
|
||||
}
|
38
src/inventory/transaction/action/validator/SlotValidator.php
Normal file
38
src/inventory/transaction/action/validator/SlotValidator.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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\action\validator;
|
||||
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\transaction\TransactionValidationException;
|
||||
use pocketmine\item\Item;
|
||||
|
||||
/**
|
||||
* Validates a slot placement in an inventory.
|
||||
*/
|
||||
interface SlotValidator{
|
||||
/**
|
||||
* Returns null if the slot placement is valid, or a TransactionValidationException if it is not.
|
||||
*/
|
||||
public function validate(Inventory $inventory, Item $item, int $slot) : ?TransactionValidationException;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user