Conversation
Storage items were granted to the player before being debited from the virtual inventory, and the transactional result of the debit was ignored. A stale GUI projection (a second viewer, or a repaint that had not run yet) could hand out the same items twice via take-all or shift-click. Debit the virtual inventory first and only grant what was actually removed in transferToPlayerInventory, transferItems and handleDropPageItems. The count-map's existing transactional removeItems is now the gate, so stale views cannot mint items.
Contributor
|
@xthedev1 1.8.2 already covers the duplication issue. Further changes may potentially introduce performance issues or create other duplication exploits. For now, I think it's safer to keep the current implementation. Thanks |
Author
hm alright thanks! |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes two item duplication exploits in the spawner storage GUI where two players viewing the same spawner (for example, two accounts synced with LAN Sync) can each take the same items.
Repro 1 — take-all: open the same Spawner Storage GUI on two accounts, turn LAN sync delay off, click take-all twice on each account, then turn sync delay back on. The items appear on both accounts.
Repro 2 — shift-click: same setup, shift-click the same stack out of the spawner storage on each account. The items appear on both accounts.
Root cause
SpawnerStorageActionmoved items into the player's inventory before debiting the virtual inventory, and ignored the transactional result of the debit:transferToPlayerInventory(left / right / shift click) computed the amount from the GUI slot, wrote it into the player inventory, then calledremoveItemsAndUpdateSellValue(...)and only used the result to decide whether to repaint.transferItems(take-all) did the same and discarded the boolean result entirely.handleDropPageItemsremoved from the virtual inventory but dropped the items regardless of the result.The storage GUI is only a projection of
VirtualInventory, so a second viewer's copy — or a repaint that has been scheduled but not yet run — can be stale. Both handlers therefore granted items that had already been debited by another viewer.Fix
Debit first, grant second:
transferToPlayerInventoryandtransferItemsnow compute how much the player can receive, callremoveItemsAndUpdateSellValuefirst, and only add to the player inventory the amount that was actually removed. A failed removal grants nothing and repaints the stale view.handleDropPageItemsnow aborts the drop if the debit fails.calculatePlayerCapacity/addToPlayerInventoryhelpers so the amount granted is always exactly the amount debited.This makes
VirtualInventory.removeItems' existing transactional check the single gate for granting items, so stale or duplicate GUI views can no longer mint items.Testing
./gradlew buildsucceeds.Notes
SpawnerStorageAction.javachanged.