From 6756203aec533979dd0f8d31f41669676c934b27 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 10 Jun 2019 16:54:45 +0100 Subject: [PATCH 1/5] InventoryTransaction: Added a warning about ordering --- .../inventory/transaction/InventoryTransaction.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pocketmine/inventory/transaction/InventoryTransaction.php b/src/pocketmine/inventory/transaction/InventoryTransaction.php index 55219fac6..f5d67be74 100644 --- a/src/pocketmine/inventory/transaction/InventoryTransaction.php +++ b/src/pocketmine/inventory/transaction/InventoryTransaction.php @@ -75,6 +75,11 @@ class InventoryTransaction{ } /** + * Returns an **unordered** set of actions involved in this transaction. + * + * WARNING: This system is **explicitly designed NOT to care about ordering**. Any order seen in this set has NO + * significance and should not be relied on. + * * @return InventoryAction[] */ public function getActions() : array{ @@ -271,6 +276,8 @@ class InventoryTransaction{ return false; } + $this->shuffleActions(); + $this->validate(); if(!$this->callExecuteEvent()){ From 96d3f4f78bf770992160b1a58f4076bd72fadcd6 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 10 Jun 2019 17:19:03 +0100 Subject: [PATCH 2/5] Updated documentation for transaction classes --- .../inventory/transaction/CraftingTransaction.php | 15 +++++++++++++++ .../transaction/InventoryTransaction.php | 14 +++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/pocketmine/inventory/transaction/CraftingTransaction.php b/src/pocketmine/inventory/transaction/CraftingTransaction.php index e5f98c4f4..e91085812 100644 --- a/src/pocketmine/inventory/transaction/CraftingTransaction.php +++ b/src/pocketmine/inventory/transaction/CraftingTransaction.php @@ -32,6 +32,21 @@ use function array_pop; use function count; use function intdiv; +/** + * This transaction type is specialized for crafting validation. It shares most of the same semantics of the base + * inventory transaction type, but the requirement for validity is slightly different. + * + * It is expected that the actions in this transaction type will produce an **unbalanced result**, i.e. some inputs won't + * have corresponding outputs, and vice versa. The reason why is because the unmatched inputs are recipe inputs, and + * the unmatched outputs are recipe results. + * + * Therefore, the validity requirement is that the imbalance of the transaction should match the expected inputs and + * outputs of a registered crafting recipe. + * + * This transaction allows multiple repetitions of the same recipe to be crafted in a single batch. In the case of batch + * crafting, the number of unmatched inputs and outputs must be exactly divisible by the expected recipe ingredients and + * results, with no remainder. Any leftovers are expected to be emitted back to the crafting grid. + */ class CraftingTransaction extends InventoryTransaction{ /** @var CraftingRecipe|null */ protected $recipe; diff --git a/src/pocketmine/inventory/transaction/InventoryTransaction.php b/src/pocketmine/inventory/transaction/InventoryTransaction.php index f5d67be74..f1e98c10e 100644 --- a/src/pocketmine/inventory/transaction/InventoryTransaction.php +++ b/src/pocketmine/inventory/transaction/InventoryTransaction.php @@ -36,7 +36,19 @@ use function min; use function spl_object_hash; /** - * This InventoryTransaction only allows doing Transaction between one / two inventories + * This is the basic type for an inventory transaction. This is used for moving items between inventories, dropping + * items and more. It allows transactions with multiple inputs and outputs. + * + * Validation **does not** depend on ordering. This means that the actions can appear in any order and still be valid. + * The only validity requirement for this transaction type is that the balance of items must add up to zero. This means: + * - No new outputs without matching input amounts + * - No inputs without matching output amounts + * - No userdata changes (item state, NBT, etc) + * + * A transaction is composed of "actions", which are pairs of inputs and outputs which target a specific itemstack in + * a specific location. There are multiple types of inventory actions which might be involved in a transaction. + * + * @see InventoryAction */ class InventoryTransaction{ protected $hasExecuted = false; From b6f3f6120b68ad9f18d9d1f56cdd1a396f0f605a Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 10 Jun 2019 17:24:16 +0100 Subject: [PATCH 3/5] InventoryTransaction: Shuffle actions on execution to prevent plugins relying on the order closes #2955 --- .../transaction/InventoryTransaction.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/pocketmine/inventory/transaction/InventoryTransaction.php b/src/pocketmine/inventory/transaction/InventoryTransaction.php index f1e98c10e..6f0f7b238 100644 --- a/src/pocketmine/inventory/transaction/InventoryTransaction.php +++ b/src/pocketmine/inventory/transaction/InventoryTransaction.php @@ -29,10 +29,12 @@ use pocketmine\inventory\transaction\action\InventoryAction; use pocketmine\inventory\transaction\action\SlotChangeAction; use pocketmine\item\Item; use pocketmine\Player; +use function array_keys; use function assert; use function count; use function get_class; use function min; +use function shuffle; use function spl_object_hash; /** @@ -110,6 +112,19 @@ class InventoryTransaction{ } } + /** + * Shuffles actions in the transaction to prevent external things relying on any implicit ordering. + */ + private function shuffleActions() : void{ + $keys = array_keys($this->actions); + shuffle($keys); + $actions = []; + foreach($keys as $key){ + $actions[$key] = $this->actions[$key]; + } + $this->actions = $actions; + } + /** * @internal This method should not be used by plugins, it's used to add tracked inventories for InventoryActions * involving inventories. From a42f68d3cf368535d205d35d4bf7d1c201fbb3d8 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 10 Jun 2019 17:55:50 +0100 Subject: [PATCH 4/5] Release 3.8.4 --- src/pocketmine/VersionInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pocketmine/VersionInfo.php b/src/pocketmine/VersionInfo.php index 872b3523f..8790f972f 100644 --- a/src/pocketmine/VersionInfo.php +++ b/src/pocketmine/VersionInfo.php @@ -23,5 +23,5 @@ namespace pocketmine; const NAME = "PocketMine-MP"; const BASE_VERSION = "3.8.4"; -const IS_DEVELOPMENT_BUILD = true; +const IS_DEVELOPMENT_BUILD = false; const BUILD_NUMBER = 0; From 7c1f038f2030272f24ffb75f53fd3c4186e984b5 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 10 Jun 2019 17:56:23 +0100 Subject: [PATCH 5/5] 3.8.5 is next --- src/pocketmine/VersionInfo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pocketmine/VersionInfo.php b/src/pocketmine/VersionInfo.php index 8790f972f..a446b583c 100644 --- a/src/pocketmine/VersionInfo.php +++ b/src/pocketmine/VersionInfo.php @@ -22,6 +22,6 @@ namespace pocketmine; const NAME = "PocketMine-MP"; -const BASE_VERSION = "3.8.4"; -const IS_DEVELOPMENT_BUILD = false; +const BASE_VERSION = "3.8.5"; +const IS_DEVELOPMENT_BUILD = true; const BUILD_NUMBER = 0;