Configuration
Four files, all merged on update:
| File | Holds |
|---|---|
config.yml | the shop item, the hologram, limits, currencies, the database, integrations |
lang/messages_en.yml | every line the plugin sends, plus the hologram text |
guis/buyer.yml | the layout of the menu everyone but the owner sees |
guis/owner.yml | the layout of the owner's management menu |
The shop item
shop-item:
material: ENCHANTING_TABLE
display-name: "&#FFD700&lDisplay Shop"
lore:
- "&7Place this block to create"
- "&7a player shop with a floating"
- "&7display."
glow: true
custom-model-data: 0A shop is identified by the tag the item carries, never by its material, so changing material
later leaves every shop already in the world working.
A material affected by gravity is refused at startup and falls back to ENCHANTING_TABLE. A block
that falls out of its own coordinates leaves a shop nobody can reach.
Three more families are accepted but are a bad idea, and the plugin cannot tell them apart to warn you: blocks that need support (torch, carpet, sapling, banner), blocks made of two halves (door, bed, tall flower), and blocks that melt or decay (ice, coral, leaves). Pick a plain solid block.
Shop defaults and block repair
shop:
defaults:
price: 0
mode: SELL
start-paused: true
restore-missing-blocks: truemode is from the SHOP's point of view: SELL means the shop sells to players, BUY means it buys
from them. A fresh shop starts paused so nobody trades with it before its owner has set the item,
the price and the currency.
The three defaults are read once, when a block is placed; changing them never touches a shop that
already exists. restore-missing-blocks is read live and applies to every shop.
restore-missing-blocks re-places the block of a shop whose coordinates are empty - broken while
the plugin was not running, or removed by something that fires no event, such as a world edit or
another plugin calling setType. Before it existed, that left a "ghost": the shop alive in every
index and still counting against its owner's limit, its hologram spinning over air, and recovery a
matter of putting a block back at coordinates nobody knew. The pass runs at startup for chunks that
are already loaded, and then per shop as each chunk loads.
Only air, water or lava counts as missing. A standing block of any other material is left exactly
where it is, because a material that does not match shop-item.material means a reconfigured
server, not a missing block. What gets placed is the CURRENT shop-item.material - what a shop was
originally placed as is not recorded anywhere - and nothing is placed into a player.
Currencies
Each entry is one currency, and the order they are declared in is the order the owner menu cycles through. A currency is backed either by commands or by EdTools.
The file ships one entry of each shape and no more. They are examples, not a currency list to keep: copy the shape you need as many times as your server has currencies and delete the one you do not. The section is marked extensible, so an entry you remove stays removed.
currencies:
okicoins:
display-name: "&#FF9B00okicoins"
give-command: "eco give {player} {amount}"
take-command: "eco take {player} {amount}"
balance-placeholder: "%vault_eco_balance%"
gems:
display-name: "&dGems"
edtoolapi: true
currency-id: gemsA command-backed currency missing give-command, take-command or balance-placeholder, or with a
template that has no {player} or no {amount}, is SKIPPED at startup with a SEVERE naming the
missing piece. That is deliberate: a currency that is skipped leaves its shops visibly
unconfigured, which you can fix, while one that registers half-configured looks fine and moves no
money.
An & written directly before a placeholder colors the name with whatever color code that
placeholder returns, which is how "&%itsmyconfig_dcolor%NAME" works.
Deleting a currency moves its shops, and keeps their prices. A currency you remove from
currencies: no longer strands the shops that traded in it: at the next start, and at the next
/dshop reload, they are moved to the first currency in the file, and every move is logged at INFO
naming the shop, its owner and the currency it left.
The NUMBER is not converted, because nothing in the file says what one currency is worth in another. A shop priced at 100 gems becomes a shop priced at 100 coins. Check what deleting a currency is about to do to your economy before you delete it.
A currency that is still declared but was SKIPPED at startup - EdTools down, a broken command template - is left alone, and its shops wait. Only a currency you actually removed from the file migrates. If nothing is left to move shops TO, the sweep does nothing and says so with a WARNING.
Limits
limits:
max-shops-per-player: 100
max-shops-permission-prefix: "sndisplayshops.limit"
external-interaction-cooldown-seconds: 5
max-pickup-stacks: 256max-shops-per-player: -1 is unlimited, 0 forbids creation. This is the number for a player
holding none of the permission nodes below.
max-shops-permission-prefix is the prefix of the per-rank override node - see
Permissions for the full node shape and how
several matching nodes resolve. It REPLACES max-shops-per-player for that player rather than
adding to it. Leave it blank to disable the permission override entirely, so every player is
governed by max-shops-per-player alone.
max-pickup-stacks bounds how much one pickup may move. Picking a shop up hands its whole stock
back at once, and stock is unbounded, so a shop holding ten million items would be a hundred and
fifty thousand ground entities in a single tick.
There is no value that switches max-pickup-stacks off. Below 1 is read as 256, because "no limit"
here means "one click can hang the server". Raise the number instead if you mean it. Over the limit
the pickup button is refused and says so; nothing is ever destroyed to make a shop fit.
Hologram
hologram: in config.yml holds the geometry - the item scale, the two vertical offsets, the
rotation timing and the bob. The TEXT lives in lang/messages_en.yml under hologram.text,
because it is language, not layout.
hologram:
item-scale: 1.2
item-y-offset: 1.3
text-y-offset: 3.0
rotation-interval-ticks: 10
rotation-period-ticks: 200
rotation-interpolation-extra-ticks: 2
bounce-amplitude: 0.1
bounce-period-ticks: 80The floating item spins and bobs, the way a dropped item does on the ground. bounce-amplitude is
how far it rises and falls around item-y-offset, in blocks; 0 leaves it hanging still.
item-y-offset stays the MIDDLE of the bob rather than its floor, so raising the amplitude swings
the item further around where it already hangs instead of pushing it up into the text.
The bob is free. It rides on the same update the spin already sends, so it does not scale with the
number of loaded shops - rotation-interval-ticks remains the plugin's single biggest CPU knob.
For the smoothest result keep bounce-period-ticks a multiple of four times
rotation-interval-ticks; the defaults are exactly eight pushes per bob.
Rotation and bounce values are clamped to a sane range at startup and a substituted value is logged. The hologram lines resolve their placeholders against the shop's OWNER, not against whoever is looking.
Database
database:
type: sqlite
pool-size: 1SQLite needs no setup. For MySQL, fill in the host, port, database, username and password.
pool-size ships at 1 and should stay there. A shop's stock is written as a running total, so two
workers can land the same row's updates out of order and the losing write is the one that survives a
restart - sold stock reappears. The plugin logs a SEVERE at startup if it finds MySQL configured
above 1.
Public developer API
api-events:
enabled: trueThe master switch of the events other plugins listen for - see the developer API. With it
false nothing is dispatched at all, and every cancellable event answers "not cancelled", so no
other plugin can stop a shop menu from opening.
That is what makes it a diagnostic rather than a performance knob: if shops have stopped responding to right-clicks and you want to know whether another plugin is the reason, turn this off and click one. Menus open again means yes.
Only the event half is gated. The read half - the facade other plugins query for a shop and its stock, and the sellwands built on it - keeps working either way, so turning this off never stops a sellwand from draining a shop.
Island integrations
integrations:
superiorskyblock:
delete-shops-on-island-disband: true
delete-shops-on-membership-loss: true
deny-placement-on-foreign-islands: trueThe plugin detects SuperiorSkyblock by its API class, so the SnSuperiorSkyblock fork and upstream
both work. Every toggle is read live, so /dshop reload switches it without a restart.
delete-shops-on-island-disband removes every shop inside an island when that island is disbanded,
whoever owns it. delete-shops-on-membership-loss removes a member's shops on an island when they
leave it, are kicked from it or are banned from it, and clears the blocks they stood on. Both act
only once the island plugin has actually made the change: a disband or a kick that another plugin
cancels removes nothing.
Removing a shop this way DESTROYS its stock. Everything the shop held is deleted with it: not dropped, not returned, not logged, and the owner is not told. For a disband that is defensible, since the island is being wiped anyway. For membership loss the island survives, so an ex-member loses stock outright. Both are switches for exactly that reason.
deny-placement-on-foreign-islands refuses a shop placed on an island the placer is not a member
of. The island's owner and its members may place; visitors and coops may not, whatever building
rights the island grants them. Blocks outside every island, and the spawn island, are never
refused. The player sees messages.shop-place-foreign-island and keeps the item.
Membership is the test, not the island's build privilege, on purpose. A shop placed under a coop or visitor grant would stand on an island where its owner never loses membership, so neither delete toggle above could ever remove it. If SuperiorSkyblock cannot answer, the placement is allowed and a warning names the cause: a broken API must not stop every shop placement on the server.
Trade and stock log
trade-log:
enabled: true
flush-seconds: 10
max-rows-per-event: 32
query:
default-days: 1
max-days: 30
max-results: 1000
max-scanned-lines: 500000
page-size: 8
cache-seconds: 60One line per stock movement, appended to plugins/SnDisplayShops/logs/<date>.log, a new file per
day, the way the server writes its own logs. A refused or aborted trade writes nothing.
Everything about reading it back is on its own page: Trade log.
flush-seconds is how long lines wait in memory before being written, and it is clamped to 1-300.
Lines are written off the main thread; the server never waits on the disk to finish a trade.
max-rows-per-event bounds a PICKUP or a DESTROY, which cover a whole shop. A shop can hold
any number of different items, and one island disband removes every shop on the island in a single
tick - without a cap, one event could fill the line buffer and stop the trades that explain it from
being recorded at all. Anything past the cap is folded into one extra line carrying how many
variants it stands for and their total, so the numbers stay complete however low you set it.
The query: block bounds a single /dshop logs command and affects nothing that gets written. It
is re-read per query, so an edit applies without a reload.
Old files are never deleted or compressed. Prune the folder yourself if the server is busy enough for it to matter.
An owner the server has not named yet can appear as owner=- on the first line after a restart -
resolving an offline player's name reads from disk, and that is not done during a click. The
owner-uuid beside it is always correct, and the name is there from the next movement onward.
The deposit-all button
Added in 2.7.0, and it does not appear by itself on a server that ran an earlier version.
The update merges the button's definition into your guis/owner.yml under templates: as
deposit:, but it never rewrites a layout: you already have - the updater adds keys you are
missing and leaves every value you already set exactly as you wrote it. Your layout is such a
value, so the button exists in the file and is placed nowhere.
To turn it on, put a + on any free cell and run /dshop reload. The shipped default puts it
immediately left of the withdraw button:
layout:
- "fffffffff"
- "ffffdffff"
- "ffcfmfpff"
- "ffffeffff"
- "sssssssss"
- "<f+wkfif>"Count your own rows before copying that line. The slot the + lands on has to exist in your
menu - a five-row menu has no slot 47.
Leaving the + out is a legal choice and nothing warns about it, the same way the withdraw
button is disabled by removing its w. But on a server with Bedrock or Geyser players, leaving
it out means those players cannot stock a shop at all: a shift-click is the only other deposit
gesture and their client cannot send one.
The button takes only stacks identical to what the shop trades, and only from the owner's 36 inventory slots - never armour, the off-hand, or a stack held on the cursor.
Two lore lines in guis/owner.yml and messages.shop-deposit-hint were reworded to name both
gestures. Those are values you already have on disk, so they are not rewritten either; copy the
new wording over from the shipped file if you want it.
Reloading
/dshop reload re-reads all four files, both menu layouts and the hologram settings. Changing the
database section needs a restart.