InGamePacketHandler: queue slots for syncing if they appear in requestChangedSlots

this is essentially a prediction without the actual predicted item. We have to sync these regardless of what happens.

fixes #5708
This commit is contained in:
Dylan K. Taylor 2023-04-24 14:06:29 +01:00
parent 3ecc980bc4
commit a4f2b99ed5
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -328,6 +328,9 @@ class InGamePacketHandler extends PacketHandler{
if(count($packet->trData->getActions()) > 50){
throw new PacketHandlingException("Too many actions in inventory transaction");
}
if(count($packet->requestChangedSlots) > 10){
throw new PacketHandlingException("Too many slot sync requests in inventory transaction");
}
$this->inventoryManager->setCurrentItemStackRequestId($packet->requestId);
$this->inventoryManager->addRawPredictedSlotChanges($packet->trData->getActions());
@ -347,6 +350,21 @@ class InGamePacketHandler extends PacketHandler{
}
$this->inventoryManager->syncMismatchedPredictedSlotChanges();
//requestChangedSlots asks the server to always send out the contents of the specified slots, even if they
//haven't changed. Handling these is necessary to ensure the client inventory stays in sync if the server
//rejects the transaction. The most common example of this is equipping armor by right-click, which doesn't send
//a legacy prediction action for the destination armor slot.
foreach($packet->requestChangedSlots as $containerInfo){
$windowId = ItemStackContainerIdTranslator::translate($containerInfo->getContainerId(), $this->inventoryManager->getCurrentWindowId());
foreach($containerInfo->getChangedSlotIndexes() as $slot){
$inventoryAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slot);
if($inventoryAndSlot !== null){ //trigger the normal slot sync logic
$this->inventoryManager->onSlotChange($inventoryAndSlot[0], $inventoryAndSlot[1]);
}
}
}
$this->inventoryManager->setCurrentItemStackRequestId(null);
return $result;
}