Nexal Shops
Physical shops for Minecraft servers. Players turn a block into a shop that sells items to other players, buys items from them, or both, with a floating display and a native hologram above it. Admins create admin shops with infinite stock. Players browse and trade with every shop from a menu, owners restock and manage their shops from anywhere, and trusted players can restock for them. Server owners manage settings, shops and data from an in-game admin GUI.
Features
- Player Shops - Look at a block, run
/shops createand set the item, prices, display and revenue mode in a wizard - Admin Shops - Infinite stock, no tax, nothing paid to anyone; for server-run economies
- Buy and Sell - Each shop can sell to players, buy from players, or both; every trade matches the item exactly (
isSimilar: enchantments, names, lore, container contents) - Five Display Styles - Glass case (floating item display), floating item, display entity (1.19.4+), armor stand, or hologram only; switch and rotate per shop
- Native Holograms - Works out of the box through Utilizer's native hologram API (TextDisplay/ArmorStand), no hologram plugin required; lines are configurable
- Revenue Modes - Instant deposit to the owner's balance, or collect it later from the shop
- Sales Tax - A configurable default rate for new shops, changeable per shop by admins, or turned off entirely
- Management Screen - Prices, stock deposit and withdrawal, revenue, deposit mode, display, teleport, transaction history and delete, from
/shops manageor by right clicking your shop - Transaction History - Who bought and sold what, when, at what price and tax, per shop; kept for a configurable number of days
- Trusted Users -
/shops trust \<player>lets another player restock a shop; prices, revenue, withdrawals and deleting stay with the owner - Browse Menu - Every shop on the server, sortable by recency, price or popularity (most trades), filterable by category (blocks, tools and weapons, armor, food, other) and searchable by item or owner name
- Remote Trading - Buy and sell from the browse menu, or turn it off so players must visit the shop
- Notifications - Sale alerts, a low stock warning when stock drops to the threshold, and revenue milestones; owners who are offline get them on their next join
- Price Suggestions -
/shops priceshows the average, lowest and highest buy price of shops selling the held item type - Teleport to Shops - Owners teleport to their shops with a configurable cost and cooldown
- Protection - Shop blocks are protected from breaking, explosions and pistons, and display entities from damage and pickup; shops respect claim and region plugins on creation. With break protection off, a broken shop block removes the shop and returns its stock to the owner
- Fair Removal - When an admin removes a player's shop, its stock and uncollected revenue go back to the owner, kept for their next join if they are offline
- Admin GUI -
/shops adminopens a hub with settings, every shop, admin shop creation, statistics, reload, export and import - PlaceholderAPI - 10 placeholders for scoreboards and holograms
- Dual Storage - JSON (
data.json) or MySQL/MariaDB, written in the background, with export and import to move between them
Technologies
- Paper API 1.20.1+ - Minecraft server API (Spigot compatible)
- Utilizer - Configuration, messages, GUIs, holograms, tasks
- ACF - Command framework
- nexal-core - JSON and SQL persistence (MariaDB/MySQL), help menus
- Vault - Economy for trades, revenue and teleport costs
- PlaceholderAPI - Placeholder integration (optional)
Commands
Aliases: /shop, /s
Player Commands
| Command | Description | Permission |
|---|---|---|
/shops | Open the shops menu (the console gets the help menu) | nexalshops.use |
/shops help [page] | Show the help menu | nexalshops.use |
/shops create | Create a shop on the block you look at (opens the creation wizard) | nexalshops.create |
/shops browse | Browse, search and trade with every shop | nexalshops.use |
/shops manage | Manage your shops | nexalshops.use |
/shops teleport [id] | Teleport to one of your shops (alias tp); without an id and with several shops, opens your shop list to pick one | nexalshops.use |
/shops trust \<player> | Let a player restock the shop you look at | nexalshops.use |
/shops untrust \<player> | Remove a trusted player from the shop you look at | nexalshops.use |
/shops price | Price suggestions for the item in your hand | nexalshops.use |
Right click a shop block to open it: its owner gets the management screen, a trusted player the restock screen, and everyone else the buy/sell screen. In the buy/sell screen, left click buys 1, shift left click buys 64 (or what is left), right click sells 1 and shift right click sells every matching item in your inventory. Worn armor and the offhand are never sold.
Admin Commands
| Command | Description | Permission |
|---|---|---|
/shops admin | Open the admin GUI (the console gets the admin commands) | nexalshops.admin |
/shops admin help [page] | List the admin commands | nexalshops.admin |
/shops admin create | Create an admin shop on the block you look at, selling the item in your hand | nexalshops.admin |
/shops admin delete \<id> | Delete any shop by the start of its ID; stock and revenue go back to its owner | nexalshops.admin |
/shops admin list [player] | List every shop, or one player's (online or offline) | nexalshops.admin |
/shops admin export | Export all data to export/ | nexalshops.admin |
/shops admin import | Import the files in export/ into the current storage | nexalshops.admin |
/shops admin reload | Reload the configuration and shop displays | nexalshops.admin |
The admin GUI has the same actions plus a Configuration screen for the most used settings
(shop limit, teleport, tax, browse menu, remote trading, notifications, holograms, price
suggestions, price abbreviation, block protection), saved straight to config.yml. Admins also get
a Manage button on every shop's buy/sell screen, and a Tax Rate button on every shop's
management screen.
Permissions
| Permission | Description | Default |
|---|---|---|
nexalshops.use | Basic shop usage | true |
nexalshops.create | Create shops (command and menu) | true |
nexalshops.delete | Delete your own shops, from the management screen or by breaking the block | true |
nexalshops.admin | /shops admin, admin shops, managing and deleting any shop | op |
nexalshops.teleport.bypass | Bypass the teleport cooldown (configurable as teleport.bypass-permission) | op |
nexalshops.limit.unlimited | Unlimited shops | op |
nexalshops.limit.\<number> | Shop limit, the highest one wins (e.g. nexalshops.limit.10) | false |
Placeholders
Requires PlaceholderAPI.
| Placeholder | Description |
|---|---|
%nexalshops_shop_count% | Shops the player owns |
%nexalshops_shop_limit% | Maximum shops allowed (online players) |
%nexalshops_shops_remaining% | Remaining shop slots (online players) |
%nexalshops_total_revenue% | Money earned from customers buying at the player's shops, after tax |
%nexalshops_total_spent% | Money the player spent buying at shops |
%nexalshops_total_transactions% | Trades the player took part in, as customer or owner |
%nexalshops_shops_created% | Shops the player ever created |
%nexalshops_collected_revenue% | Revenue waiting to be collected in the player's shops |
%nexalshops_total_stock% | Items in stock across the player's shops |
%nexalshops_total_shops% | Shops on the server (no player needed) |
Configuration
config.yml
# Storage type: "json" or "sql"
storage:
type: json
auto-save-interval: 300 # Seconds between flushes to disk (changes are also written in the background as they happen; 0 to disable)
transaction-retention-days: 30 # Transactions older than this are deleted (0, or leaving the setting out, keeps them forever)
sql:
host: localhost
port: 3306
database: minecraft
username: root
password: ""
creation:
# Where the creation wizard starts; the player can change both before confirming
default-display-type: FLOATING_ITEM # FLOATING_ITEM, FLOATING, DISPLAY_ENTITY, ARMOR_STAND, HOLOGRAM_ONLY
default-instant-deposit: true
max-price: 1000000000 # Highest buy or sell price a player can enter
# Permission: nexalshops.limit.X - player can have X shops
# Permission: nexalshops.limit.unlimited - no limit
shop-limits:
default: 5
unlimited-permission: "nexalshops.limit.unlimited"
tax:
enabled: true # false: no tax on any sale
default-rate: 5.0 # Percentage taken from sales; new shops start with it, admins can change it per shop
display:
# When true, large prices are abbreviated (e.g. $1.5M instead of $1,500,000)
abbreviate-prices: true
hologram:
enabled: true # Show a text hologram above every shop
admin-shop-name: "<gradient:#FF5252:#FF7070>\<bold>Admin Shop\</bold>\</gradient>"
# Placeholders: %owner%, %item_name%, %buy_price%, %sell_price%, %stock%
# Lines containing %stock% are hidden for admin shops.
# Lines containing %buy_price% or %sell_price% are hidden when that price is disabled.
lines:
- "<gradient:#FFC107:#FFCD38>\<bold>%owner%'s Shop\</bold>\</gradient>"
- "\<white>%item_name%\</white>"
- "<gradient:#2ECC71:#52D68A>Buy: $%buy_price%\</gradient>"
- "<gradient:#FFC107:#FFCD38>Sell: $%sell_price%\</gradient>"
- "<gradient:#AAAAAA:#BBBBBB>Stock:\</gradient> \<white>%stock%\</white>"
y-offset: 2.0 # Height above shop block
floating-item:
y-offset: 1.0
# Glass case: armor stand with a glass head and the item floating inside
floating-item-display:
glass-type: GLASS # GLASS, TINTED_GLASS, WHITE_STAINED_GLASS, etc.
y-offset: -0.3
item-y-offset: 1.0
armor-stand:
y-offset:
helmet: -0.25
chestplate: 0.25
leggings: 0.75
boots: 1.25
display-entity: # 1.19.4+
scale: 0.8
y-offset: 1.5
browse:
enabled: true # Set to false to disable the /shops browse GUI
remote-purchase-enabled: true # Allow buying and selling from the browse GUI; when false, players must visit the shop
items-per-page: 45
default-sort: "RECENT" # RECENT, PRICE_ASC, PRICE_DESC, POPULAR
teleport:
enabled: true
cost: 100.0 # Vault cost to teleport (0 for free)
cooldown: 60 # Seconds between teleports
bypass-permission: "nexalshops.teleport.bypass"
notifications:
sale-notification: true
low-stock-threshold: 10 # Warn the owner once when a sale takes the stock to this or lower
revenue-milestones: # Notify an owner when their total revenue passes these amounts
- 1000
- 5000
- 10000
- 50000
- 100000
offline-notifications: true # Queue notifications for offline players
max-pending-notifications: 50 # Maximum pending notifications per player
protection:
prevent-break: true # Only the owner (with nexalshops.delete) and admins can break a shop block; when false anyone can, and the shop is removed with its stock returned to the owner
prevent-explosions: true # Explosions do not destroy shop blocks
prevent-pistons: true # Pistons cannot move shop blocks
prevent-hopper-extraction: true # Reserved for linked chest storage; has no effect yet
price-suggestions:
enabled: true
cache-duration: 300 # Seconds to cache price data
min-samples: 3 # Minimum shops needed for suggestion
messages.yml
Every player-facing message is in messages.yml: chat messages, chat input prompts and the
offline notifications, with MiniMessage colours and gradients, sounds and titles. The colour
reference at the top of the file lists the gradients for find-and-replace. Messages added in an
update are used from the plugin's defaults until you add them to your file.
Database Schema
With storage.type: json everything is in data.json, one collection per table below. With
sql, the plugin creates these tables (one connection pool for all of them):
shops_shops
| Column | Type | Key | Description |
|---|---|---|---|
id | VARCHAR(36) | PK | Shop ID |
ownerUUID | VARCHAR(36) | Owner (the creator, for admin shops) | |
ownerName | VARCHAR(64) | Owner name when the shop was created | |
serializedItem | TEXT | The item sold or bought (Base64) | |
world | VARCHAR(64) | World name | |
x, y, z | INT | Shop block position | |
buyPrice | DOUBLE | Price customers pay per item, -1 when disabled | |
sellPrice | DOUBLE | Price the shop pays per item, -1 when disabled | |
stock | INT | Items in stock | |
collectedRevenue | DOUBLE | Revenue waiting to be collected | |
instantDeposit | BOOLEAN | Revenue paid instantly (true) or collected in the shop (false) | |
displayType | VARCHAR(16) | Display style | |
rotation | FLOAT | Display rotation in degrees | |
storageType | VARCHAR(16) | Always VIRTUAL (reserved) | |
linkedChestLocation | VARCHAR(255) | Unused (reserved) | |
adminShop | BOOLEAN | Admin shop with infinite stock | |
taxRate | DOUBLE | Tax percentage on sales | |
createdAt | BIGINT | Creation timestamp | |
lastTransaction | BIGINT | Last trade timestamp | |
trustedUsersJson | TEXT | Trusted player UUIDs (JSON) |
shops_transactions
| Column | Type | Key | Description |
|---|---|---|---|
id | VARCHAR(36) | PK | Transaction ID |
shopId | VARCHAR(36) | → shops_shops.id | Shop traded with |
shopOwnerUUID | VARCHAR(36) | Shop owner | |
customerUUID | VARCHAR(36) | Customer | |
customerName | VARCHAR(64) | Customer name | |
type | VARCHAR(16) | BUY (customer bought) or SELL (customer sold) | |
itemName | VARCHAR(255) | Item name | |
quantity | INT | Items traded | |
pricePerItem | DOUBLE | Price per item | |
totalPrice | DOUBLE | Total price | |
taxAmount | DOUBLE | Tax taken | |
timestamp | BIGINT | When it happened |
shops_players
| Column | Type | Key | Description |
|---|---|---|---|
id | VARCHAR(36) | PK | Player UUID |
lastKnownName | VARCHAR(64) | Last known name | |
notificationsEnabled | BOOLEAN | Whether the player gets shop notifications | |
pendingNotificationsJson | TEXT | Notifications waiting for the next join (JSON) | |
totalShopsCreated | INT | Shops ever created | |
totalRevenue | DOUBLE | Money earned from customers, after tax | |
totalSpent | DOUBLE | Money spent at shops | |
totalTransactions | INT | Trades taken part in | |
lastTeleportTime | BIGINT | Last shop teleport, for the cooldown |
shops_claims
| Column | Type | Key | Description |
|---|---|---|---|
id | VARCHAR(36) | PK | Claim ID |
ownerId | VARCHAR(36) | Player the items are owed to | |
serializedItem | TEXT | The item (Base64) | |
amount | INT | How many | |
createdAt | BIGINT | When the shop was removed |
Key Legend: PK = Primary Key, → = refers to
Installation
- Install Vault and an economy plugin (EssentialsX, CMI, ...)
- Download the plugin JAR and place it in your
plugins/folder - Start or restart the server
- Configure
config.yml, or use/shops admin→ Configuration in game - Reload with
/shops admin reload
To move from JSON to SQL: /shops admin export, set storage.type: sql and the connection
details, restart, then /shops admin import.