Add Brew Packer factory to make BreweryX brews stackable - #960
Conversation
Brews are potions, which vanilla caps at a stack size of one, so every bottle takes a whole inventory slot and bulk trade is painful. The new recipe hands back the same brew with the vanilla max stack size component set on it, so bottles merge into one slot while staying real, drinkable, BreweryX readable brews. A brew has to be sealed first, because BreweryX writes a fresh random scramble id into an unsealed brew on every save and no two of those are ever equal. Pre-sealed brews are taken as they are, unsealed ones are sealed during the run when seal_unsealed is on. Sealed brews are also immutable, so they stay inert in barrels and distillers. Only brews on the recipe's allow list are touched, each with its own stack size. Entries are keyed by BreweryX brew id rather than display name, since the id is stable across renames and unique, whereas the name is a bad/normal/good triplet that is easy to pick wrong. Ids cannot be validated at parse time because BreweryX loads POSTWORLD, so unknown ones are reported once on first use. BreweryX is a compileOnly dependency on the jar already vendored in ansible/src/paper-plugins, matching zorweth, kitpvp and simpleadminhacks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
BreweryX swaps the potion for a plain one in PlayerItemConsumeEvent so vanilla does not apply its effects. That makes the server finish using the replacement rather than the held stack, and put the result in the hand slot with setItemInHand, which overwrites the stack wholesale. Drinking one brew off a stack of sixteen would leave the player holding a single glass bottle, destroying the other fifteen. Setting the event's replacement decides what ends up in the hand, so the rest of the stack goes back there and the empty bottle is handed over separately, since overriding the replacement drops the one the server made. Stacks now drain a bottle at a time, the way eating from a stack of food does. Runs after BreweryX's own handler, which sits on HIGHEST, so a drink it refused in creative or through BPlayer#drink is left alone rather than paying out a free bottle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A standard FCC factory carrying pack_brews and repair_brew_packer. The
allow list starts with the everyday brews at 16 and the spirits lower,
and packed brews are lored 'Packed Brew ({size})' so players can tell
them from ordinary ones and read the limit off the bottle.
Setup cost and the allow list are a starting point for balance rather
than a settled one. Note that both are effectively permanent once
players hold stock: the max stack size component stays on the item, and
brews packed at different sizes or under different lore will not stack
with each other.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The LLM disclosure policy requires the model(s) used to be specified as well, can you add them? |
|
Yes, I haven't fully reviewed all of this myself, nor tested it locally or a whole bunch of other things I need to do before this is marked ready for review. Just wanted to get it out of the context window before I leave for a few hours. But, the model used was Claude Opus 5 with high effort. |
| brew_packer: | ||
| type: FCC | ||
| name: Brew Packer | ||
| citadelBreakReduction: 0.8 |
There was a problem hiding this comment.
Consistent with the compactor, but almost every other factory uses 1.0
| type: FCC | ||
| name: Brew Packer | ||
| citadelBreakReduction: 0.8 | ||
| setupcost: |
There was a problem hiding this comment.
A real balanced setup cost is going to be needed before this is released.
| brew_packer: | ||
| type: FCC | ||
| name: Brew Packer | ||
| citadelBreakReduction: 0.8 |
| type: DECOMPACT | ||
| input: | ||
| compact_lore: Compacted Item | ||
| pack_brews: |
There was a problem hiding this comment.
Essentially all of this needs to be balanced/reviewed further.
| compileOnly(project(":plugins:heliodor-paper")) | ||
| compileOnly(project(":plugins:zorweth-paper")) | ||
| compileOnly(libs.worldedit) | ||
| compileOnly(files("../../ansible/src/paper-plugins/BreweryX-3.6.3.jar")) |
There was a problem hiding this comment.
I'm sure brewery has a maven repo entry or something we can use here instead. This seems pretty brittle.
What
Adds a
BREW_STACKrecipe type to FactoryMod and a Brew Packer factory that makes BreweryX brews stackable.Brews are potions, which vanilla caps at a stack size of one, so every bottle takes a whole inventory slot and bulk trade and transport are painful. The recipe hands back the same brew with the vanilla
max_stack_sizecomponent set on it, so bottles merge into a single slot while staying real, drinkable, BreweryX readable brews. Stacks split and merge like any other item.How it works
seal_unsealedis on. Sealing is irreversible and rounds an odd quality down to the next even one, exactly as BreweryX's own sealing table does.Brew#age,Brew#distillSlotandBrew#canDistillall short circuit onimmutable, andBSealer/MCBarrelguard onisStripped/isStatic, so a stack cannot be aged, distilled or re-sealed in bulk. No duplication vector through BreweryX's mechanics.bad/normal/goodtriplet that is easy to pick the wrong part of. Ids cannot be checked at parse time because BreweryX loadsPOSTWORLD, so unknown ones are reported once on first use rather than failing silently.Drinking from a stack
This needed a fix. BreweryX swaps the potion for a plain one in
PlayerItemConsumeEventso vanilla does not apply its effects, which sends the server down the branch that finishes using the replacement rather than the held stack and then callssetItemInHand, overwriting the stack wholesale. Without this, drinking one brew off a stack of sixteen would leave the player holding a single glass bottle and destroy the other fifteen.BrewStackListenersets the event's replacement to the rest of the stack and hands the empty bottle over separately, since overriding the replacement drops the one the server made. Stacks now drain a bottle at a time, the way eating from a stack of food does. It runs after BreweryX's handler (HIGHEST) so a drink refused in creative or byBPlayer#drinkis left alone.Config
BREW_STACKis documented in the plugin's defaultconfig.yml. The live factory is added to both the paper and zorweth FactoryMod configs:allowed_brewsalso accepts a plain list of ids, and{size}inpacked_loreis replaced with that brew's limit.BreweryX is a
compileOnlydependency on the jar already vendored inansible/src/paper-plugins, matching zorweth, kitpvp and simpleadminhacks, and is asoftdepend— without it the recipe is skipped with a warning and the listener is not registered.Testing
This has not been run on a server yet. It compiles and the behaviour was traced through Paper, CraftBukkit and BreweryX source, but FactoryMod has no test suite so there is no runtime evidence. Reviewers should treat the following as unverified:
containedExactlyInand a wrong amount just makes the crafting table silently do nothingBalance note
Setup cost and the allow list are a starting point, not settled balance. Both are effectively permanent once players hold stock: the
max_stack_sizecomponent stays on the item, and brews packed at different sizes or under differentpacked_lorewill not stack with each other, so these are best fixed before release.🤖 Generated with Claude Code