ShopShelves Spigot — Changelog
===============================
Version 1.0.12
--------------
New Feature: Sale & Tax System
• Added /shops sale and /shops tax commands for applying server-wide or per-player price modifiers to admin shops.
• Global deals replace each other (only one global sale and one global tax active at a time).
• Player deals stack — multiple timed deals can coexist without losing earlier ones when a newer one expires.
• Resolution logic: highest sale wins, highest tax wins, they cancel each other out. A 25% sale and 20% tax results in a net 5% sale.
• Global deals take priority over personal deals when the global percentage is higher on that side.
• Added /shops deals command to view active global and personal deal percentages at a glance.
• Text displays on admin shops automatically update to reflect the active global deal price when a sale or tax is set or cleared.
• Player-owned shelf shops (PLAYERSHELF mode) are completely immune to deals — sales and taxes are an admin tool and do not affect player shops.
• Added player_deals_online config option: when enabled, personal deal timers only count down while the player is connected to the server. Global deals always use wall-clock time.
• Timed deals accept duration tokens: 30m (minutes), 6h (hours), 7d (days).
New Permission Nodes
• shopshelves.sale — allows using /shops sale.
• shopshelves.sale.<N> — allows applying a sale up to N% (e.g. shopshelves.sale.20).
• shopshelves.sale.# — allows applying a sale of any percentage.
• shopshelves.tax — allows using /shops tax.
• shopshelves.tax.<N> — allows applying a tax up to N%.
• shopshelves.tax.# — allows applying a tax of any percentage.
• shopshelves.deals — allows viewing active deals via /shops deals. Defaults to true (all players).
New: Deal Placeholders
The following placeholders are now available in messages.yml and display format strings:
• %sale% — net effective sale % after global+personal cancellation (0 if none).
• %tax% — net effective tax % after global+personal cancellation (0 if none).
• %sale_format% — always renders as "Sale X%" even when 0.
• %tax_format% — always renders as "Tax X%" even when 0.
• %if_sale% — renders "Sale X%" only when a sale is active, otherwise empty.
• %if_tax% — renders "Tax X%" only when a tax is active, otherwise empty.
• %global_deal% — shows the winning side for global deals only ("Sale X%" or "Tax X%" after they offset each other, or empty if equal/zero).
• %player_deal% — shows the winning side for the combined player result (global + personal). Whichever side is larger after cancellation wins.
Developer API
• Added price modifier API to ShopshelvesApi. Third-party plugins can now apply and remove per-player price multipliers for admin shops programmatically.
• ShopshelvesApi.setPlayerPriceModifier(uuid, multiplier) — applies a permanent modifier. 0.80 = 20% discount, 1.20 = 20% surcharge.
• ShopshelvesApi.setPlayerPriceModifier(uuid, multiplier, durationMs) — timed version.
• ShopshelvesApi.removePlayerPriceModifier(uuid) — removes any modifier set by the calling plugin.
• ShopshelvesApi.getEffectivePriceMultiplier(uuid) — returns the combined effective multiplier for a player (all sources: API + command + global).
• ShopshelvesApi.hasActiveModifier(uuid) — returns true if any deal is currently active for a player.
• API modifiers feed into the same stacking system as command-set deals and respect all existing PLAYERSHELF immunity rules.
• Added DealEntry.Source.API to distinguish API-set modifiers from command-set ones internally.
Persistence
• All deals (global and player) are persisted in the existing shopshelves.db SQLite file across server restarts. A new deals table is created automatically on first run — no migration steps required.
Developer information
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle.
maven { name = "Modrinth"; url = "https://api.modrinth.com/maven" }