ItemExchange: support multiple inputs and outputs per exchange - #45
Open
ProgrammerGodMC wants to merge 1 commit into
Open
ItemExchange: support multiple inputs and outputs per exchange#45ProgrammerGodMC wants to merge 1 commit into
ProgrammerGodMC wants to merge 1 commit into
Conversation
Author
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
An exchange could only ever pair one input rule with one output rule. A single exchange can now require several different items and pay out several — e.g. 2 iron + 1 diamond for a sword + a shield.
Rules are grouped by their order in the shop inventory: an unbroken run of inputs followed by an unbroken run of outputs is one exchange, and the next input after an output starts the next. Trades stay all-or-nothing — the buyer must have every input and the shop every output, or nothing moves. Every input and output is always listed when browsing, so a buyer always sees the full price before paying it.
Behaviour change
input,output,input,output— the documented and common layout — parses identically to before, so ordinary shops are unaffected.Consecutive inputs now merge instead of splitting.
input,input,output,outputwas previously a donation of the first input plus an exchange of the second input for the first output, with the second output ignored; it is now one exchange taking both inputs for both outputs.This matters most for donation shops. A chest of 12 input rules with no outputs used to be 12 separate donations; it is now a single exchange demanding all 12 items at once — and past
maxInputsit is disabled entirely.Why the new stock allocator
Utilities.getStock/calculateStockare load-bearing, not cosmetic. The old per-rule scan searched the inventory independently for each rule, so two rules matching the same items would both claim the same stack and the trade would silently under-charge. The new allocator reserves across all rules at once with no double-claiming.Conformance is precomputed once per call because
ExchangeRule.conforms()builds its debug strings unconditionally, and the stock search would otherwise multiply its call count on the browse path — which runs on every punch.Exchange size limits
A bulk rule block holds any number of rules in one item, so a very large exchange is cheap to build. New
config.ymlsection, live-reloadable with/iereload:An over-limit exchange is rejected outright, never trimmed — dropping an input would let a buyer underpay, and dropping an output would shortchange them. Enforcement is in
TradeRule.isValid(), the one chokepoint both the grouping and the listener already gate on, and it sits after bulk flattening so loose and bulk rules are measured identically. The limit applies per exchange, not per bulk item: one bulk block can still hold any number of normal exchanges.Because rule items look normal in a container and a bulk block hides its contents, a disabled exchange is announced on punch
0means no limit configs without atradeLimitssection fall back to the jar defaultsNotes
TradeRulenow holds lists.getInput(),getOutput()andhasOutput()are retainedNameLayerGluenow checks every input. It would have compiled unchanged, but a group lock on any non-first input would have been silently bypassed.InventoryUtilsalready accepted item arrays and committed atomically.Testing
Tested on a local Paper 1.21.8 server running the full plugin set, and it works:
LLM use
Implementation and write-up assisted by Claude Opus 5.