Installation
- 1Drop MarketPulse-1.0.0.jar into plugins/.
- 2Install Vault and any economy plugin. Without one MarketPulse loads and quotes prices but refuses every trade, rather than telling players they were paid when nothing moved.
- 3Start the server. Paper fetches the SQLite driver itself on first start.
- 4Read the startup line: it names the economy it hooked, the catalogue size, and any command name another plugin already owns.
- 5Type /marketpulse to open the market, or /marketpulse price diamond 64 to see the curve.
How a price is worked out
Every item has a stock level, and the price is a function of it:
price = price_field x (base-stock / current-stock) ^ elasticityclamped to a floor and a ceiling you set per item. At exactly base-stock an item costs the price you typed, so the config file means what it looks like it means. Buying drains stock and the price rises; selling refills it and the price falls.
Setting elasticity to 0 pins a price forever. That is the supported way to have one fixed-price line in a dynamic market, rather than a separate code path nobody tests.
Why a bulk order costs more than the shelf price
Each unit is priced at the stock level it is actually traded at, and the quote is the sum. With the shipped defaults, one diamond is $120.00 and sixty-four are $7,723.88 — not $7,680.00.
This is the whole plugin. The obvious implementation quotes the current price and multiplies by the quantity, and it is wrong in the one case that matters: a player selling ten stacks of iron gets paid the pre-dump price for all 640 of them, and the market only reacts afterwards — to a crash that already happened, at somebody else’s expense.
Players are shown it happening. After a bulk trade the plugin reports the first and last unit price of their own order, and the item’s new price, so the lesson that dumping is worth less than trickling is learned from the market rather than from a wiki page.
The three settings that decide your economy
**spread** (default 0.25) is the market’s cut: sell price = buy price x (1 - spread). Never set it to 0 — at 0 a round trip is free, and free is enough for a player to churn an item’s price in both directions all day. It is also your main money sink.
**elasticity** is per item, and decides how violently a price reacts. 1.0 is proportional: half the stock, twice the price. The defaults set farm-automatable items high (cobblestone 1.4, iron 1.3, emerald 1.3 — a villager hall is automation whatever the ore is worth) and hand-mined ones lower (diamond 0.9), so the curve does not punish the players it exists to protect.
**drift.rate** (default 0.05) is how fast prices recover, as the fraction of the gap closed every interval. Set it to 0 and prices freeze where they are: whatever the first week does to iron is iron’s price forever. That is a supported choice and a much harsher server.
Sell caps, for what farms produce by the shulker box
Optional, per item: sell-cap sets how many units one player may sell per window, and market.sell-window-hours sets the window.
The clock starts at that player’s first sale of the item, not at midnight. A calendar reset is a cliff nobody on the server shares a timezone with, and it hands the whole allowance to whoever happens to be awake at the right moment.
Caps and elasticity do different jobs: elasticity makes dumping unprofitable, a cap makes it impossible. Most servers want the first, and only need the second on two or three items.
Only plain items trade
An enchanted, renamed, damaged or otherwise customised item is invisible to the market and stays in the player’s inventory.
This is not a nicety. A market that matched on material alone would buy a Mending netherite pickaxe at the price of a bare one — and the player who did it by accident would not find out until much later. Every match compares the whole stack against a freshly constructed one, which means potion contents, written books, shulker contents and anything a future Minecraft version invents fail the check too, without the plugin needing to know they exist.
/marketpulse sell hand says so explicitly when you are holding something it will not take, because "the market does not buy that" about an item it visibly lists is the most confusing refusal a shop can give.
Permissions
marketpulse.use and marketpulse.history default to everyone; marketpulse.history.others and marketpulse.admin default to op.
Commands are deliberately not declared in plugin.yml. A permission there makes Paper hide the command from anyone lacking the node, so a player without it gets Brigadier’s "unknown command" and cannot tell a missing permission from a broken plugin. MarketPulse registers into the command map instead and refuses with a message that explains itself.
Every node is declared with a real default, because an undeclared node is op-only whatever your permissions plugin says about it — which looks exactly like a permissions plugin that is not working.
What is on the record
plugins/MarketPulse/data.db holds stock levels, the trade ledger and sell allowances.
Stock is written through on every trade rather than saved on shutdown, so a crash costs nothing — and a crash is exactly when a server is least likely to shut down cleanly. Stock is the price, so losing it would mean every price silently reverting to baseline.
The ledger is append-only: a trade is never updated or deleted. Operator changes made with /marketpulse stock are deliberately not written to it — the ledger answers "who traded what", an operator correction is not a trade, and recording one there would make the history lie about where the money went. It goes to the server log instead.
Commands
| Command | What it does | Permission |
|---|---|---|
/marketpulse | Open the market. Aliases /market, /shop and /mp, each droppable in the config. | marketpulse.use (everyone) |
/marketpulse price (item) [qty] | What it costs right now — including what a bulk order would really clear at. | marketpulse.use |
/marketpulse buy (item) [qty|all] · /marketpulse sell (item|hand) [qty|all] | Trade from chat. Orders are trimmed to what you can hold, afford or still sell, then re-priced. | marketpulse.use |
/marketpulse sellall | Sell everything tradeable you are carrying, each line priced separately. | marketpulse.use |
/marketpulse top [rising|falling] | What is short and what is a glut, right now. | marketpulse.use |
/marketpulse history [player|all] | The ledger. Your own by default; anyone’s with the extra node. | marketpulse.history (everyone) |
/marketpulse stock (item) [amount|reset] | Read or set a stock level — the direct way to move a price without a trade. | marketpulse.admin |
/marketpulse drift | Run one recovery step now, so you can see a setting you just changed take effect. | marketpulse.admin |
/marketpulse commands | Which command names this plugin actually owns on your server. | marketpulse.admin |
Still stuck?
Post in Discord with your server version and the relevant part of the log. That is almost always enough to get a straight answer the same day.
Get help