An in‑game economy system for MITE (fml3.x) providing:
- System (server‑configured) item shop
- Player global marketplace (list / buy NBT‑aware items)
- Persistent balances
- Localized chat with parameter substitution
- Hotkeys for quick access (default: B system, G global, K mailbox)
- Minimal bandwidth (authoritative server catalogs)
- Features Overview
- System Shop
- Global Marketplace
- Economy & Balances
- Configuration Files
- Commands
- Hotkeys & Key Binding Persistence
- Chat Localization & Placeholders
- Item Tooltip Augmentation
- Data Persistence
- Networking Protocol
- Adding / Updating Prices
- Troubleshooting
- Extending / Ideas
- License
| Domain | Highlights |
|---|---|
| System Shop | Server‑owned price list (buy/sell), GUI grid, shift stack buy/sell |
| Global Marketplace | Player listings, NBT preserved, unlist refund, self‑buy protection |
| Economy | One‑decimal currency (tenths), /money query & OP set |
| Persistence | Balances (NBT), global listings (config/global_shop.cfg) |
| Localization | Keys + params; client resolves placeholders with language pack |
| Input | Two injectable key bindings (rebind safely, persisted) |
| Safety | Server authoritative pricing; client never trusts local cfg for costs |
- Open:
/shopor default hotkey B. - Grid of server items (paged 19×N).
- Shift‑click shop item → attempt full stack purchase (max stack size).
- Shift‑click your inventory slot → sells that entire stack (if configured) or disposes if forced.
Server sends the entire catalog (id, meta, buy, sell) when opening; client never reads local newshop.cfg.
Player‑driven listings:
| Action | Command / UI | Notes |
|---|---|---|
| Open marketplace | /gshop or hotkey G |
Snapshot from server |
| List item | /gshop sell <price> [amount] |
Price per item (one decimal), amount ≤ hand |
| View own listings | /gshop my |
Shows id, item, amount, price |
| Unlist | /gshop unlist <id> |
Refunds original items (NBT intact) |
| Buy | GUI click (1) / Shift (all) | Self‑buy blocked |
Listing record stores: id, owner UUID/name, item id, meta, amount, priceTenths, optional NBT (compressed on wire).
Self‑buy rejection avoids double messaging and accidental price manipulation.
- Currency unit: tenths (1 displayed decimal).
- Formatting:
whole.fraction(e.g.12.3). - Balance operations:
- Buy: subtract
- Sell: add
- Dispose (if forced unlisted sell): no change
- Persisted per player (NBT tag
shop_money).
| File | Purpose | Format |
|---|---|---|
config/newshop.cfg |
System shop price list | id[:meta]=buy,sell + force_sell_unlisted=true/false |
config/global_shop.cfg |
Player listings persistence | id;ownerUUID;ownerName;itemId;meta;amount;priceTenths;base64NBT |
force_sell_unlisted=true
minecraft:diamond=100,50
minecraft:iron_ingot=25,12
35:14=8,4 # Red wool (numeric id:meta)
263=7,3 # Coal
Rules:
- Comments start with
# minecraft:<name>matches unlocalized root (noitem./tile.prefix)- Negative or malformed lines ignored
- Prices accept one decimal (tenths stored)
| Command | Description | Access |
|---|---|---|
/shop |
Open system shop | All |
/shop reload |
Reload server price list (no GUI forced) | All (adjust via wrapper if needed) |
/gshop |
Open global market | All |
/gshop sell <price> [amount] |
List item in hand | All |
/gshop my |
Show own listings | All |
/gshop unlist <id> |
Remove listing & refund | All |
/money |
Show balance | All |
/money <amount> |
Set own balance | OP |
Default bindings:
- System shop: B (
key.openShop) - Global market: G (
key.openGlobalShop) -
- Mailbox: K (
key.openMailbox)
- Mailbox: K (
Persistence details:
- Custom bindings are appended after GameSettings constructor.
- A Mixin re-parses
options.txtto restore saved keyCodes for these descriptions. - Rebinding via the Controls menu persists normally across restarts.
Server sends raw keys with pipe‑delimited parameters:
shop.buy.success|item=Diamond Sword|count=1|cost=120.0
gshop.sale.success|buyer=Alice|item=Enchanted Book|count=2|revenue=50.0
Client Mixin:
- Detects prefix (
shop.,gshop.,globalshop.) - Looks up translation
- Replaces
{item},{count},{cost},{gain},{revenue},{buyer},{seller},{id},{page},{pages},{price},{amount},{balance}. - When on a remote server, also attempts to translate raw
tile.*.name/item.*.nametokens inside param values.
Context flags:
inShop(system shop GUI open)inGlobalShop(global market GUI open)
Global market stacks get transient NBT markers (GShopPriceTenths, etc.) to inject listing info without altering the player's real inventory items.
System shop uses NBT values sent per catalog entry; falls back to server config (should be redundant).
| Data | Mechanism |
|---|---|
| Player balance | Player NBT tag (shop_money) |
| Global listings | config/global_shop.cfg lines |
| System prices | config/newshop.cfg authoritative on server |
| Key binds | options.txt (with custom re-load) |
| ID | Dir | Payload | Description |
|---|---|---|---|
| 1 | S→C | resultKey, balance | Transaction/result message |
| 2 | C→S | itemID, meta, count | System buy |
| 3 | C→S | itemID, count, slotIndex | System sell |
| 4 | S→C | windowId, balance, catalog[] | Open system shop + catalog |
| 5 | S→C | 36 slots | Inventory sync |
| 6 | C→S | — | Open system shop |
| 7 | S→C | windowId, balance, listings[] | Global market snapshot |
| 8 | C→S | — | Open global market |
| 9 | C→S | listingId, count | Buy listing |
| 10 | C→S | itemId, meta, amount, price | (Reserved) future GUI listing |
| 11 | C→S | listingId | Unlist listing |
Catalog entry: (itemID, meta, buyTenths, sellTenths)
Listing entry: (id, itemId, meta, amount, priceTenths, ownerName, [NBT])
- Edit
config/newshop.cfg - Run
/shop reload - Players reopening the/system shop will receive updated catalog.
No GUI auto-pop on reload (prevents surprise context switches).
MIT