All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Manual category default reseed command — added
/shopadmin reseed [mode]to restore missing bundled category defaults on demand without overwriting existing files. Omittingmodereseeds all bundled modes; providing a mode (e.g.prison,smp) reseeds only that mode.
- Bootstrap architecture cleanup — startup and shutdown orchestration now lives in the
bootstrappackage (EzShopsBootstrap), whileEzShopsPluginis reduced to a thin lifecycle entry point (onEnable/onDisabledelegation). - Runtime component access moved to registry — component/debug/reseed accessors are now provided by
EzShopsRegistry, removing lifecycle/state getters fromEzShopsPlugin.
- Default category file persistence across restarts — bundled category defaults are now seeded per mode directory (
shop/{mode}/categories/*.yml) and are no longer recreated automatically for existing mode directories when server owners intentionally delete them. - Mode support for default seeding — bundled shop resource discovery now works across available packaged modes (including future bundled modes), rather than relying on prison-only default category handling.
- Config persistence after reloads —
/shop reloadnow reloadsconfig.ymlfrom disk before refreshing pricing/features, and setup GUI toggles now reload config before saving. This prevents stale in-memory values from being written back over server-owner edits. - Shop category parser resilience — category parsing now isolates failures per category so one malformed entry can no longer break loading of the category set.
- Duplicate-material shop entries — when multiple items intentionally share the same material (for example splash potion variants), pricing keys are now resolved per-item to prevent collisions that could cause broken/empty category behavior.
- List-style
on-buy/on-sellhooks now execute — command hook parsing now accepts both list syntax (on-buy: - "cmd") and nested syntax (on-buy.commands) for compatibility with the documented format, preventing silent no-op purchases foritem-type: COMMANDentries.
- Player Shops documentation: a dedicated Player Shops guide covering the full setup flow (direct sign placement and
/playershopGUI), commands, permissions, configuration reference, purchase flow, double-chest support, and tips. - Player Shops: browse GUI: added a
/playershopscommand that opens a paginated, in-game inventory allowing players to browse all active player shops and purchase items without visiting each chest. - Player Shops: MySQL storage: added
MysqlPlayerShopRepositoryand support forplayer-shops.storage.type: mysql(configurablehost,port,database,username,password,table-prefix). The repository serialises item stacks as YAML and preserves deferred entries for worlds that are not loaded; the plugin falls back to the YAML backend if MySQL is unavailable at startup. - Repository factory & wiring:
PlayerShopComponentnow selects the configured storage backend (YAML or MySQL) at startup and registers the browse GUI and/playershopscommand when player shops are enabled. - API additions:
PlayerShopManagerexposeshasStock(PlayerShop)andformatPrice(double)(public) to support the browse GUI and other integrations. - Permissions & commands: added the
playershopscommand and theezshops.playershop.browsepermission (default: true).
- Build target baseline: Maven compiler settings now target Java 17 (
source/targetviajava.version), replacing the previous Java 21 compile target inpom.xml. - Paper API baseline for Java 17 builds: default
paper.versionchanged to1.20.6-R0.1-SNAPSHOTto align with the Java 17 compatibility target. - EzFramework dependency alignment: pinned and updated persistence stack dependencies in
pom.xml:com.github.EzFramework:jaloquent->1.3.3com.github.EzFramework:JavaQueryBuilder->1.2.1com.github.EzFramework:Jaker->1.0.7
- Incorrect
sign-formatkeys inmain-settings.md— the Player Shops configuration section documented non-existent keys (header,owner-line,item-line,stock-line,price-line,{stock}placeholder). It now documents the real keys (available-header,out-of-stock-header,owner-format,unknown-owner-name,item-format,price-format,out-of-stock-line) with the correct placeholders ({owner},{amount},{item},{price}).
Through time we've made the stock market more stable, by doing this the documentation got outdated and configuration options that existed before got phased out. This version there was focus on updating the documentation and adding back options that got phased out in a more stable way.
- Configurable stock price-engine parameters -
volatility-min,volatility-max,demand-multiplier,min-price, andupdate-intervalare now realconfig.ymloptions under thestock:section. The plugin reads them on startup and applies them to the price engine. All defaults match the previously hardcoded values so existing behaviour is preserved.
- Incorrect stock-market configuration documented -
docs/configuration/main-settings.mdanddocs/shops/pricing/stock-market.mdpreviously documented a non-existentstock-market:config block. Both pages now document the realstock:section (enabled,cooldown-millis,blocked,overrides,categories). Price-engine parameters (volatility-min,volatility-max,demand-multiplier,min-price,update-interval) are now implemented as real config options (see Unreleased → Added). /sellcommand missing from documentation - the Quick Sell GUI command (/sell) is now documented in the Commands reference with its behavior and permission node./shopadmincommand missing from documentation -/shopadmin [browse|market]is now documented under Admin Commands including both the player-shops and team-market views./teamshop marketsubcommand missing from documentation - the team P2P market subcommand is now documented in Commands, the TeamsAPI integration page, and the tab-completion list for/teamshop.- Missing permission nodes in documentation - the following nodes were present in
plugin.ymlbut absent from the Permissions reference; they are now documented:ezshops.shop.admin(open/shopadminGUI)ezshops.teamshop.market(access team P2P market)ezshops.pricing.admin.set,ezshops.pricing.admin.disable,ezshops.pricing.admin.list(granular pricing-admin nodes)
on-sellcommands not executing foritem-type: COMMANDitems —sell()no longer checks or removes physical items from the player's inventory when the item's delivery type isCOMMAND. Previously the transaction exited early with "insufficient items" because the player had no material to hand over, preventing sell commands from running at all.on-sell execute-asoverridden byon-buy execute-as—ShopPricingManagernow tracksexecute-asindependently for theon-buyandon-sellblocks. Previously a single shared flag meant that settingon-buy: execute-as: playerwould silently overrideon-sell: execute-as: console, causing sell commands to run as the player instead of the console.
- Code coverage reporting — JaCoCo is now configured in the Maven build (
jacoco-maven-plugin 0.8.12). Coverage reports (jacoco.xml) are generated on everymvn testrun and uploaded to Codecov by the CI workflow for both unit-test and feature-test jobs.
- Quick Sell GUI "Nothing to sell" after shift-click —
handleConfirmnow calls a newShopTransactionService.sellDirect()method that skips the player-inventory item count/removal steps. Previously, shift-clicking items into the GUI moved them out of the player's inventory, so the oldsell()path found zero items and reported nothing to sell. - Quick Sell GUI shows "Nothing to sell" when sell fails after shift-click —
handleConfirmnow distinguishes between a genuinely empty GUI and a GUI that has items but whosesellDirectcall failed (e.g. economy down, dynamic price driven to $0.00 by a previous sale, rotation expired). The actual failure reason is shown to the player instead of the misleading "No items to sell." message. Items that failed to sell remain in the GUI so the player can retry. - Quick Sell GUI rejects rotation items even when directly sellable —
sellDirectandisSellableboth applied a rotation-visibility check that belongs only in the main shop menu. The Quick Sell GUI is designed to accept any item with a configured sell price; rotation restrictions are now only enforced insell(), which is the path used when a player types/sellor/sellhand. - Legacy
shop.ymlitem keys not found when using lowercase material names —loadLegacyEntriesnow normalises every price key toMaterial.name()(e.g.BIRCH_LOG) before registering it in the price map. Previously, a config entry written asbirch_log:was stored under the lowercase key, sogetPrice(Material.BIRCH_LOG)could not find it, silently treating the item as unpriced.
- Stripped log variants in the wood category — all 9 stripped log types (
STRIPPED_OAK_LOG,STRIPPED_SPRUCE_LOG,STRIPPED_BIRCH_LOG,STRIPPED_JUNGLE_LOG,STRIPPED_ACACIA_LOG,STRIPPED_DARK_OAK_LOG,STRIPPED_MANGROVE_LOG,STRIPPED_PALE_OAK_LOG,STRIPPED_CHERRY_LOG) are now included in the defaultwood.ymlconfig so players can sell stripped logs with/sellhandand the Quick Sell GUI out of the box. - Wood (all-bark) block variants in the wood category — all 9 wood block types (
OAK_WOOD,SPRUCE_WOOD,BIRCH_WOOD,JUNGLE_WOOD,ACACIA_WOOD,DARK_OAK_WOOD,MANGROVE_WOOD,PALE_OAK_WOOD,CHERRY_WOOD) are now included. Previously, attempting to/sellhanda "Birch Wood" block (as opposed to a "Birch Log") would return "That item is not configured in the shop." - Plank variants in the building category — all 9 plank types (
OAK_PLANKS,SPRUCE_PLANKS,BIRCH_PLANKS,JUNGLE_PLANKS,ACACIA_PLANKS,DARK_OAK_PLANKS,MANGROVE_PLANKS,PALE_OAK_PLANKS,CHERRY_PLANKS) are now included in the defaultbuilding.ymlconfig.
- TeamTreasury transaction safety —
depositnow refunds the player's Vault balance if the YAML save fails, preventing money from being lost on a failed write.withdrawdebits the treasury before paying the player so a failed save aborts the operation without creating currency from nothing. - TeamStockManager negative-amount guard —
removeTeamStocknow returnsfalseimmediately whenamount <= 0, preventing invalid stock mutations.
- TeamsAPI optional integration —
NoClassDefFoundErrorno longer crashes plugin startup when TeamsAPI is absent from the classpath. The availability check is now wrapped in aNoClassDefFoundErrorcatch block so the integration degrades gracefully whether the JAR is missing entirely or the plugin is simply not loaded.
- Folia support — EzShops now runs on Folia servers. All scheduler calls are routed through a new
SchedulerAdapterthat transparently delegates toGlobalRegionScheduler/AsyncScheduleron Folia and toBukkitScheduleron Paper/Spigot/Bukkit. Thefolia-supported: trueflag has been added toplugin.yml.
- EzBoost engine improvement — reflective access to EzBoost's price-multiplier API is now cached after the first lookup.
Class.forName,getMethod, andgetPluginare no longer called on every transaction; instead, resolvedMethodreferences are reused for the lifetime of the server.
This version we focussed on adding Team Shops, a full team-based economy layer built on top of TeamsAPI. Teams get their own market, shared treasury, stock pool, and role-based pricing, all accessible through a new /teamshop command.
- TeamsAPI integration — EzShops now integrates with TeamsAPI as a soft dependency; all features degrade gracefully when TeamsAPI is absent.
- Role-based sell multipliers — MEMBER, ADMIN and OWNER each receive a configurable sell price bonus when selling to the shop (
teams-integration.sell-multiplierinconfig.yml). - Role-based buy discounts — MEMBER, ADMIN and OWNER each receive a configurable buy price reduction when purchasing from the shop (
teams-integration.buy-discountinconfig.yml). - Team treasury — a shared balance funded automatically by a configurable percentage of every sell transaction (
teams-integration.treasury-split). Members can deposit and withdraw funds through the treasury GUI. - Shared team stock — stock quantities are pooled per team; all members draw from and contribute to the same pool (
teams-integration.shared-stock). /teamshopcommand — opens the team shop dashboard showing team info, current multipliers and quick links./teamshop treasury— opens the team treasury GUI (deposit / withdraw; requiresezshops.teamshop.treasury.withdraw)./teamshop stocks— browse all items your team currently has in stock.
- Permissions:
ezshops.teamshop(default: true) — access the team shop dashboard.ezshops.teamshop.treasury.withdraw(default: true) — withdraw from the team treasury.ezshops.teamshop.admin(default: op) — administrative team stock commands.
- Automatic data cleanup — team stock and treasury data are deleted automatically when a team is disbanded via the
TeamDeleteEvent.
