FreeMinecraftModels Furniture Shop
For a purchase-only economy, set registerCraftingRecipes: false in config.yml and restart. Valid enabled entries remain in the shop catalog, but are removed from Bukkit crafting and the player /fmm craftable-items menu. The setting defaults to true.
FreeMinecraftModels ships with an optional Vault-backed shop that lets players buy craftable props with in-game currency. The shop is disabled by default — it only registers itself when explicitly enabled and a Vault economy provider is available.
Quick Setup
- Install Vault and a Vault-compatible economy provider (EssentialsX, CMI, etc.).
- Start the server once so
plugins/FreeMinecraftModels/shop_config.ymlis generated. - Set
enabled: trueinshop_config.yml. - Restart the server or complete a successful
/fmm reload; the shop registers during full initialization. - Run
/fmm shopin-game to confirm the menu opens.
If any prerequisite is missing, the shop subcommand stays unregistered, so its configurable disabled message is not used through that handler. If the shop is enabled but Vault or its economy provider is missing, FMM logs a specific warning.
How It Works
- The shop reads recipes from
plugins/FreeMinecraftModels/recipes/. - The shop lists loaded recipes with
isEnabled: trueandshopEnabled: true. Recipes load as one catalog: a YAML syntax error, two enabled recipe files for the samemodel_id, or a recipe the server rejects fails the whole catalog instead of dropping one entry, so check the console after/fmm reload. Registration still constructs and validates the recipe when crafting is disabled - Each entry uses a paper display item with the model appearance when available, a price line, a purchase prompt and its model ID. Purchases produce the model's paper placement item; this path does not create an authored weapon from its
material:and enchantments - Clicking an entry calls
PurchaseHandler, which checks the player's balance via Vault, withdraws the price, and gives the player the placement item. Items that do not fit in inventory are dropped at the player's feet.
Permissions
| Permission | Default | Description |
|---|---|---|
freeminecraftmodels.shop | true | Required to open the shop. Default is true so every player can browse |
The permission alone does not enable the shop — enabled: true in shop_config.yml and a working economy provider are still required.
shop_config.yml
See the Configuration page for the full key reference. The headline keys are:
enabled— master toggle (defaultfalse)defaultPrice— default for recipes missingshopPrice; a nonpositive default falls back to100.0. Changing it does not replace existing per-recipe pricesmenuTitle,priceLoreFormat,clickToBuyLoreFormat— visual stylemessages.*— five customizable feedback messages
All message strings support & color codes and the placeholders listed in the configuration reference.
Per-Recipe Fields
Each recipe in plugins/FreeMinecraftModels/recipes/<model_id>.yml carries two shop-specific fields:
isEnabled: true
model_id: "wooden_chair"
shape:
- "L L"
- "LLL"
- "L L"
ingredients:
L: OAK_LOG
shopEnabled: true
shopPrice: 250.0
| Field | Default | Behavior |
|---|---|---|
shopEnabled | true | When false, the recipe is hidden from purchases. Crafting still depends on recipe enablement and registerCraftingRecipes |
shopPrice | defaultPrice from shop_config.yml | Vault currency cost when the player clicks the item |
The /fmm craftify builder writes both fields on save, so adjusting price is just a text edit on the recipe file followed by /fmm reload.
Purchase Outcomes
The PurchaseHandler recognizes seven outcomes. The first five map to configurable messages in shop_config.yml; the two delivery-failure messages are fixed:
| Outcome | Triggered when | Message key |
|---|---|---|
SUCCESS | Withdrawal succeeded and the item fit in inventory | messages.purchaseSuccess |
SUCCESS_WITH_OVERFLOW | Withdrawal succeeded but the item had to be dropped at the player's feet | messages.purchaseSuccess + messages.inventoryFull |
INSUFFICIENT_FUNDS | Player balance below price, or the underlying economy provider rejected the withdrawal | messages.insufficientFunds |
NOT_FOR_SALE | Recipe is disabled, has shopEnabled: false, or its model is not loaded | messages.itemNotForSale |
SHOP_DISABLED | The shop config or cached Vault hook reports disabled | messages.shopDisabled |
DELIVERY_FAILED_REFUNDED | Withdrawal succeeded, delivery failed, and the undelivered amount was refunded | Fixed: The item could not be delivered. The undelivered amount was refunded. |
DELIVERY_FAILED_REFUND_PENDING | Withdrawal succeeded, delivery failed, and the refund failed or the delivered amount could not be read | Fixed: The purchase could not be settled. The shop has been disabled; contact an administrator to review your payment. |
Use nonnegative finite shopPrice values. The purchase handler does not sanitize them before calling Vault. A rejected withdrawal response returns INSUFFICIENT_FUNDS, but provider exceptions during withdrawal are not caught here. The hook caches its provider during initialization; it does not continuously detect provider removal.
If delivery throws after the withdrawal, FMM counts how much of the purchase reached the inventory or the ground and deposits the price of the rest back. When that refund fails, or the delivered amount cannot be read, FMM disables the shop and logs [FMM Shop] Disabled after unresolved purchase with the player UUID and the amount to review. The shop stays disabled until you reconcile the payment and run /fmm reload.
Troubleshooting
/fmm shop does not exist.
The shop is unregistered. Verify all three of:
- Vault is installed
- An economy provider is registered (run
/balanceor/ecoto confirm one is responding) enabled: trueinshop_config.yml
Then restart the server or complete /fmm reload. An importer-triggered content-only reload does not reinitialize the shop config or register its command.
Items I expect to see are missing from the menu.
Open the recipe file in plugins/FreeMinecraftModels/recipes/. Check that both isEnabled and shopEnabled are true. Run /fmm reload after editing.
Players are charged but get no item.
Check for an overflow item dropped at the player's feet and inspect the console around the click. A rejected withdrawal response returns INSUFFICIENT_FUNDS; an exception from the provider during withdrawal is not converted to that result. A failed delivery logs [FMM Shop] Item delivery failed with the delivered count and the refund. If the console shows [FMM Shop] Disabled after unresolved purchase, the refund did not go through: settle that payment by hand, keep the console log and provider transaction evidence, then run /fmm reload to re-enable the shop.