
hShop
A very customisable and weirdly easy to use Shop plugin.
hShop 1.0.0 bugfix
release28 марта 2026 г.hShop Changelog
Bug Fixes
GUI & Inventory
Item theft via bottom inventory Clicking in the player's own inventory while a shop session was active was not fully blocked. Shift-clicking and drag events could move items in and out of the shop GUI. Both are now cancelled unconditionally when a session is active.
Drag events never cancelled
InventoryDragEvent was not handled at all, allowing players to drag items freely into shop GUI slots. A drag handler is now in place.
Category icon clicks did nothing
Main menu icon clicks were matched by comparing the item's display name string against a freshly colorized string — these could produce different §-code sequences and silently fail on every click. Icons are now registered in the session by slot at placement time, so clicks resolve by slot lookup instead.
Shop item clicks did nothing
Category page clicks rebuilt the available-slot index list and assumed item i was at available[i]. Items with an explicit slot: value broke this completely. Items are now registered in the session by their actual slot at placement time.
Ghost sessions after closing confirm menu Closing a confirm menu left the session alive permanently. The next chest, crafting table, or any inventory the player opened had all its clicks intercepted and cancelled. Sessions are now cleaned up correctly on close.
Confirm cancel lore passed wrong type
The cancel item's lore was passed as a bare String to a List<String> parameter, producing broken lore. Wrapped in Collections.singletonList().
Filler overwrote category and shop icons The decoration filler ran before shop items were placed, filling slots that items were then placed on top of. On certain decoration configs this caused icons to appear hidden. Decoration is now applied last and only fills slots that are genuinely empty.
Filler showing when enabled: false
Setting enabled: false under filler in a decoration file had no effect — empty slots were still filled. The enabled state is now properly stored and respected.
Memory leak on player disconnect
PlayerListener.onQuit was completely empty. Every disconnected player's session remained in the map permanently. Sessions are now removed on quit.
Transactions & Economy
hasInventorySpace false-positive gave items on full inventory
The check used containsAtLeast(item, 1) which returns true if the player has any of that item — even a full 64/64 stack. Purchases succeeded when the inventory was completely full. Now uses direct stack-size calculation against getStorageContents().
hshop.bypass.buy permission did nothing
The permission was defined in plugin.yml but was never checked in buyItem(). It is now checked before the buy-disabled gate.
Amount clamped to 0 proceeded as success
If a player had exactly hit their buy limit, getRemaining() returned 0, the amount was clamped to 0, and the transaction continued — withdrawing 0 currency and giving a 0-count item, returning SUCCESS. Now returns LIMIT_REACHED if amount is 0 after clamping.
hshop.bypass.sell checked but did nothing
The permission block was present but empty. It now correctly skips the sell-disabled check.
shopItem.getAmount() per-purchase quantity was never applied
Items configured with amount: 5 always gave 1 item per purchase. Now correctly gives purchaseAmount × shopItem.getAmount().
removeItems() missing updateInventory()
Without this call the client's inventory could desync, showing ghost items until re-log. Now called after every removal.
Transaction log directory never created
If transaction-log.file pointed to a subdirectory (e.g. logs/transactions.log), FileWriter threw an IOException on every transaction. mkdirs() is now called before writing.
Global sell multiplier compounded on every reload
The multiplier was applied to sell.price at load time and stored back into the ShopItem. Reloading three times with a 0.5 multiplier effectively applied 0.125×. The raw price is now stored and the multiplier is applied only at transaction time.
{sell_price} in item lore showed raw price instead of multiplied price
Players saw one price in the lore and received a different amount on sell. Lore now uses the effective sell price after applying the multiplier.
Commands
/hshop help double-printed every line
Called both get("help.player") and iterated getStringList("help.player"), printing everything twice.
/hshopa reload used wrong message key
Referenced admin.plugin-reloaded but the key is general.plugin-reloaded.
resetlimit / resetcooldown only worked for online players
Used Bukkit.getPlayer() which returns null for offline players. Now falls back to OfflinePlayer.
giveitem silently lost items on full inventory
addItem() leftovers were discarded. Excess items are now dropped at the player's feet.
SellHandCommand sent "no-permission" for a disabled feature
When sell-hand was disabled in config, the command sent a misleading no-permission message. Now sends sell.sellhand-disabled.
SellHandCommand only handled SUCCESS and a generic else
All other result codes (SHOP_DISABLED, NOT_ENOUGH_ITEMS, etc.) played a fail sound with no message. Each result code now has a proper message.
/hshopa setprice accepted negative prices
No validation was in place. Values below 0 are now rejected.
Sessions not cleared on /hshopa reload
After a reload, players with open menus held sessions pointing at old ShopCategory and ShopItem objects from before the reload. Sessions are now cleared on reload.
Data & Configuration
YAML key dot-corruption for cooldowns and limits
If a category or item ID contained a dot, YamlConfiguration treated it as a nested path separator when saving, silently corrupting all cooldown and limit data for those items. Dots in keys are now replaced before writing.
slot: AUTO in category items parsed as slot 0
getInt("slot", -1) returned 0 when the value was the string "AUTO". Every AUTO-slotted item landed at slot 0, overlapping decorations. Now reads the string value first and only parses as int if it is not "AUTO".
Category file listing order was non-deterministic
File[] from listFiles() has undefined order across operating systems, causing category load order to vary between restarts. Files are now sorted alphabetically before parsing.
Enchantments and flags not written back on save
saveCategory() never included enchantments or flags in its write-back loop. These keys silently disappeared from the yml after any admin command triggered a save.
New items added to yml on disk erased on next save
saveCategory() called yml.set("items", null) before writing back in-memory items. Any item added to the file manually while the server was running — without a reload — was permanently deleted the next time anything triggered a save. The save method now merges properly instead of wiping and rewriting.
Messages & Formatting
Placeholder values not colorized before injection
get(path, placeholders) colorized the message template first, then injected raw placeholder values after — so a display name like &fɢᴇᴀʀ landed in the already-colorized string and was never processed, showing as literal &fɢᴇᴀʀ in chat. Placeholder values are now colorized individually before being injected.
Hex color codes not working (&#ffffff)
Hex color codes in item names, lore, and titles were not rendering correctly. The color translation has been rewritten to manually build the correct §x§R§R§G§G§B§B sequences, fixing support for all 6-digit hex codes in both upper and lowercase.
send() suppressed valid messages with wrong blank-check
Checked for literal '' and "" strings which can never match a parsed Java value after colorize() runs. Replaced with isBlank().
sellall-success message had mismatched placeholder
The message used {total} but the code passed {items}. Both are now passed and the message updated.
Missing message keys
sell.sellhand-disabled and sell.sellall-disabled were referenced in code but absent from messages.yml. Both are now present.
New Features
Hex color code support (&#RRGGBB)
All text fields in messages.yml, categories/*.yml, and decorations/*.yml now support hex color codes in &#RRGGBB format. Can be freely mixed with standard & codes — e.g. &#B45AE8&lPurple Bold.
Pin category icons to specific slots (icon-slot)
Each category file now supports an icon-slot key to pin its icon to a fixed slot in the main menu. Set it to a slot number (0-indexed) or AUTO to fill in sort order as before. Out-of-bounds values, decoration-reserved slots, and duplicates fall back to AUTO with a console warning.
icon-slot: 13 # pin to centre of a 6-row menu
icon-slot: AUTO # default — fills left-to-right in sort order
Player placeholders in decoration items Custom items in decoration files now support dynamic per-player placeholders in their name and lore, resolved fresh for each player when the menu opens:
| Placeholder | Description |
|---|---|
{player} | Player's name |
{vault_balance} | Raw Vault balance |
{vault_formatted} | Vault-formatted balance |
{shards} | Raw hShards balance |
{shards_formatted} | Formatted hShards balance |
PlaceholderAPI support in decoration items
Any %placeholder% from PlaceholderAPI can now be used in decoration item names and lore. PlaceholderAPI is optional — the plugin functions normally without it.
purse.yml decoration
A new built-in decoration displaying a gold nugget with the player's Vault and hShards balances. Drop it in plugins/hShop/decorations/ and set default-decoration: purse in config.yml.
hShards balance now resolves correctly
The hShards hook cached an availability flag at startup that could be set incorrectly due to plugin load timing, causing balances to always show as 0.00. The hook now checks HShardsAPI.isAvailable() live on every call and wraps all API calls in error handling.
hShop 1.0.0
beta27 марта 2026 г.[1.0.0] - Initial Release
Features
- Basic shop system implementation
- Buy and sell item support
- Integration with Vault for economy handling
- PlaceholderAPI support for dynamic values
- Configurable shop setup
Compatibility
- Supports Paper, Spigot, Bukkit, and possibly Purpur.
- Requires Minecraft 1.21+
Dependencies
- Vault (for economy)
- PlaceholderAPI (optional)
Notes
- First public release of hShop
- More features and improvements coming soon
