Last active
September 11, 2018 13:42
-
-
Save extremeheat/f1e9e0b8ca884727e6a3abfc7bfdc5a3 to your computer and use it in GitHub Desktop.
Various Minecraft: Windows 10 Edition-related patches for PocketMine-MP. Must be applied consecutively.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From ee6d6a6154ce35a4945add6aa6bd57f2144b185c Mon Sep 17 00:00:00 2001 | |
From: extremeheat <[email protected]> | |
Date: Sun, 24 Apr 2016 00:46:33 -0400 | |
Subject: [PATCH 1/4] Keep better track of inventory changes on Windows 10 | |
Edition, fix inventory moving issues | |
--- | |
src/pocketmine/Player.php | 198 ++++++++++++++++++++- | |
.../inventory/SimpleTransactionGroup.php | 26 ++- | |
2 files changed, 221 insertions(+), 3 deletions(-) | |
diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php | |
index 7cdf04e..d3fcfcb 100644 | |
--- a/src/pocketmine/Player.php | |
+++ b/src/pocketmine/Player.php | |
@@ -186,6 +186,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
public $creationTime = 0; | |
+ /** @var Item[] */ | |
+ protected $pickedupItems = []; | |
+ | |
protected $randomClientId; | |
protected $lastMovement = 0; | |
@@ -488,6 +491,57 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
return $this->perm->getEffectivePermissions(); | |
} | |
+ public function addPickedupItem(Item $item) { | |
+ if (count($this->getPickedupItems()) > 5 and !$this->isCreative()) | |
+ throw new \OutOfRangeException("Items array size cannot be greater than 5."); | |
+ | |
+ $appended = false; | |
+ | |
+ // Check if we already picked up the same item and if so append it onto | |
+ // existing picked up items. | |
+ foreach ($this->getPickedupItems() as $i) { | |
+ if ($i->deepEquals($item) and $i->getCount() < $i->getMaxStackSize()) { | |
+ | |
+ $amountFree = $i->getMaxStackSize() - $i->getCount(); | |
+ | |
+ if ($amountFree <= 0) | |
+ continue; | |
+ else { | |
+ if ($amountFree < $item->getCount()) { | |
+ $i->setCount($i->getMaxStackSize()); | |
+ $item->setCount($item->getCount() - $amountFree); | |
+ } elseif ($amountFree == $item->getCount()) { | |
+ $i->setCount($i->getMaxStackSize()); | |
+ $appended = true; | |
+ break; | |
+ } else { | |
+ $i->setCount($i->getCount() + $item->getCount()); | |
+ $appended = true; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ if (!$appended) | |
+ $this->pickedupItems[] = $item; | |
+ } | |
+ | |
+ public function removePickedupItem($index) { | |
+ unset($this->pickedupItems[$index]); | |
+ } | |
+ | |
+ public function setPickedupItems(Array $items) { | |
+ if (count($items) > 5) | |
+ throw new \OutOfRangeException("Items array size must be 5."); | |
+ $this->pickedupItems = $items; | |
+ } | |
+ | |
+ | |
+ public function getPickedupItems() { | |
+ return $this->pickedupItems; | |
+ } | |
+ | |
/** | |
* @param SourceInterface $interface | |
* @param null $clientID | |
@@ -1747,6 +1801,141 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
$this->server->onPlayerLogin($this); | |
} | |
+ public function processContainerChange(Inventory $inventory, $slot, Item $newItem, Item $oldItem) { | |
+ if ($newItem->getCount() > $newItem->getMaxStackSize() || $newItem->getCount() < 0) | |
+ $this->inventory->sendContents($this); | |
+ | |
+ if ($oldItem != $newItem) { | |
+ $this->server->getLogger()->debug("Item change!"); | |
+ if ($newItem->getId() == 0 && $oldItem->getId() != 0) { | |
+ // The entire slot was picked up. | |
+ $this->server->getLogger()->debug("PICKUP: Full slot of " . $oldItem); | |
+ | |
+ // Picked up all items in slot | |
+ $this->addPickedupItem($oldItem); | |
+ | |
+ // Clear the slot now that we've picked it up | |
+ $inventory->clear($slot); | |
+ | |
+ } else if ($newItem->deepEquals($oldItem)) { | |
+ // We're picking up a portion of the items in a slot | |
+ | |
+ if ($newItem->getCount() > $oldItem->getCount()) { | |
+ $this->server->getLogger()->debug("PLACEMENT: " . $newItem); | |
+ | |
+ // We're placing an item | |
+ if (count($this->getPickedupItems()) == 0) { | |
+ // Illegal action: we're placing an item that we haven't picked up. | |
+ $this->kick("Cannot place an item that does not exist."); | |
+ return; | |
+ } else { | |
+ // Check if we picked up the item | |
+ foreach ($this->getPickedupItems() as $k => $i) { | |
+ if ($i->deepEquals($newItem)) { | |
+ $amountPlaced = $newItem->getCount() - $oldItem->getCount(); | |
+ $remainingPickedup = $i->getCount() - $amountPlaced; | |
+ | |
+ if (!$i->getCount() >= $newItem->getCount() || $remainingPickedup < 0) { | |
+ $this->kick("You attempted to place more of an item than you have."); | |
+ return; | |
+ } | |
+ | |
+ if ($remainingPickedup) | |
+ $i->setCount($remainingPickedup); | |
+ else | |
+ $this->removePickedupItem($k); | |
+ | |
+ $this->server->getLogger()->debug("You picked up and placed: " . $i); | |
+ $inventory->setItem($slot, $newItem); | |
+ | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ } else { | |
+ $this->server->getLogger()->debug("PICKUP: " . $newItem); | |
+ // We're picking an item up | |
+ | |
+ $amountPickedup = $oldItem->getCount() - $newItem->getCount(); | |
+ if ($amountPickedup < 1) { | |
+ $this->kick("Cannot pickup less than 1 of an item!"); | |
+ return; | |
+ } | |
+ | |
+ $itemPickedup = clone $oldItem; | |
+ $itemPickedup->setCount($amountPickedup); | |
+ | |
+ $inventory->setItem($slot, $newItem); | |
+ $this->addPickedupItem($itemPickedup); | |
+ | |
+ } | |
+ } else if (($newItem->getId() != 0 && $oldItem->getId() == 0) && count($this->getPickedupItems()) == 0) { | |
+ // PE sends us this information in reverse order. | |
+ // This bit of code should never be reached because SimpleTransactionGroup.php handles it | |
+ } else if ($newItem->getId() != 0 && $oldItem->getId() == 0) { | |
+ $this->server->getLogger()->debug("PLACEMENT: Full slot of " . $newItem); | |
+ | |
+ // We're placing some items into a blank slot | |
+ foreach ($this->getPickedupItems() as $k => $i) { | |
+ if ($i->deepEquals($newItem)) { | |
+ $remainingPickedup = $i->getCount() - $newItem->getCount(); | |
+ | |
+ if (!$i->getCount() >= $newItem->getCount() || $remainingPickedup < 0) { | |
+ $this->kick("You attempted to place more of an item than you have."); | |
+ return; | |
+ } | |
+ | |
+ if ($remainingPickedup) | |
+ $i->setCount($remainingPickedup); | |
+ else | |
+ $this->removePickedupItem($k); | |
+ | |
+ $this->server->getLogger()->info("You picked up and placed: " . $i); | |
+ $inventory->setItem($slot, $newItem); | |
+ break; | |
+ } | |
+ } | |
+ } else if (!$newItem->deepEquals($oldItem)) { | |
+ if ($oldItem->deepEquals($newItem, false)) // Durability change, already handled by server | |
+ return; | |
+ | |
+ // Swapping items | |
+ $this->server->getLogger()->debug("SWAP: " . $oldItem . " for " . $newItem); | |
+ | |
+ // Check through our pickedup items to make sure that $newItem was picked up | |
+ $found = false; | |
+ foreach ($this->getPickedupItems() as $k => $i) { | |
+ if ($i->deepEquals($newItem)) { | |
+ // This checks how much of the item we picked up is actually swapped | |
+ $remainingPickedup = $i->getCount() - $newItem->getCount(); | |
+ | |
+ if (!$i->getCount() >= $newItem->getCount() || $remainingPickedup < 0) { | |
+ $this->kick("You attempted to place more of an item than you have."); | |
+ return; | |
+ } | |
+ | |
+ if ($remainingPickedup) | |
+ $i->setCount($remainingPickedup); | |
+ else | |
+ $this->removePickedupItem($k); | |
+ | |
+ $inventory->setItem($slot, $newItem); | |
+ | |
+ $found = true; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if ($found == false) { | |
+ $this->kick("You attempted to swap for an item that you don't have."); | |
+ return; | |
+ } | |
+ | |
+ $this->addPickedupItem($oldItem); | |
+ } | |
+ } | |
+ } | |
+ | |
/** | |
* Handles a Minecraft packet | |
* TODO: Separate all of this in handlers | |
@@ -2541,6 +2730,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
}else{ | |
unset($this->windowIndex[$packet->windowid]); | |
} | |
+ | |
+ if (!$this->isCreative()) | |
+ foreach ($this->getPickedupItems() as $i) | |
+ $this->level->dropItem($this, $i); | |
+ | |
+ $this->setPickedupItems([]); | |
+ | |
break; | |
case ProtocolInfo::CRAFTING_EVENT_PACKET: | |
@@ -2774,7 +2970,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
$this->currentTransaction->addTransaction($transaction); | |
- if($this->currentTransaction->canExecute()){ | |
+ if($this->currentTransaction->canExecute() || $this->currentTransaction->isWindows10Edition($transaction)){ | |
$achievements = []; | |
foreach($this->currentTransaction->getTransactions() as $ts){ | |
$inv = $ts->getInventory(); | |
diff --git a/src/pocketmine/inventory/SimpleTransactionGroup.php b/src/pocketmine/inventory/SimpleTransactionGroup.php | |
index 595cff3..a8781df 100644 | |
--- a/src/pocketmine/inventory/SimpleTransactionGroup.php | |
+++ b/src/pocketmine/inventory/SimpleTransactionGroup.php | |
@@ -41,6 +41,9 @@ class SimpleTransactionGroup implements TransactionGroup{ | |
/** @var Transaction[] */ | |
protected $transactions = []; | |
+ /** @var bool */ | |
+ protected $windows10Edition = false; | |
+ | |
/** | |
* @param Player $source | |
*/ | |
@@ -126,6 +129,22 @@ class SimpleTransactionGroup implements TransactionGroup{ | |
return true; | |
} | |
+ public function isWindows10Edition($transaction) { | |
+ if (count($this->transactions) > 1) | |
+ return false; | |
+ | |
+ if (count($this->source->getPickedupItems()) == 0 && // The player dosen't have anything picked up | |
+ (($transaction->getTargetItem()->getId() != 0 && $transaction->getSourceItem()->getId() == 0) || // An item was placed into an air block | |
+ ($transaction->getTargetItem()->getCount() > $transaction->getSourceItem()->getCount()))) { // An item was added to an existing slot with a larger quantity | |
+ // PE | |
+ $this->windows10Edition = false; | |
+ return false; | |
+ } | |
+ $this->windows10Edition = true; | |
+ return true; | |
+ } | |
+ | |
+ | |
public function canExecute(){ | |
$haveItems = []; | |
$needItems = []; | |
@@ -134,7 +153,7 @@ class SimpleTransactionGroup implements TransactionGroup{ | |
} | |
public function execute(){ | |
- if($this->hasExecuted() or !$this->canExecute()){ | |
+ if($this->hasExecuted() or (!$this->canExecute() && !$this->windows10Edition)){ | |
return false; | |
} | |
@@ -151,7 +170,10 @@ class SimpleTransactionGroup implements TransactionGroup{ | |
} | |
foreach($this->transactions as $transaction){ | |
- $transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem()); | |
+ if ($this->windows10Edition) | |
+ $this->source->processContainerChange($transaction->getInventory(), $transaction->getSlot(), $transaction->getTargetItem(), $transaction->getSourceItem()); | |
+ else | |
+ $transaction->getInventory()->setItem($transaction->getSlot(), $transaction->getTargetItem()); | |
} | |
$this->hasExecuted = true; | |
-- | |
2.8.1.windows.1 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From b916b75ae927c55916f64d5345063b201a4f8c8a Mon Sep 17 00:00:00 2001 | |
From: extremeheat <[email protected]> | |
Date: Sun, 24 Apr 2016 16:32:28 -0400 | |
Subject: [PATCH 2/4] Fix dropping items on Windows 10 Edition | |
--- | |
src/pocketmine/Player.php | 58 +++++++++++++++++++++++++++++++++++++++++++---- | |
1 file changed, 54 insertions(+), 4 deletions(-) | |
diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php | |
index d3fcfcb..2f7bc4a 100644 | |
--- a/src/pocketmine/Player.php | |
+++ b/src/pocketmine/Player.php | |
@@ -2670,18 +2670,68 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
if($this->spawned === false or $this->blocked === true or !$this->isAlive()){ | |
break; | |
} | |
- $item = $this->inventory->getItemInHand(); | |
- $ev = new PlayerDropItemEvent($this, $item); | |
+ | |
+ $replacementItem = Item::get(Item::AIR, 0, 1); | |
+ $droppedItem = null; | |
+ | |
+ // We can't just assume that we're dropping the item in hand because | |
+ // on the Windows 10 Edition you can drop items directly from inventories | |
+ if (count($this->getPickedupItems()) > 0) { | |
+ foreach ($this->getPickedupItems() as $k => $i) { | |
+ if ($packet->item->deepEquals($i)) { | |
+ $remaining = $i->getCount() - $packet->item->getCount(); | |
+ if ($remaining < 0) { | |
+ $this->kick("Cannot drop more of an item than you have!"); | |
+ break; | |
+ } else if ($remaining == 0) | |
+ $this->removePickedupItem($k); | |
+ else | |
+ $i->setCount($remaining); | |
+ | |
+ $droppedItem = $packet->item; | |
+ // Nothing to replace when dropping from inventory | |
+ $replacementItem = null; | |
+ } | |
+ } | |
+ } else { | |
+ $itemInHand = clone $this->inventory->getItemInHand(); | |
+ if (!$itemInHand->deepEquals($packet->item)) { | |
+ // The block held and the block being dropped is not the same | |
+ break; | |
+ } elseif ($itemInHand->getCount() != $packet->item->getCount()) { | |
+ // The only difference is that the amount dropped differs | |
+ $remaining = $itemInHand->getCount() - $packet->item->getCount(); | |
+ if ($remaining < 0) { | |
+ // The client is attempting to drop more of an item than in hand | |
+ break; | |
+ } else { | |
+ $itemInHand->setCount($remaining); | |
+ $replacementItem = $itemInHand; | |
+ $droppedItem = $packet->item; | |
+ } | |
+ } else { | |
+ // Dropped everyting in slot | |
+ $droppedItem = $itemInHand; | |
+ } | |
+ } | |
+ | |
+ if (!$droppedItem) | |
+ break; | |
+ | |
+ $ev = new PlayerDropItemEvent($this, $droppedItem); | |
$this->server->getPluginManager()->callEvent($ev); | |
if($ev->isCancelled()){ | |
$this->inventory->sendContents($this); | |
break; | |
} | |
- $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1)); | |
+ if ($replacementItem) | |
+ $this->inventory->setItemInHand($replacementItem); | |
+ | |
$motion = $this->getDirectionVector()->multiply(0.4); | |
- $this->level->dropItem($this->add(0, 1.3, 0), $item, $motion, 40); | |
+ // TODO: Stack nearby item drops | |
+ $this->level->dropItem($this->add(0, 1.3, 0), $droppedItem, $motion, 40); | |
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false); | |
break; | |
-- | |
2.8.1.windows.1 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From a28f2262e649881ee07a81b3527b153cb0c80e6f Mon Sep 17 00:00:00 2001 | |
From: extremeheat <[email protected]> | |
Date: Mon, 25 Apr 2016 15:25:58 -0400 | |
Subject: [PATCH 3/4] Account for hotbar <-> slot changes | |
--- | |
src/pocketmine/Player.php | 6 ++++++ | |
1 file changed, 6 insertions(+) | |
diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php | |
index 2f7bc4a..490ba0d 100644 | |
--- a/src/pocketmine/Player.php | |
+++ b/src/pocketmine/Player.php | |
@@ -1927,6 +1927,12 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
} | |
if ($found == false) { | |
+ // Hotbar <-> slot mapping change | |
+ if ($this->inventory->getItem($hotbarSlot = $this->inventory->getHotbarSlotIndex($slot))->deepEquals($newItem)) { | |
+ $this->inventory->setItem($hotbarSlot, $oldItem); | |
+ $this->inventory->setItem($slot, $newItem); | |
+ return; | |
+ } | |
$this->kick("You attempted to swap for an item that you don't have."); | |
return; | |
} | |
-- | |
2.8.1.windows.1 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 996538338a6f0313f48c11b7eb984560959a719f Mon Sep 17 00:00:00 2001 | |
From: extremeheat <[email protected]> | |
Date: Tue, 26 Apr 2016 00:21:00 -0400 | |
Subject: [PATCH] Fix crafting in Windows 10 Edition | |
--- | |
src/pocketmine/Player.php | 80 ++++++++++++++++++++++------ | |
src/pocketmine/inventory/CraftingManager.php | 8 +++ | |
src/pocketmine/inventory/ShapedRecipe.php | 13 +++++ | |
3 files changed, 84 insertions(+), 17 deletions(-) | |
diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php | |
index 490ba0d..5bc4b52 100644 | |
--- a/src/pocketmine/Player.php | |
+++ b/src/pocketmine/Player.php | |
@@ -186,6 +186,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
public $creationTime = 0; | |
+ protected $maxPickupableItems = 10; // 9 crafting, 1 held | |
/** @var Item[] */ | |
protected $pickedupItems = []; | |
@@ -491,9 +492,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
return $this->perm->getEffectivePermissions(); | |
} | |
- public function addPickedupItem(Item $item) { | |
- if (count($this->getPickedupItems()) > 5 and !$this->isCreative()) | |
- throw new \OutOfRangeException("Items array size cannot be greater than 5."); | |
+ public function addPickedupItem(Item $item, bool $ignoreItemCount = false) { | |
+ if (count($this->getPickedupItems()) >= $this->maxPickupableItems and !$this->isCreative() and !$ignoreItemCount) | |
+ throw new \OutOfRangeException("Items array size cannot be greater than {$this->maxPickupableItems}."); | |
$appended = false; | |
@@ -531,9 +532,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
unset($this->pickedupItems[$index]); | |
} | |
- public function setPickedupItems(Array $items) { | |
- if (count($items) > 5) | |
- throw new \OutOfRangeException("Items array size must be 5."); | |
+ public function setPickedupItems(Array $items, bool $ignoreItemCount = false) { | |
+ if (count($items) > $this->maxPickupableItems and !$ignoreItemCount) | |
+ throw new \OutOfRangeException("Items array size must be {$this->maxPickupableItems}."); | |
$this->pickedupItems = $items; | |
} | |
@@ -2805,27 +2806,67 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
$this->dataPacket($pk); | |
break; | |
} | |
- | |
$recipe = $this->server->getCraftingManager()->getRecipe($packet->id); | |
- | |
if($recipe === null or (($recipe instanceof BigShapelessRecipe or $recipe instanceof BigShapedRecipe) and $this->craftingType === 0)){ | |
$this->inventory->sendContents($this); | |
break; | |
} | |
- | |
foreach($packet->input as $i => $item){ | |
if($item->getDamage() === -1 or $item->getDamage() === 0xffff){ | |
$item->setDamage(null); | |
} | |
- | |
if($i < 9 and $item->getId() > 0){ | |
$item->setCount(1); | |
} | |
} | |
- | |
$canCraft = true; | |
+ $giveItem = true; | |
+ // Keep a local copy so we can revert changes if needed | |
+ $pickedupItems = $this->getPickedupItems(); | |
+ | |
+ if (empty($packet->input)) { | |
+ // Get a list of recipes that can be used to craft the result. | |
+ $recipes = $this->server->getCraftingManager()->getRecipesByItem($packet->output[0]); | |
+ // As soon as a recipe whose ingridients can be satisfied is found, | |
+ // use it. This shouldn't cause any issues for the few items that have | |
+ // multiple recipes they can be crafted with. | |
+ $canCraft = false; | |
+ foreach ($recipes as $r) { | |
+ $need = $r->getIngredientList(); | |
+ $have = []; | |
- if($recipe instanceof ShapedRecipe){ | |
+ foreach ($need as $i){ | |
+ foreach ($this->getPickedupItems() as $key => $item) { | |
+ if ($need == $have) // We already have all the things we need | |
+ break; | |
+ if ($item->deepEquals($i, $i->getDamage() !== null, $i->getCompoundTag() !== null)) { | |
+ $amountRemaining = $item->getCount() - $i->getCount(); | |
+ | |
+ if ($amountRemaining > 0) { | |
+ $item->setCount($amountRemaining); | |
+ $have[] = $i; | |
+ } elseif ($amountRemaining <= 0) { | |
+ // Relatively safe operation here as items stack | |
+ $have[] = $item; | |
+ $this->removePickedupItem($key); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ if ($need != $have) { | |
+ // Can't craft | |
+ $this->setPickedupItems($pickedupItems); | |
+ continue; | |
+ } else { | |
+ // Reset the recipe to the correct one | |
+ $recipe = $r; | |
+ $canCraft = true; | |
+ $giveItem = false; | |
+ $this->addPickedupItem(clone $recipe->getResult(), true); | |
+ break; | |
+ } | |
+ } | |
+ }elseif($recipe instanceof ShapedRecipe){ | |
for($x = 0; $x < 3 and $canCraft; ++$x){ | |
for($y = 0; $y < 3; ++$y){ | |
$item = $packet->input[$y * 3 + $x]; | |
@@ -2878,6 +2919,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
if(!$canCraft or !$recipe->getResult()->deepEquals($result)){ | |
$this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": expected " . $recipe->getResult() . ", got " . $result . ", using: " . implode(", ", $ingredients)); | |
$this->inventory->sendContents($this); | |
+ $this->setPickedupItems($pickedupItems); | |
break; | |
} | |
@@ -2902,6 +2944,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
if(!$canCraft){ | |
$this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": client does not have enough items, using: " . implode(", ", $ingredients)); | |
$this->inventory->sendContents($this); | |
+ $this->setPickedupItems($pickedupItems); | |
break; | |
} | |
@@ -2909,6 +2952,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
if($ev->isCancelled()){ | |
$this->inventory->sendContents($this); | |
+ $this->setPickedupItems($pickedupItems); | |
break; | |
} | |
@@ -2929,10 +2973,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
$this->inventory->setItem($slot, $newItem); | |
} | |
- $extraItem = $this->inventory->addItem($recipe->getResult()); | |
- if(count($extraItem) > 0){ | |
- foreach($extraItem as $item){ | |
- $this->level->dropItem($this, $item); | |
+ // Avoid item client-sided duplicating in Windows 10 Edition as the item is already created | |
+ if ($giveItem) { | |
+ $extraItem = $this->inventory->addItem($recipe->getResult()); | |
+ if(count($extraItem) > 0){ | |
+ foreach($extraItem as $item){ | |
+ $this->level->dropItem($this, $item); | |
+ } | |
} | |
} | |
@@ -2970,7 +3017,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade | |
$this->awardAchievement("diamond"); | |
break; | |
} | |
- | |
break; | |
case ProtocolInfo::CONTAINER_SET_SLOT_PACKET: | |
diff --git a/src/pocketmine/inventory/CraftingManager.php b/src/pocketmine/inventory/CraftingManager.php | |
index 6ff6f1e..876cb30 100644 | |
--- a/src/pocketmine/inventory/CraftingManager.php | |
+++ b/src/pocketmine/inventory/CraftingManager.php | |
@@ -126,6 +126,14 @@ class CraftingManager{ | |
} | |
/** | |
+ * @param Item $item | |
+ * @return Recipe[] | |
+ */ | |
+ public function getRecipesByItem(Item $item) { | |
+ return @array_values($this->recipeLookup[$item->getId() . ":" . $item->getDamage()]) ?? []; | |
+ } | |
+ | |
+ /** | |
* @return FurnaceRecipe[] | |
*/ | |
public function getFurnaceRecipes(){ | |
diff --git a/src/pocketmine/inventory/ShapedRecipe.php b/src/pocketmine/inventory/ShapedRecipe.php | |
index 823e6c4..864a93a 100644 | |
--- a/src/pocketmine/inventory/ShapedRecipe.php | |
+++ b/src/pocketmine/inventory/ShapedRecipe.php | |
@@ -139,6 +139,19 @@ class ShapedRecipe implements Recipe{ | |
} | |
/** | |
+ * @return Item[][] | |
+ */ | |
+ public function getIngredientList() { | |
+ $ingredients = []; | |
+ for ($x = 0; $x < 3; ++$x) | |
+ for ($y = 0; $y < 3; ++$y) | |
+ if (!empty($this->ingredients[$x][$y])) | |
+ if (!$this->ingredients[$x][$y]->getId() == Item::AIR) | |
+ $ingredients[] = $this->ingredients[$x][$y]; | |
+ return $ingredients; | |
+ } | |
+ | |
+ /** | |
* @return string[] | |
*/ | |
public function getShape(){ | |
-- | |
2.8.1.windows.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
????