mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-30 23:29:54 +00:00
InGamePacketHandler: fixed dropping items from unselected hotbar slots
This commit is contained in:
parent
043e81e737
commit
ea386c42d3
@ -386,39 +386,51 @@ class InGamePacketHandler extends PacketHandler{
|
|||||||
throw new PacketHandlingException("Expected exactly 2 actions for dropping an item");
|
throw new PacketHandlingException("Expected exactly 2 actions for dropping an item");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sourceSlot = null;
|
||||||
|
$clientItemStack = null;
|
||||||
|
$droppedCount = null;
|
||||||
|
|
||||||
foreach($data->getActions() as $networkInventoryAction){
|
foreach($data->getActions() as $networkInventoryAction){
|
||||||
if($networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_WORLD && $networkInventoryAction->inventorySlot == NetworkInventoryAction::ACTION_MAGIC_SLOT_DROP_ITEM){
|
if($networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_WORLD && $networkInventoryAction->inventorySlot == NetworkInventoryAction::ACTION_MAGIC_SLOT_DROP_ITEM){
|
||||||
//drop item - we don't need to validate this, we only care about the count
|
$droppedCount = $networkInventoryAction->newItem->getItemStack()->getCount();
|
||||||
//if the resulting actions don't match the client for some reason, it will trigger an automatic
|
if($droppedCount <= 0){
|
||||||
//prediction rollback anyway.
|
|
||||||
//it's technically possible to see this more than once, but a normal client should never do that.
|
|
||||||
$droppedItemStack = $networkInventoryAction->newItem->getItemStack();
|
|
||||||
if($droppedItemStack->getCount() <= 0){
|
|
||||||
throw new PacketHandlingException("Expected positive count for dropped item");
|
throw new PacketHandlingException("Expected positive count for dropped item");
|
||||||
}
|
}
|
||||||
$inventory = $this->player->getInventory();
|
}elseif($networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER && $networkInventoryAction->windowId === ContainerIds::INVENTORY){
|
||||||
|
//mobile players can drop an item from a non-selected hotbar slot
|
||||||
$heldItem = $inventory->getItemInHand();
|
$sourceSlot = $networkInventoryAction->inventorySlot;
|
||||||
$heldItemStack = TypeConverter::getInstance()->coreItemStackToNet($heldItem);
|
$clientItemStack = $networkInventoryAction->oldItem->getItemStack();
|
||||||
//because the client doesn't tell us the expected itemstack ID, we have to deep-compare our known
|
}else{
|
||||||
//itemstack info with the one the client sent. This is costly, but we don't have any other option :(
|
throw new PacketHandlingException("Unexpected action type in drop item transaction");
|
||||||
if($heldItemStack->getCount() < $droppedItemStack->getCount() || !$heldItemStack->equalsWithoutCount($droppedItemStack)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//this modifies $heldItem
|
|
||||||
$droppedItem = $heldItem->pop($droppedItemStack->getCount());
|
|
||||||
|
|
||||||
$builder = new TransactionBuilder();
|
|
||||||
$builder->getInventory($inventory)->setItem($inventory->getHeldItemIndex(), $heldItem);
|
|
||||||
$builder->addAction(new DropItemAction($droppedItem));
|
|
||||||
|
|
||||||
$transaction = new InventoryTransaction($this->player, $builder->generateActions());
|
|
||||||
return $this->executeInventoryTransaction($transaction, $itemStackRequestId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if($sourceSlot === null || $clientItemStack === null || $droppedCount === null){
|
||||||
|
throw new PacketHandlingException("Missing information in drop item transaction, need source slot, client item stack and dropped count");
|
||||||
|
}
|
||||||
|
|
||||||
throw new PacketHandlingException("Legacy 'normal' transactions should only be used for dropping items");
|
$inventory = $this->player->getInventory();
|
||||||
|
|
||||||
|
if(!$inventory->slotExists($sourceSlot)){
|
||||||
|
return false; //TODO: size desync??
|
||||||
|
}
|
||||||
|
|
||||||
|
$sourceSlotItem = $inventory->getItem($sourceSlot);
|
||||||
|
$serverItemStack = TypeConverter::getInstance()->coreItemStackToNet($sourceSlotItem);
|
||||||
|
//because the client doesn't tell us the expected itemstack ID, we have to deep-compare our known
|
||||||
|
//itemstack info with the one the client sent. This is costly, but we don't have any other option :(
|
||||||
|
if(!$serverItemStack->equals($clientItemStack)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this modifies $sourceSlotItem
|
||||||
|
$droppedItem = $sourceSlotItem->pop($droppedCount);
|
||||||
|
|
||||||
|
$builder = new TransactionBuilder();
|
||||||
|
$builder->getInventory($inventory)->setItem($sourceSlot, $sourceSlotItem);
|
||||||
|
$builder->addAction(new DropItemAction($droppedItem));
|
||||||
|
|
||||||
|
$transaction = new InventoryTransaction($this->player, $builder->generateActions());
|
||||||
|
return $this->executeInventoryTransaction($transaction, $itemStackRequestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleUseItemTransaction(UseItemTransactionData $data) : bool{
|
private function handleUseItemTransaction(UseItemTransactionData $data) : bool{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user