Skip to content

Block free (b:0 / s:0) shops; break pre-existing ones on interact#3

Merged
ParadauxIO merged 1 commit into
masterfrom
feat/block-free-shops
May 30, 2026
Merged

Block free (b:0 / s:0) shops; break pre-existing ones on interact#3
ParadauxIO merged 1 commit into
masterfrom
feat/block-free-shops

Conversation

@ParadauxIO
Copy link
Copy Markdown
Collaborator

Free shops — a buy or sell price of exactly 0 — are an abuse vector. This disallows them and cleans up any that already exist.

Behaviour

  • Creation blockedPreShopCreation/FreePriceChecker runs after PriceChecker normalises the price line and rejects creation (INVALID_PRICE) when the buy or sell price is 0. An unoffered side (NO_PRICE = -1) is untouched, so a normal buy-only / sell-only shop with a non-zero price still works fine.
  • Pre-existing ones broken on interactPreTransaction/FreeShopBreaker (LOWEST): the first time someone clicks a free shop, the trade is cancelled with INVALID_SHOP (which sends the "invalid shop" message via ErrorMessageSender) and the sign is destroyed — firing ShopDestroyedEvent (so it's de-registered from the market) then breakNaturally().
  • Both registered in ChestShop.registerEvents().

Notes

  • Detection reads the stored price line via PriceUtil.getExactBuyPrice/SellPrice and compares to PriceUtil.FREE (0), so B 0, S 0, B 0:S 5, bare 0, etc. are all caught after normalisation.
  • mvn -pl plugin -am compile passes. Listener logic is Bukkit-event-coupled (no unit layer in the plugin); worth a quick in-game smoke test: try to create a B 0 shop (should be rejected), and click an existing free shop (should break with the invalid-shop message).

🤖 Generated with Claude Code

Free shops — a buy or sell price of exactly 0 — are an abuse vector. Disallow
them and clean up any that already exist.

- PreShopCreation/FreePriceChecker (NORMAL, after PriceChecker normalises the
  price line): rejects creation with INVALID_PRICE if the buy or sell price is
  0. An unoffered side (NO_PRICE / -1) is unaffected, so non-zero buy-only or
  sell-only shops still work.
- PreTransaction/FreeShopBreaker (LOWEST): the first time anyone interacts with
  a pre-existing free shop, cancel the trade with INVALID_SHOP (sends the
  "invalid shop" message via ErrorMessageSender) and destroy the sign
  (ShopDestroyedEvent → de-register, then breakNaturally).
- Register both in ChestShop.registerEvents().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Coverage report

Overall Project 24.1%
File Coverage
ChestShop.java 0%

@ParadauxIO ParadauxIO merged commit a758151 into master May 30, 2026
2 checks passed
@ParadauxIO ParadauxIO deleted the feat/block-free-shops branch May 31, 2026 00:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant