FreeMinecraftModels Configuration
registerCraftingRecipes in config.yml defaults to true. Set it to false and restart for a purchase-only economy: recipes remain visible in the menus and shop, but Bukkit crafting recipes are removed. The crafting instructions on this page require this setting to remain true.
This page covers the current config.yml and shop_config.yml settings that materially affect setup, rendering, player interaction, and the optional furniture shop.
File Locations
plugins/FreeMinecraftModels/config.yml
plugins/FreeMinecraftModels/shop_config.yml
shop_config.yml is generated on first run; the shop itself stays disabled until you opt in.
plugin.yml declares api-version: 1.21.4, so Minecraft 1.21.4 is the minimum supported server version. Support for older lines was dropped; legacy render/output branches still exist in the code but are no longer reachable on a server that can load the plugin.
config.yml Settings
setupDone
- Default:
false - Controls whether the first-time setup guidance is considered complete
- Players with broad FreeMinecraftModels permissions are reminded to run
/fmm setupwhile this remainsfalse - The setup flow toggles this value for you; you do not need to hand-edit it during normal onboarding
nightbreak.autoDownloadPluginUpdates
- Default:
false - Shared MagmaCore setting (lives under the
nightbreak:section ofconfig.yml) - When
true, FreeMinecraftModels automatically downloads available plugin jar updates and content update files on startup - Downloaded plugin and content updates are only applied after the server restarts
- Automatic plugin downloads require a valid Nightbreak account token and an active supporter Patreon membership. Without both, leave this
falseand use the in-game update button instead - This is the config-key equivalent of running
/fmm downloadpluginupdate//fmm downloadallon every boot; toggle it from the/fmm setupmenu or by hand
useDisplayEntitiesWhenPossible
- Default:
true - Tells FreeMinecraftModels to prefer display-entity rendering when the server and client path support it
- The plugin still falls back to armor-stand displays when display entities are not available (the config comment names servers older than 1.19.4 and Bedrock clients; in practice the current plugin declares
api-version: 1.21.4, so the fallback you will actually hit is the Bedrock one) - Bedrock clients are a special case, so do not assume this forces the same rendering path for every player
maxModelViewDistance
- Default:
60 - Limits how far modeled entities are sent to viewers
- Lower values reduce packet and client rendering load in dense model-heavy areas
- Individual entities can override this at runtime via
ModeledEntity.setViewDistanceOverride(int)— see the API guide
maxInteractionAndAttackDistance
- Default:
3 - Applies to static and dynamic modeled entities
- Used by the runtime interaction and hit detection checks
maxInteractionAndAttackDistanceForProps
- Default:
6 - Applies to prop entities
- This is separate from the static/dynamic entity interaction distance
sendCustomModelsToBedrockClientsV2
- Default:
true - Controls whether FreeMinecraftModels attempts to send custom models to Bedrock clients
- This key replaces the older
sendCustomModelsToBedrockClients(which defaulted tofalse). The rename toV2flips the default so Bedrock players see models by default; if you previously set the old key explicitly you can delete it and the new V2 key takes over - If disabled, Bedrock players fall back to the underlying vanilla entity where that exists (and disguises will not render for them)
- If you enable it, make sure your Bedrock/Geyser/Floodgate resource-pack path is actually ready for those clients
- Runtime diagnostic logging for the Bedrock display pipeline is not a config key — it is flipped at runtime via
/fmm debug bedrock on|offso it never accidentally stays on in production. See Commands
skipUnchangedBoneUpdates
- Default:
true - When
true, a model bone only sends its per-tick move/metadata packets to viewers if its position, rotation, or scale actually changed since the last tick - Perfectly still bones (static props, idle parts of a model) send nothing, which cuts per-client packet load hard in dense areas such as NPC hubs and towns
- The periodic full resync still runs, so any rare client drift self-heals
- Set to
falseonly to restore the old "always resend every bone every tick" behavior for debugging
useDeltaMetadataPackets
- Default:
true - When
true, the per-tick metadata packet for display-entity model bones sends only the values that changed (the bone's transformation) instead of re-serializing the entire item-display blob (item model + custom model data) every tick - Full state is still sent when a player first sees a model and on the periodic resync
- Set to
falseto restore the old full-snapshot-every-tick behavior for debugging or comparison
maxModelsForProximityOverride
- Default:
25 - Pseudo load balancer for the close-range visibility override
- Normally a model within 10 blocks of a player is always shown, skipping the line-of-sight raytrace so models you are standing next to do not pop in
- In a dense area (for example a multi-floor NPC hub) that override turns dozens of models the player cannot actually see — on other floors, behind walls — into viewers that send packets every tick
- When a world holds at least this many loaded models, the close-range override is disabled in that world, so the occlusion raytrace runs even up close and culls models the player has no line of sight to. Sparse worlds keep the override, so they keep the no-pop-in behavior
- The decision is per world, not global, so a crowded hub world does not penalize quiet ones
- Raise it very high to effectively restore the always-override behavior; set it to
0to always require line of sight /fmm packetdebugis the intended tool for measuring the effect — see Commands
preventPropPlacementInProtectedRegions
- Default:
true - When
true, FreeMinecraftModels asks MagmaCore's registered protection providers whether this specific player may build in the cell the prop would occupy, and refuses the placement if the answer is no - Players with the
freeminecraftmodels.bypassregionprotectionpermission (default:op) skip the check entirely and are never blocked - Built-in player-aware providers currently cover WorldGuard and GriefPrevention. Any other plugin can register a MagmaCore protection provider and be honored the same way. With no provider registered, the check has no effect
- The refusal message is
You don't have permission to place a model here!
The check is player-aware, not region-aware. Earlier versions asked "is this location inside any protected region?" and blocked everyone. The current check asks "may this player build here?", so a player who legitimately owns the claim, or is a trusted member of it, or is inside their own WorldGuard region, can place props there normally. Only players who could not place a vanilla block in that cell are refused.
Every placement gets a single-cell check; voxelized props get a second, volume-wide one:
| Prop type | Cells checked |
|---|---|
| Normal (free-form) prop | The single cell adjacent to the clicked block face — the cell the prop will occupy |
voxelize: true prop | That same adjacent cell first, then every cell in the prop's rotated footprint (width x height x depth) around the grid-aligned placement point. If any cell in that volume is off-limits, the whole placement is refused |
The volume check exists because a voxelized prop can be several blocks wide, so testing only the clicked cell would let a player straddle a claim boundary and drop a large prop into someone else's build. It runs after the free-space check, so Not enough space to place this model! still takes priority when the footprint is physically obstructed.
The bypass permission is checked before the provider query, so granting freeminecraftmodels.bypassregionprotection is the supported way to let staff place props anywhere without disabling this key server-wide.
shop_config.yml
The optional Vault-backed furniture shop lives in its own config so it can be enabled or tuned independently of the main plugin behavior. The shop refuses to register if Vault or an economy provider is missing.
Top-level keys
| Key | Default | Description |
|---|---|---|
enabled | false | Master toggle for /fmm shop. The command only registers when this is true and Vault + an economy provider are both present |
defaultPrice | 100.0 | Price written into recipe files that do not set their own shopPrice on next load |
menuTitle | &8FMM - Furniture Shop | Title shown at the top of the shop inventory (supports & color codes) |
priceLoreFormat | &7Price: &e{price} | Lore line appended to each shop item showing its price. Placeholder: {price} |
clickToBuyLoreFormat | &aClick to purchase | Lore line appended to each shop item prompting purchase |
Message keys (messages.*)
All message strings support & color codes.
| Key | Default | Placeholders |
|---|---|---|
messages.purchaseSuccess | &aPurchased &f{item} &afor &e{price}&a. Balance: &e{balance}&a. | {item}, {price}, {balance} |
messages.insufficientFunds | &cYou need &e{price} &cto buy &f{item}&c. Balance: &e{balance}&c. | {item}, {price}, {balance} |
messages.shopDisabled | &cThe furniture shop is currently unavailable. | none |
messages.itemNotForSale | &cThat item is not currently for sale. | {item} |
messages.inventoryFull | &eYour inventory was full; &f{item} &ehas been dropped at your feet. | {item} |
Per-recipe shop fields
Each recipe file in plugins/FreeMinecraftModels/recipes/<model_id>.yml gets two additional fields:
| Field | Default | Description |
|---|---|---|
shopEnabled | true | Whether this recipe is visible in /fmm shop. Recipes with shopEnabled: false are still craftable but never listed for purchase |
shopPrice | defaultPrice from shop_config.yml | Vault currency cost for this specific item |
The recipe builder (/fmm craftify) writes both fields on save so price tuning is just a text edit away.
Permissions
Registered in plugin.yml
| Permission | Default | Description |
|---|---|---|
freeminecraftmodels.* | op | Wildcard granting admin, deleteall, self/others disguise, and region-protection bypass permissions |
freeminecraftmodels.admin | op | Access to /fmm admin (the admin content browser) and /fmm giveitem. Other admin/debug commands (/fmm location, /fmm spawn, /fmm mount, /fmm itemify, /fmm craftify, /fmm reload, /fmm stats, /fmm hitbox visualize, /fmm debug, /fmm packetdebug, /fmm setup, /fmm initialize, /fmm recommendedplugins, /fmm downloadall, /fmm downloadallcontent, /fmm updatecontent, /fmm downloadpluginupdate, /fmm forcereinstallcontent) check the wildcard freeminecraftmodels.* instead |
freeminecraftmodels.deleteall | op | Child of the wildcard; access to /fmm deleteall |
freeminecraftmodels.disguise.self | op | Allows /fmm disguise / /fmm undisguise on the sender |
freeminecraftmodels.disguise.others | op | Allows targeted disguise/undisguise plus /fmm disguiselist |
freeminecraftmodels.bypassregionprotection | op | Place and interact with props anywhere another plugin would block normal block placement, even when preventPropPlacementInProtectedRegions is on |
freeminecraftmodels.menu | true | Access to /fmm craftable items menu |
freeminecraftmodels.shop | true | Access to /fmm shop |
nightbreak.login | op | Registered by MagmaCore, not by plugin.yml. Required by the shared /nightbreaklogin and /nightbreaklogout commands |
Model YML Configuration
A model's companion .yml file has the same base name and directory as its .bbmodel. Props and held items use different parts of this configuration.
Props
isEnabled: true
voxelize: true
solidify: true
scripts:
- my_prop.lua
| Field | Description |
|---|---|
isEnabled | Whether the definition is enabled; defaults to true |
scripts | Independent prop Lua scripts from plugins/FreeMinecraftModels/scripts/ |
voxelize | Snap placement to the block grid and 90-degree rotation increments; check the whole rotated footprint for free space |
solidify | With voxelization, send packet-only barrier blocks for client collision; these are not world blocks and are removed with the prop |
Held Items
isEnabled: true
material: DIAMOND_SWORD
name: "&bFrost Blade"
lore:
- "&7A sword forged in ice"
enchantments:
- "minecraft:sharpness,3"
- "minecraft:unbreaking,2"
material selects a Bukkit item material and registers a held item instead of a prop. name and lore support color codes. Enchantments use lowercase namespaced IDs and positive integer levels. Receive registered items through /fmm giveitem <id>, the admin menu, or a configured recipe.
Equipped-item Lua scripts are retired. A held-item definition with a nonempty scripts: list, old unnamespaced enchantments such as SHARPNESS,3, or a material unavailable on this server is skipped with a diagnostic. FMM leaves the authored file unchanged. Remove the retired item script binding and author effects through enchantment definitions; prop scripts remain supported.
For wands and staves, add a magic weapon definition. Do not put weapon behavior in a prop script or the retired item hooks.
Operational Notes
/fmm reloadre-imports content and regenerates the output pack, so configuration changes that affect rendering behavior are easiest to validate after a reload. AFmmReloadedEventis dispatched on each reload so dependent plugins can re-bind their model attachments.- On a world unload, FMM removes prop runtime models while retaining their persistent backing stands. When those entities load again, it deduplicates and restores the props. This is separate from permanently picking up or destroying a prop.
- The generated pack is byte-stable, so regenerating it from an unchanged model set produces an identical zip and SHA1. That is what lets ResourcePackManager skip a redundant re-upload. See Resource Pack Output.
- FreeMinecraftModels only generates the resource pack; it does not host it by itself.
- ResourcePackManager is still the recommended delivery path for Java clients and the safest documented path for mixed setups.
- WorldGuard, WorldEdit, GriefPrevention, Vault, floodgate, and Geyser-Spigot are declared as
softdependinplugin.yml— none of them are required to start the plugin, but they unlock specific features when present: WorldGuard/WorldEdit/GriefPrevention feed both the protection-aware Lua predicates and the player-aware prop-placement check, Vault enables the furniture shop, and floodgate/Geyser-Spigot enable the Bedrock rendering backend.
When To Change These Values
Use this config for runtime behavior tuning, not content-package management.
- Use
/fmm setup,/fmm downloadall, and/fmm updatecontentfor official package lifecycle work - Use the
importsfolder for manual.bbmodelor other local content import work - Use
config.ymlwhen you need to adjust render mode, visibility distance, interaction distance, Bedrock behavior, region-protection enforcement, or automatic update downloads - Use
skipUnchangedBoneUpdates,useDeltaMetadataPackets, andmaxModelsForProximityOverridefor packet/bandwidth tuning in model-dense worlds. All three default to the optimized behavior; thefalse/ very-high settings exist for debugging and A/B comparison, not as recommended production values - Use
shop_config.yml(and the per-recipeshopEnabled/shopPricefields) to tune the furniture shop without touching code
Known Caveats
- Bedrock behavior depends on both
sendCustomModelsToBedrockClientsV2and your broader Floodgate/Geyser/resource-pack setup, so keep claims conservative unless you have tested your exact stack. - The shop silently disables itself if Vault or an economy provider is missing. Use
/fmm versionand check the console on startup if/fmm shopis unexpectedly missing.