PAR-288
[chestshop] Collapse the PreShopCreation + PreTransaction validation pipelines into services (Phase 3)
The last of the "Bukkit events as internal middleware" design: the shop-creation validation chain (PreShopCreationEvent → ~12 priority-ordered preshopcreation listeners coordinating through a mutable outcome/signLines bag) and the pre-transaction validation chain (PreTransactionEvent → pretransaction listeners). Collapse each into a direct service step — ShopService.create(...) returning a CreationOutcome, and a TransactionService pre-trade validation method — preserving the exact ordering, mutations, and partial-transaction maths.
Keep the genuine cross-plugin integration events that the validators fire: AccountQuery/AccountAccess (Treasury/Business firm resolution + access) and BuildPermissionEvent (WorldGuard/GriefPrevention terrain). Those stay; only the internal coordination event + its listener chain collapse.
Entrypoints (SignCreate for creation, PlayerInteract for transaction) call the service directly instead of building+firing the event. Staged: map both pipelines first, then collapse creation, then transaction, smoke-testing between. Completes the entrypoint→service→DAO migration (PAR-282 family).
Resources
- commita3181ec Subsume the shop-creation validation pipeline into ShopService (PAR-282/PAR-288)ParadauxIO/hibernia-economy
- commit05a870d Subsume the pre-transaction validation pipeline into TransactionService (PAR-282/PAR-288)ParadauxIO/hibernia-economy
- commit6f1fbeb Re-home the notification-cooldown cleanup to PlayerConnect (PAR-288)ParadauxIO/hibernia-economy
- commit57f770e Strip inert event-handler markers from collapsed listeners (PAR-288)ParadauxIO/hibernia-economy
- commitc2e957f Collapse info/reload events into InfoService (PAR-288)ParadauxIO/hibernia-economy
- commitf5619cc Collapse protection events into ProtectionService (PAR-288)ParadauxIO/hibernia-economy
- commite90548d Collapse item/sign resolution events into ItemService (PAR-288)ParadauxIO/hibernia-economy
- commitf540e91 Collapse ShopCreated/ShopDestroyed events into ShopService (PAR-288)ParadauxIO/hibernia-economy
- commitada7433 Collapse the TransactionEvent fan-out into TransactionService.process (PAR-288)ParadauxIO/hibernia-economy
- commit2e5b567 Replace AccountQuery/AccountAccess events with direct API resolution (PAR-288)ParadauxIO/hibernia-economy
- commit04b9f28 Collapse the pre-transaction validation pipeline into TransactionService.validate (PAR-288)ParadauxIO/hibernia-economy
- commit268a25a Collapse the shop-creation validation pipeline into ShopService.create (PAR-288)ParadauxIO/hibernia-economy
Comments
tesks · Jun 26, 2026, 10:13 PM
Part 1 done (commit 268a25a, pushed): shop-creation pipeline collapsed. PreShopCreationEvent is now a plain carrier; ShopService.create(player, sign, lines) runs the 12 former validators as ordered steps in their exact priority+registration order (the two ignoreCancelled steps — fee charge + NameChecker's HIGHEST pass — guarded on !isCancelled). SignCreate calls it directly; registerPreShopCreationEvents removed. Integration events (ItemParse/AccountQuery/AccountAccess/BuildPermission) still fire. Builds + tests green.
Remaining:
- Part 2: collapse the PreTransactionEvent pipeline (PlayerInteract entrypoint; LOWEST validators + the partial/non-partial alternative — PartialTransactionModule XOR AmountAndPriceChecker — + StockFittingChecker + PermissionChecker + ErrorMessageSender with owner notifications). The hot trade path — wants its own careful pass + smoke test.
- Cleanup: strip the now-inert @EventHandler/Listener markers from both validator sets (left in place for now; harmless since unregistered).
tesks · Jun 26, 2026, 10:21 PM
Part 2 done (commit 04b9f28, pushed): pre-transaction pipeline collapsed. PreTransactionEvent is now a plain carrier; TransactionService.validate(ctx) runs the former pretransaction validators in exact priority+registration order (the partial/non-partial alternative preserved; AmountAndPriceChecker's ignoreCancelled guarded). PlayerInteract calls it directly; registerPreTransactionEvents removed. Builds + tests green.
Both internal validation pipelines (PreShopCreation + PreTransaction) and the entire economy event bus are now plain service calls.
Remaining cleanup (cosmetic, not yet done): strip the now-inert @EventHandler/Listener markers from the ~22 former validator classes — they're unregistered and called directly, so harmless, but misleading. ~60 mechanical edits; deferred to keep this from sprawling.
"Zero events" status: the internal coordination/validation/economy events are gone. What remains as events is intentional — genuine cross-plugin integration points (AccountQuery/AccountAccess → Treasury/Business, BuildPermission → WorldGuard/GriefPrevention, ItemParse/ItemString → custom-item plugins), Bukkit platform events (SignChange/PlayerInteract/BlockBreak), and the post-event fan-outs (TransactionEvent, ShopCreated/ShopDestroyed → loggers/market/messages) which are observer-style "it happened" notifications — a possible future phase if you want those collapsed too.
tesks · Jun 26, 2026, 11:13 PM
Increment A done (commit 2e5b567): eliminated AccountQueryEvent + AccountAccessEvent. Account resolution/access now run as direct API calls through AccountService.resolveAccount/canAccess → EconomyService (which gained the BusinessApi handle + a 4-arg bind). TreasuryListener no longer holds account state — it only advertises the provider and migrates legacy business signs. Deleted AccountListener and both event classes.
Remaining increments toward zero custom events: B TransactionEvent fan-out, C ShopCreated/ShopDestroyed, D item-parse/material/sign-validation (custom-item plugin integration → API), E protection (BuildPermission/ProtectionCheck/ProtectBlock → WorldGuard/GriefPrevention via API), F ShopInfo/ItemInfo/ChestShopReload, plus stripping the now-inert @EventHandler/implements Listener markers off the collapsed validator classes.
tesks · Jun 26, 2026, 11:25 PM
Increment B done (commit ada7433): TransactionEvent is now a plain carrier; its 8-handler fan-out runs as ordered calls in TransactionService.process (faithful priority + ignoreCancelled order). Sign migration moved to EconomyService.migrateLegacyBusinessSign; TreasuryListener is now handler-free. Deleted TransactionExecutor; de-registered EmptyShopDeleter/TransactionLogger/TransactionMessageSender/MetricsModule and MarketListener.onTransaction.
Also fixed two silently-dropped handlers from the earlier carrier collapses (they were registered but inert, logging a severe at startup): RestrictedSign.onPreTransaction (restricted-shop trade gate) → validate(); StockCounterModule.onPreShopCreation (counter seeding) → create().
Next: C ShopCreatedEvent/ShopDestroyedEvent.
tesks · Jun 26, 2026, 11:31 PM
Increment C done (commit f540e91): ShopCreatedEvent/ShopDestroyedEvent collapsed into ShopService.onCreated/onDestroyed (faithful priority order). Firing sites (SignCreate, SignBreak.sendShopDestroyedEvent, EmptyShopDeleter) call the service directly. Deleted ShopRefundListener; de-registered the post-creation/removal loggers + message sender; MarketListener shop handlers now static (still registered for onInventoryClose).
Now mapping D (ItemParseEvent/ItemStringQueryEvent/MaterialParseEvent/SignValidationEvent) — these may be genuine external custom-item extension points (ItemBridge/Nexo/etc.), so checking whether they collapse to internal calls or must become direct third-party API calls before touching them.
tesks · Jun 26, 2026, 11:45 PM
Increment D done (commit e90548d): ItemParseEvent/ItemStringQueryEvent/MaterialParseEvent/SignValidationEvent collapsed into a new ItemService (ChestShop.items()) with faithful priority ordering (parse: ItemBridge→alias→vanilla; stringify: ItemBridge→vanilla→alias). SignParseListener/ItemStringListener de-registered; ItemAliasModule is now a Guice @Singleton (same instance registered only for its reload handler); ItemBridge's resolvers are static and only invoked when the plugin is hooked (Dependencies calls ItemService.enableItemBridge()), keeping com.jojodmo.itembridge off the path when absent. ~15 firing sites rewired.
Remaining: E (BuildPermissionEvent/ProtectionCheckEvent/ProtectBlockEvent → WorldGuard/GriefPrevention via direct API), F (ShopInfoEvent/ItemInfoEvent/ChestShopReloadEvent), plus stripping inert @EventHandler markers off the unregistered validator classes.
tesks · Jun 26, 2026, 11:56 PM
Increment E done (commit f5619cc): protection events collapsed into ProtectionService (ChestShop.protection()). canAccess/canView run vanilla shop-member check then WorldGuard (deny-if-either); canBuild runs WorldGuard then GriefPrevention with the ignoreCancelled skip preserved. WG/GP integration classes are no longer Listeners — Dependencies wires them as method references only when the plugin is hooked + flag on, so com.sk89q/me.ryanhamshire stay off the path when absent. ProtectBlockEvent deleted (no handlers since PAR-285 removed LWC/Lockette; Security.protect returns false, had no callers).
Last group: F — ShopInfoEvent/ItemInfoEvent/ChestShopReloadEvent (ItemInfoEvent is the intricate one: ~15 contributor handlers + a nested crossbow-projectile sub-query). Then the inert-marker cleanup.
tesks · Jun 27, 2026, 12:05 AM
Increment F done (commit c2e957f): ShopInfoEvent/ItemInfoEvent/ChestShopReloadEvent collapsed into InfoService (ChestShop.info()). collectItemInfo runs the basic + extended /iteminfo contributors in firing order (HIGH map/potion override the basic by key); /chestshop reload calls loadConfig() + ItemService.reloadAliases() directly. The info listeners, ItemAliasModule and the vanilla plugins/ChestShop protection class are de-registered.
Milestone: zero internal custom events. All 12 ChestShop custom events are now plain carriers or deleted; nothing is dispatched through Bukkit's event bus internally. Treasury/Business + WorldGuard/GriefPrevention/ItemBridge are reached via direct API links. Only genuine platform-event listeners remain. Six revertable commits: 2e5b567, ada7433, f540e91, e90548d, f5619cc, c2e957f.
Final step in progress: stripping the now-inert @EventHandler/implements Listener markers off the ~26 unregistered validator/info classes (cosmetic; they cause no runtime effect since unregistered classes are never reflected).
Activity
- ParadauxIO linked a commit — Commit a3181ec — Subsume the shop-creation validation pipeline into ShopService (PAR-282/PAR-288)
- ParadauxIO linked a commit — Commit 05a870d — Subsume the pre-transaction validation pipeline into TransactionService (PAR-282/PAR-288)
- ParadauxIO linked a commit — Commit 6f1fbeb — Re-home the notification-cooldown cleanup to PlayerConnect (PAR-288)
- ParadauxIO linked a commit — Commit 57f770e — Strip inert event-handler markers from collapsed listeners (PAR-288)
- ParadauxIO linked a commit — Commit c2e957f — Collapse info/reload events into InfoService (PAR-288)
- ParadauxIO linked a commit — Commit f5619cc — Collapse protection events into ProtectionService (PAR-288)
- ParadauxIO linked a commit — Commit e90548d — Collapse item/sign resolution events into ItemService (PAR-288)
- ParadauxIO linked a commit — Commit f540e91 — Collapse ShopCreated/ShopDestroyed events into ShopService (PAR-288)
- ParadauxIO linked a commit — Commit ada7433 — Collapse the TransactionEvent fan-out into TransactionService.process (PAR-288)
- ParadauxIO linked a commit — Commit 2e5b567 — Replace AccountQuery/AccountAccess events with direct API resolution (PAR-288)
- tesks changed status to Status → Pending Release
- tesks commented
- tesks commented
- tesks commented
- tesks commented
- tesks commented
- tesks commented
- tesks commented
- ParadauxIO linked a commit — Commit 04b9f28 — Collapse the pre-transaction validation pipeline into TransactionService.validate (PAR-288)
- tesks commented
- ParadauxIO linked a commit — Commit 268a25a — Collapse the shop-creation validation pipeline into ShopService.create (PAR-288)
- tesks created the issue