general — Plain, single-line server name — used by the {server_name} placeholder (scoreboard, tablist, chat, etc). Deliberately separate from server.properties' "motd" (and from NeoEssentials' own /motd system): that MOTD is typically multi-line and heavily formatted for the multiplayer server list, which breaks when dropped into a single scoreboard/tablist line. Use {server_motd} instead if you actually want the configured MOTD text somewhere. |
general.serverName | "My Server" | — |
hologram — How often the hologram scheduler POLLS every hologram to see if it's due for a refresh (pollIntervalTicks, in server ticks — 20 = once/second) and advances animation/spin/hover (animationInterval, in ticks — 1 = every tick, the fastest possible). pollIntervalTicks is NOT how often placeholders actually refresh — that's each hologram's own refreshInterval (in SECONDS, default 5, set via "/hologram refreshinterval <id> <seconds>"). Lowering pollIntervalTicks below that per-hologram gate does nothing visible; it only exists so the gate itself gets checked promptly rather than up to a full poll cycle late. animationInterval only covers {animation:NAME} frame advancement, /hologram addframes cycling, and spin/hover motion — there's no benefit setting it below 1, since an animation's own frameDuration is already clamped to a 50ms (1-tick) minimum. Apply changes with "/neoe reload". |
hologram.pollIntervalTicks | 10 | — |
hologram.animationInterval | 1 | — |
modules — Enable or disable major mod subsystems (true = enabled, false = disabled). RESTART REQUIRED — whether a command is registered at all (and whether a subsystem's manager is initialized) is decided once at server start. "/neoe reload" only refreshes config VALUES, it can't add/remove already-registered commands, so toggling anything in this section (or in "commands" below) will NOT take effect until the server restarts. |
modules.economyEnabled | true | — |
modules.permissionsEnabled | true | — |
modules.kitsEnabled | true | — |
modules.teleportationEnabled | true | — |
modules.moderationEnabled | true | — |
modules.chatEnabled | true | — |
modules.webDashboardEnabled | true | — |
modules.hologramsEnabled | true | — |
modules.shopEnabled | true | — |
modules.auctionHouseEnabled | true | — |
modules.vaultEnabled | true | — |
modules.tablistEnabled | true | — |
modules.scoreboardEnabled | true | — |
modules.resourcePacksEnabled | true | — |
modules.playerTagsEnabled | true | — |
modules.discordIntegrationEnabled | true | — |
modules.votifierEnabled | true | — |
modules.cratesEnabled | true | — |
logging — Per-subsystem logging control. For each category: "normal": routine info-level messages -> console + logs/latest.log (default: on) "debug": verbose trace messages -> logs/debug.log only (default: off) Warnings and errors are ALWAYS logged regardless of these settings — these toggles only control routine chatter and opt-in verbose tracing, never real problems. Reload in-game with /neoessentials reload after changing these. |
logging.categories |
logging.categories.chat | { "normal": true, "debug": false } | — |
logging.categories.economy | { "normal": true, "debug": false } | — |
logging.categories.permissions | { "normal": true, "debug": false } | — |
logging.categories.teleportation | { "normal": true, "debug": false } | — |
logging.categories.moderation | { "normal": true, "debug": false } | — |
logging.categories.auctionHouse | { "normal": true, "debug": false } | — |
logging.categories.kits | { "normal": true, "debug": false } | — |
logging.categories.webDashboard | { "normal": true, "debug": false } | — |
logging.categories.discord | { "normal": true, "debug": false } | — |
logging.categories.config | { "normal": true, "debug": false } | — |
logging.categories.commands | { "normal": true, "debug": false } | — |
logging.categories.votifier | { "normal": true, "debug": false } | — |
logging.categories.crates | { "normal": true, "debug": false } | — |
logging.categories.general | { "normal": true, "debug": false } | — |
storage |
storage.type | "json" | "json" (default, one file per collection), "yaml" (same shape, human-editable), "sqlite" (single embedded database file), or "mysql" (shared network database — use this to sync moderation/economy/etc. data across multiple servers). RESTART REQUIRED — StorageManager picks the backend once at server start and never reconstructs it; "/neoe reload" only refreshes config VALUES, so changing this and reloading silently keeps every manager on the OLD backend with no warning that anything is wrong. Existing data auto-migrates into the new backend on the restart that actually picks it up (see autoMigrate below). |
storage.autoMigrate | true | Existing JSON data is imported automatically the first time you switch away from "json" — set false only if you deliberately want a fresh, empty store. |
storage.sqlite |
storage.sqlite.file | "data.db" | Relative to the server's data directory (neoessentials/store/<this file>) |
storage.sqlite.autoDownloadDriver | true | The SQLite driver isn't bundled in the mod jar (it used to be, but its native library caused it to conflict with other mods that also bundle their own copy — see the SqliteDriverProvisioner javadoc). It's downloaded from Maven Central and verified against a pinned checksum the first time SQLite storage is actually used. Set false to disable that download and place the driver jar yourself instead — the server log will tell you the exact path and download URL if it's missing. |
storage.mysql |
storage.mysql.host | "localhost" | — |
storage.mysql.port | 3306 | — |
storage.mysql.database | "neoessentials" | — |
storage.mysql.username | "neoessentials" | — |
storage.mysql.password | "" | — |
storage.mysql.useSSL | false | — |
storage.mysql.poolSize | 10 | Max concurrent connections in the pool |
storage.mysql.autoDownloadDriver | true | The MySQL driver isn't bundled in the mod jar (it used to be, but it caused the same kind of split-package module conflict as the SQLite driver used to — see the MySqlDriverProvisioner javadoc). It's downloaded from Maven Central and verified against a pinned checksum the first time MySQL storage is actually used. Set false to disable that download and place the driver jar yourself instead — the server log will tell you the exact path and download URL if it's missing. |
commands |
commands.balance | true | — |
commands.pay | true | — |
commands.paytoggle | true | — |
commands.eco | true | — |
commands.baltop | true | — |
commands.repair | true | — |
commands.dispose | true | — |
commands.powertool | true | — |
commands.powertooltoggle | true | — |
commands.tablist | true | — |
commands.scoreboard | true | — |
commands.clearinventory | true | — |
commands.enchant | true | — |
commands.enchanthand | true | — |
commands.msg | true | — |
commands.reply | true | — |
commands.afk | true | — |
commands.ignore | true | — |
commands.unignore | true | — |
commands.mute | true | — |
commands.unmute | true | — |
commands.msgtoggle | true | — |
commands.socialspy | true | — |
commands.mutelist | true | — |
commands.permissions | true | — |
commands.kit | true | — |
commands.createkit | true | — |
commands.delkit | true | — |
commands.listkits | true | — |
commands.home | true | — |
commands.sethome | true | — |
commands.delhome | true | — |
commands.listhomes | true | — |
commands.warp | true | — |
commands.setwarp | true | — |
commands.delwarp | true | — |
commands.listwarps | true | — |
commands.spawn | true | — |
commands.setspawn | true | — |
commands.tpa | true | — |
commands.tpahere | true | — |
commands.tpaccept | true | — |
commands.tpdeny | true | — |
commands.tpcancel | true | — |
commands.tp | true | — |
commands.tphere | true | — |
commands.tpall | true | — |
commands.tpo | true | — |
commands.tppos | true | — |
commands.back | true | — |
commands.top | true | — |
commands.jump | true | — |
commands.jumpto | true | — |
commands.tpr | true | — |
commands.settpr | true | — |
commands.ban | true | — |
commands.tempban | true | — |
commands.unban | true | — |
commands.banip | true | — |
commands.unbanip | true | — |
commands.kick | true | — |
commands.kickall | true | — |
commands.jail | true | — |
commands.unjail | true | — |
commands.setjail | true | — |
commands.deljail | true | — |
commands.vanish | true | — |
commands.freeze | true | — |
commands.unfreeze | true | — |
commands.dashboard | true | — |
commands.anvil | true | — |
commands.book | true | — |
commands.crafting | true | — |
commands.compass | true | — |
commands.getpos | true | — |
commands.fletching | true | — |
commands.depth | true | — |
commands.helpop | true | — |
commands.list | true | — |
commands.near | true | — |
commands.motd | true | — |
commands.nick | true | — |
commands.realname | true | — |
commands.rules | true | — |
commands.sign | true | — |
commands.seen | true | — |
commands.smithing | true | — |
commands.stonecutting | true | — |
commands.suicide | true | — |
commands.whois | true | — |
commands.invsee | true | — |
commands.enderchest | true | — |
commands.enderchestedit | true | — |
commands.worth | true | — |
commands.sell | true | — |
commands.setworth | true | — |
commands.kitreset | true | — |
commands.broadcast | true | — |
commands.time | true | — |
commands.day | true | — |
commands.night | true | — |
commands.weather | true | — |
commands.sun | true | — |
commands.storm | true | — |
commands.thunder | true | — |
commands.kill | true | — |
commands.gamemode | true | — |
commands.tpohere | true | — |
commands.tpoffline | true | — |
commands.ptime | true | — |
commands.pweather | true | — |
commands.effect | true | — |
commands.spawnmob | true | — |
commands.mob | true | — |
commands.unlimited | true | — |
commands.condense | true | — |
commands.me | true | — |
commands.tptoggle | true | — |
commands.gc | true | — |
commands.mem | true | — |
commands.lightning | true | — |
commands.smite | true | — |
commands.skull | true | — |
commands.itemname | true | — |
commands.rename | true | — |
commands.itemlore | true | — |
commands.remove | true | — |
commands.loom | true | — |
commands.cartography | true | — |
commands.cartographytable | true | — |
commands.renamehome | true | — |
commands.warpinfo | true | — |
commands.world | true | — |
commands.spawner | true | — |
commands.recipe | true | — |
commands.tpauto | true | — |
commands.fireball | true | — |
commands.tree | true | — |
commands.bigtree | true | — |
commands.break | true | — |
commands.ice | true | — |
commands.bottom | true | — |
commands.tpaall | true | — |
commands.broadcastworld | true | — |
commands.bcastworld | true | — |
commands.ping | true | — |
commands.playtime | true | — |
commands.sudo | true | — |
commands.rtoggle | true | — |
commands.firework | true | — |
commands.nuke | true | — |
commands.itemdb | true | — |
commands.potion | true | — |
commands.info | true | — |
commands.antioch | true | — |
commands.kittycannon | true | — |
commands.beezooka | true | — |
commands.rest | true | — |
commands.backup | true | — |
commands.backupCommand | "" | Shell command to run when /backup is used (leave empty to disable) |
commands.showkit | true | — |
commands.powertoollist | true | — |
commands.customtext | true | — |
commands.payconfirmtoggle | true | — |
commands.ciconfirmtoggle | true | — |
commands.item | true | — |
commands.i | true | — |
commands.help | true | — |
commands.tempbanip | true | — |
commands.togglejail | true | — |
commands.jails | true | — |
commands.jailinfo | true | — |
commands.banlist | true | Previously missing entries (commands that existed in code but had no toggle — added so every registered command is actually controllable). |
commands.clearwarnings | true | — |
commands.freezeall | true | — |
commands.unfreezeall | true | — |
commands.freezelist | true | — |
commands.jailfor | true | — |
commands.jaillist | true | — |
commands.unvanish | true | — |
commands.vanishlist | true | — |
commands.warn | true | — |
commands.warnings | true | — |
commands.removewarn | true | — |
commands.note | true | — |
commands.notes | true | — |
commands.removenote | true | — |
commands.report | true | — |
commands.reports | true | — |
commands.reviewreport | true | — |
commands.chatformat | true | — |
commands.dashboardregister | true | — |
commands.linkaccount | true | — |
commands.language | true | — |
commands.neoe | true | — |
commands.neoessentials | true | — |
commands.placeholder | true | — |
commands.pex | true | — |
commands.mail | true | — |
commands.nearby | true | — |
commands.who | true | — |
commands.online | true | — |
commands.nickname | true | — |
commands.setnick | true | — |
commands.grindstone | true | — |
commands.ci | true | — |
commands.clearinv | true | — |
commands.fix | true | — |
commands.trash | true | — |
commands.inv | true | — |
commands.ec | true | — |
commands.ecedit | true | — |
commands.pt | true | — |
commands.ptt | true | — |
commands.pwarp | true | — |
commands.setpwarp | true | — |
commands.delpwarp | true | — |
commands.pwarps | true | — |
commands.holo | true | — |
commands.hologram | true | — |
commands.chestshop | true | — |
commands.cshop | true | — |
commands.npcshop | true | — |
commands.ah | true | — |
commands.auctionhouse | true | — |
commands.vault | true | — |
economy |
economy.sellMultiplier | 1.0 | Currency symbol and starting balance are configured in economy.json, not here — these keys used to also exist here but were always shadowed by economy.json's copy. Multiplier for all /sell prices (1.0 = 100%, 0.5 = 50%, 2.0 = 200%) |
economy.allowSellNamedItems | false | Allow selling items that have a custom display name (renamed items) |
economy.useExternalEconomy | false | Use a detected external economy mod (e.g. SG Economy API) instead of NeoEssentials' own internal balances, registered at higher priority into the Vault service registry (see vault/VaultManager.java). Off by default — an operator has to explicitly opt in, since silently switching which mod controls player money is higher-stakes than the equivalent external-permissions toggle. |
localization |
localization.language | "" | Language code (e.g. "fr_fr", "de_de"). Leave empty for "en_us". Change with /language <code>. |
localization.preserveCustomTranslations | false | — |
webDashboard |
webDashboard.enabled | true | Master switch for the web dashboard |
webDashboard.autoStart | false | Start automatically on server boot. false = use /dashboard start |
webDashboard.port | 8080 | HTTP server port (1024–65535). Restart required after changing. |
webDashboard.websocketPort | 8081 | WebSocket port for real-time updates. Must differ from HTTP port. |
webDashboard.bindAddress | "0.0.0.0" | Bind address: '0.0.0.0' = all interfaces, '127.0.0.1' = localhost only (more secure) |
webDashboard.mode | "external" | How the dashboard is served: "external" — serve ONLY the REST API under "/api/*"; the "/" static-file route is not registered at all (default). Use this if you run a separate dashboard app (e.g. NeoEssentials-Dashboard, a Laravel app) that talks to this API from outside. "internal" — serve the mod's own bundled dashboard UI (webdashboard-ui) at "/" AND the REST API under "/api/*". "both" — serve both (same as "internal", kept as an explicit alias for clarity when you intentionally use the built-in UI AND point an external app at the same API). |
webDashboard.publicUrl | "" | Public-facing base URL for the mod's OWN bundled dashboard (mode "internal"/"both"), e.g. "http://your.server.ip:8080" or "https://mc.example.com" if reverse-proxied. The mod cannot reliably auto-detect this — it may sit behind NAT/port-forwarding or a proxy, so bindAddress/port alone aren't enough to build a browser-usable link. Leave empty to disable features that need a public dashboard link (e.g. the in-chat "view profile" link on player names) when running in "internal" mode. Not needed at all in "external" mode — externalDashboard.url below is used instead. |
webDashboard.customProfileUrlTemplate | "" | Point the in-chat "view profile" link at your OWN external site instead of either NeoEssentials dashboard — full control over the URL shape. Supports {player} (URL-encoded username) and {uuid} placeholders, e.g. "https://myserver.com/players/{player}". Takes priority over externalDashboard.url/publicUrl above when set. Leave empty to use one of those instead. |
webDashboard.externalDashboard — Populated automatically by running `/dashboard pair <dashboardUrl> <code>` in-game/ console (get the code from the dashboard's own Configuration page) — never hand-type these. Once paired, url/token push a notification (Authorization: Bearer <token>) whenever a dashboard_user is created/updated/deleted here, so the external dashboard can mirror the change into its own user table automatically. Empty/absent = not paired yet. Use /dashboard unpair to clear. This URL is also reused to build the in-chat "view profile" link on player names when running in "external" mode. |
webDashboard.externalDashboard.url | "" | — |
webDashboard.externalDashboard.token | "" | — |
webDashboard.externalDashboard.keyId | "" | — |
webDashboard.roleSync — Keeps a linked player's dashboard role (see /dashboardregister) in sync with their real in-game permission status — grants ADMIN when they gain the configured permission/group, revokes it again when they lose it. Off by default. Only ever adjusts roles it granted itself — a role you set manually (e.g. /apikey create <label> OPERATOR) is never touched. |
webDashboard.roleSync.enabled | false | — |
webDashboard.roleSync.intervalSeconds | 300 | How often (seconds) the reconciliation sweep runs, in addition to an immediate check whenever a linked player joins. |
webDashboard.roleSync.adminPermission | "neoessentials.admin.dashboard" | A player with this permission node is granted the dashboard ADMIN role. Leave empty to not check by permission node. |
webDashboard.roleSync.adminGroup | "admin" | A player in this permission group is granted the dashboard ADMIN role. Leave empty to not check by group. Checked in addition to (OR) adminPermission. |
webDashboard.securitySettings |
webDashboard.securitySettings.requireAuthentication | true | Require Bearer token authentication on all API endpoints (strongly recommended) |
webDashboard.securitySettings.enableRateLimiting | true | Enable per-IP rate limiting on dashboard API requests |
webDashboard.securitySettings.maxRequestsPerMinute | 60 | Maximum API requests per IP per minute when rate limiting is enabled |
webDashboard.securitySettings.publicModerationLookupEnabled | true | Public, no-login player moderation lookup (bans/mutes/kicks/warns by player name, plus a recent-punishments feed) — matches ban-management plugins' public transparency page. Never exposes IP bans/IP mutes regardless of this setting. |
security |
security.enableInputValidation | true | — |
security.maxCommandLength | 256 | — |
security.maxReasonLength | 500 | — |
security.allowUnsafeCommands | true | — |
security.enableCommandLengthEnforcer | true | Controls whether the CommandLengthEnforcer event handler validates player commands |
items |
items.permission-based-item-spawn | false | Require 'neoessentials.item.spawn' (and per-item nodes) to spawn items via commands |
items.oversized-stacksize | 64 | Maximum stack size for oversized stacks |
items.default-stack-size | -1 | Default stack size for all items. -1 = use vanilla behaviour. |
items.unsafe-enchantments | true | Allow enchantments beyond vanilla limits (e.g. Sharpness X) |
items.max-unsafe-enchantment-level | 32767 | Maximum level allowed when unsafe-enchantments is true |
items.item-spawn-blacklist — Items that cannot be spawned via commands even with permissions |
items.inventoryAuditLog | true | Log every /invsee and /enderchest view/edit to neoessentials/inventory_audit.log |
shop |
shop.pricing |
shop.pricing.enabled | false | Master switch. false = every shop uses its raw configured buy/sell price, no computation overhead at all. All the sub-sections below are ignored while off. |
shop.pricing.supplyDemand — Prices drift toward maxMultiplier as a shop's stock depletes, and toward minMultiplier as it fills back up — buying gets more expensive, selling gets less rewarding, the closer a shop is to running out. |
shop.pricing.supplyDemand.enabled | true | — |
shop.pricing.supplyDemand.maxStock | 500 | Stock level (items) at which the multiplier bottoms out at minMultiplier |
shop.pricing.supplyDemand.minMultiplier | 0.8 | — |
shop.pricing.supplyDemand.maxMultiplier | 2.0 | — |
shop.pricing.timeDiscount — Flat percentage discount on buy prices during a fixed daily time window (server time, 24h clock). |
shop.pricing.timeDiscount.enabled | true | — |
shop.pricing.timeDiscount.startHour | 12 | — |
shop.pricing.timeDiscount.endHour | 14 | — |
shop.pricing.timeDiscount.discountPercent | 10.0 | — |
shop.pricing.bulkTiers — Extra discount for buying in bulk. Each tier's discount applies once the purchase quantity reaches minQuantity; only the highest tier a purchase qualifies for is applied. Leave the array empty to disable bulk discounts without touching the other rules above. |
permissions |
permissions.useExternalPermissions | true | Use an external permission system (LuckPerms etc.) instead of the built-in one |
permissions.defaultGroup | "default" | — |
permissions.opsBypassPermissions | true | Allow server operators (OP level) to bypass permission checks |
permissions.vanillaOpFallback | true | — |
permissions.requireExplicitGrant | true | When true, a player gets a command only if you granted its node (LuckPerms or the internal manager). PermissionRegistry defaultValue=true is NOT used as a silent grant. OP still bypasses when opsBypassPermissions is true. Set false to restore "player commands work for everyone unless denied". |
permissions.opsBypassEconomyModifierPermissions | false | Whether the two OP-bypass settings above also apply to GRADED economy-modifier permission nodes (neoessentials.economy.sellmultiplier.*, .taxexempt, .nopaycooldown, .maxbalance.*, .paylimit.*). Those nodes represent opt-in bonuses meant to be granted explicitly (per-player or per-group) — not admin capabilities — so this defaults to false: OPs get their usual command-permission bypass, but do NOT silently receive the highest sell multiplier / free tax exemption / no pay cooldown just for being OP. Set true to restore the old blanket-bypass behavior. |
permissions.wildcardsGrantEconomyModifierPermissions | false | Whether a wildcard permission (e.g. "neoessentials.*", "neoessentials.economy.*") granted to a group or user is allowed to satisfy the same graded economy-modifier nodes above (sellmultiplier tiers, taxexempt, nopaycooldown, maxbalance/paylimit tiers). Defaults to false: those nodes must be listed explicitly (either the exact node itself, or a wildcard scoped no broader than "neoessentials.economy.sellmultiplier.*" etc.) even for a group whose permission list is just "neoessentials.*" — a broad admin wildcard should not silently hand out a 3x sell multiplier or free tax exemption nobody deliberately assigned that group. Set true to let wildcards cover these nodes too. |
permissions.cachePermissions | true | — |
permissions.permissionCacheExpiryMinutes | 30 | Minutes before cached permission entries expire |
permissions.auditLogging | true | Log all permission grant/revoke actions |
afk |
afk.enabled | true | — |
afk.timeout | 300 | Seconds of inactivity before a player is marked AFK |
afk.kickTimeout | 0 | Seconds after going AFK before the player is kicked (0 = disabled) |
afk.afkkickMessage | "Kicked for being AFK too long" | — |
afk.enableafkBroadcasts | true | — |
afk.broadcastOnAfk | true | — |
afk.broadcastOnReturn | true | — |
afk.afkMessage | "{player} is now AFK" | — |
afk.returnMessage | "{player} is no longer AFK" | — |
afk.ignoreAfkInSleep | true | AFK indicator in the tablist is configured in tablist.json (showAfkIndicator/afkSuffix), not here. Ignore AFK players when counting sleep votes |
afk.enableActivityTracking | true | — |
afk.trackMovement | true | — |
afk.trackChat | true | — |
afk.trackCommands | true | — |
afk.trackInteractions | true | — |
afk.movementThreshold | 0.1 | — |
afk.rotationThreshold | 5.0 | — |
afk.excludedCommands | ["afk", "list", "who", "tps", "ping", "help", "?"] | Commands that do not reset the AFK timer |
afk.autoSave | true | — |
afk.saveInterval | 60 | — |
afk.invulnerableWhenAfk | false | Make AFK players immune to all damage (mobs, environment, explosions, etc.) Useful for hardcore-style servers where an AFK death would be permanent |
kits |
kits.skipUsedOneTimeKitsFromKitList | false | Hide one-time-use kits from /kit list after they have been claimed |
kits.kitAutoEquip | false | Auto-equip kit armor when the player's armor slots are empty |
kits.pastebinCreatekit | false | Use pastebin for /createkit output instead of writing to kits.json directly |
kits.maxKitsPerPlayer | 10 | Maximum active kit cooldowns per player (-1 = unlimited) |
kits.allowKitOverride | true | Allow players with the override permission to bypass kit cooldowns |
kits.logKitUsage | true | Log kit usage to server logs |
kits.commandCosts — Economy cost per kit command use (0 = free) |
kits.commandCosts.kit | 0 | — |
kits.commandCosts.createkit | 0 | — |
kits.commandCosts.delkit | 0 | — |
kits.commandCosts.listkits | 0 | — |
kits.newPlayerKit — Kit given to players on their very first join (bypasses cost and permissions) |
kits.newPlayerKit.enabled | false | — |
kits.newPlayerKit.kitName | "" | Kit name, e.g. "starter". Leave empty to disable. |
teleportation |
teleportation.homeSettings |
teleportation.homeSettings.maxHomes | 5 | Maximum homes per player (-1 = unlimited) |
teleportation.homeSettings.allowCrossDimensionHomes | true | Allow homes to be set in the Nether, End, etc. |
teleportation.homeSettings.homeSetCooldown | 30 | Cooldown in seconds between /sethome uses (0 = disabled) |
teleportation.homeSettings.homeTeleportCooldown | 5 | Cooldown in seconds between /home teleports (0 = disabled) |
teleportation.homeSettings.homeDeleteCooldown | 10 | Cooldown in seconds between /delhome uses (0 = disabled) |
teleportation.homeSettings.requireConfirmationForDelete | true | Require confirmation dialog before deleting a home |
teleportation.homeSettings.enableHomeTeleportSafety | true | Block /home if the destination is unsafe (lava, void, solid ceiling, etc.) |
teleportation.homeSettings.logHomeActions | true | Log home set / delete / teleport actions |
teleportation.warpSettings |
teleportation.warpSettings.allowPlayerWarps | true | Allow players to create their own warps (requires permission) |
teleportation.warpSettings.maxPlayerWarps | 3 | Maximum player-created warps (-1 = unlimited) |
teleportation.warpSettings.warpCooldown | 10 | Cooldown in seconds between /warp uses (0 = disabled) |
teleportation.warpSettings.warpSetCooldown | 60 | Cooldown in seconds between /setwarp uses (0 = disabled) |
teleportation.warpSettings.allowCrossDimensionWarps | true | Allow warps across dimensions |
teleportation.warpSettings.logWarpActions | true | Log warp creation / deletion / usage |
teleportation.warpSettings.perWarpPermission | false | Require 'neoessentials.warps.<name>' permission for each individual warp |
teleportation.spawnSettings |
teleportation.spawnSettings.spawnOnJoin | true | Teleport players to spawn on their first join |
teleportation.spawnSettings.spawnOnDeath | false | Teleport players to spawn on death (overrides bed spawn) |
teleportation.spawnSettings.spawnCooldown | 5 | Cooldown in seconds between /spawn uses (0 = disabled) |
teleportation.spawnSettings.allowSpawnSet | true | Allow /setspawn |
teleportation.spawnSettings.enableSpawnSafety | true | Block spawn teleport if the spawn location is unsafe |
teleportation.spawnSettings.logSpawnActions | true | Log spawn teleports and spawn point changes |
teleportation.teleportRequestSettings |
teleportation.teleportRequestSettings.requestTimeout | 60 | Seconds before TPA requests expire |
teleportation.teleportRequestSettings.maxPendingRequests | 5 | Maximum pending requests a player can have at once |
teleportation.teleportRequestSettings.cooldownBetweenRequests | 10 | Cooldown in seconds between sending TPA requests |
teleportation.teleportRequestSettings.allowMultipleRequests | false | Allow multiple TPA requests to the same player |
teleportation.teleportRequestSettings.enableRequestNotifications | true | Send chat notifications for incoming TPA requests |
teleportation.teleportRequestSettings.autoAcceptFromFriends | false | Auto-accept requests from friends (requires friends system) |
teleportation.teleportRequestSettings.enableTeleportSafety | true | Block teleportation to unsafe destinations |
teleportation.teleportRequestSettings.logTeleportRequests | true | Log TPA request actions |
teleportation.generalSettings |
teleportation.generalSettings.teleportDelay | 3 | Warm-up delay in seconds before teleportation completes (0 = instant) |
teleportation.generalSettings.cancelOnMovement | true | Cancel the teleport if the player moves during the warm-up delay |
teleportation.generalSettings.cancelOnDamage | false | Cancel the teleport if the player takes damage during the warm-up delay |
teleportation.generalSettings.enableTeleportWarmup | true | Show countdown messages during the teleport delay |
teleportation.generalSettings.allowTeleportInCombat | false | Allow teleportation while in combat (requires combat system) |
teleportation.generalSettings.maxTeleportDistance | -1 | Maximum teleport distance in blocks (-1 = unlimited) |
teleportation.generalSettings.enableParticleEffects | true | Show particle effects at source / destination |
teleportation.generalSettings.enableSoundEffects | true | Play sound effects during teleportation |
teleportation.generalSettings.protectedAreas | [] | World regions where teleportation is blocked (requires a region plugin) |
teleportation.randomTeleportSettings |
teleportation.randomTeleportSettings.defaultLocation | "{world}" | Default named location slot when /tpr is run with no argument. {world} is replaced with the player's current world name. |
teleportation.randomTeleportSettings.defaultMinRange | 0 | Global minimum distance from centre in blocks |
teleportation.randomTeleportSettings.defaultMaxRange | 5000 | Global maximum distance from centre (-1 = half the world border). Every attempt that lands outside already-generated terrain forces a real (potentially costly) chunk generation on the main thread — a smaller range means repeated /tpr uses are more likely to reuse terrain generated by earlier ones, instead of constantly pushing into brand-new territory. Raise this once the surrounding area is mostly pre-generated. |
teleportation.randomTeleportSettings.findAttempts | 6 | Attempts to find a safe random position before giving up. Each attempt that lands on ungenerated terrain force-generates a chunk — keep this modest on servers without pre-generated terrain, since 10 failed attempts in a row means 10 forced generations. |
teleportation.randomTeleportSettings.cacheThreshold | 5 | Minimum pre-computed cached locations to maintain |
teleportation.randomTeleportSettings.prewarmBatchSize | 2 | How many NEW cache slots one /tpr use is allowed to force-generate in the background right after teleporting. Keeping this small (rather than bursting the full gap up to cacheThreshold at once) spreads that cost across several /tpr uses instead of stacking a second lag spike immediately after every teleport. |
teleportation.randomTeleportSettings.cooldown | 60 | Cooldown in seconds between /tpr uses per player (0 = disabled) |
teleportation.randomTeleportSettings.mode | "command" | "command" (default) = /tpr instantly teleports, exactly as before. "gui" = bare /tpr (no location argument) opens a chest-GUI biome picker instead — /tpr <locationName> still bypasses the GUI either way. |
teleportation.randomTeleportSettings.biomeSearchRadius | 6400 | Search radius/step (in blocks) used only by GUI biome-picker teleports — same engine /locate biome uses. Larger radius finds rarer biomes but is slower. |
teleportation.randomTeleportSettings.biomeSearchStep | 32 | — |
teleportation.randomTeleportSettings.biomeMenuItems — GUI-only: pin specific biomes to fixed slots and/or override their icon. slot — 0-44, page-1 slot to pin this biome to (0 = top-left box). Optional — omit to leave the biome auto-positioned (alphabetical, like every other biome) while still overriding just its icon. item — icon item id override. Optional — omit to keep the built-in default icon (that biome's sapling/dedicated block, or a generic fallback if unmapped). Pinned biomes are removed from the auto-listed pool (shown once, at their pinned slot); every unpinned biome — including any this mod doesn't recognize, e.g. from a biome mod — still fills the remaining slots automatically across page 1 and beyond. |
teleportation.randomTeleportSettings.excludedBiomes | [] | Biome resource locations excluded globally (e.g. "minecraft:ocean") |
teleportation.randomTeleportSettings.locations — Named location slots. Update centre in-game with /settpr <name>. |
teleportation.randomTeleportSettings.locations.default |
teleportation.randomTeleportSettings.locations.default.center | { "x": 0, "y": 64, "z": 0, "world": "minecraft:overworld" } | — |
teleportation.randomTeleportSettings.locations.default.minRange | 0 | — |
teleportation.randomTeleportSettings.locations.default.maxRange | 10000 | — |
teleportation.randomTeleportSettings.locations.default.excludedBiomes |
teleportation.backSettings |
teleportation.backSettings.enableDeathBack | true | Save death location so /back returns the player to where they died |
teleportation.backSettings.enableTeleportBack | true | Save pre-teleport location for /back (home / warp / spawn / tpa) |
teleportation.backSettings.enableBackSafety | false | Check destination safety before /back teleport. Off on this server: the check treats unloaded chunks as unsafe, which broke /back after any long-range teleport (origin chunks unload once the player leaves); vanilla teleportTo loads the target chunk itself. |
teleportation.backSettings.teleportDelay | 3 | Warm-up delay for /back in seconds (0 = instant, overrides generalSettings.teleportDelay) |
teleportation.backSettings.backCooldown | 0 | Cooldown between /back uses in seconds (0 = disabled) |
moderation |
moderation.banSettings |
moderation.banSettings.enablePermanentBans | true | — |
moderation.banSettings.enableTempBans | true | — |
moderation.banSettings.enableIPBans | true | — |
moderation.banSettings.maxBanReason | 500 | — |
moderation.banSettings.defaultBanReason | "Banned by an operator" | — |
moderation.banSettings.autoExpireTempBans | true | — |
moderation.banSettings.checkExpiredBansInterval | 300 | Interval in seconds to check for expired temp bans (300 = 5 min, 0 = disabled, min 5) |
moderation.banSettings.logBanActions | true | Log all ban / unban actions |
moderation.banSettings.broadcastBans | false | Broadcast ban actions to online staff |
moderation.banSettings.banMessageFormat | "You have been banned from this server.\nReason: {reason}\nBanned by: {bannedBy}\n{duration}" | — |
moderation.banSettings.tempBanMessageFormat | "You have been temporarily banned from this server.\nReason: {reason}\nBanned by: {bannedBy}\nExpires: {expiry}" | — |
moderation.banSettings.ipBanMessageFormat | "Your IP address has been banned from this server.\nReason: {reason}\nBanned by: {bannedBy}" | — |
moderation.jailSettings |
moderation.jailSettings.enableJailSystem | true | — |
moderation.jailSettings.requireJailLocation | true | Require a jail location to be set before jailing players |
moderation.jailSettings.jailTeleportOnLogin | true | Teleport jailed players back to jail when they reconnect |
moderation.jailSettings.maxJailReason | 500 | — |
moderation.jailSettings.defaultJailReason | "Jailed by an operator" | — |
moderation.jailSettings.jailMessageFormat | "You have been jailed.\nReason: {reason}\nJailed by: {jailedBy}\nJail: {jail}" | — |
moderation.jailSettings.preventJailEscape | true | Prevent jailed players from using teleportation commands |
moderation.jailSettings.logJailActions | true | Log all jail / unjail actions |
moderation.jailSettings.defaultSphereRadius | 10.0 | Default radius (blocks) for sphere-shaped jails when no explicit radius is given |
moderation.jailSettings.maxJailsBeforeTempBan | 3 | Repeat-offender auto-escalation: jailing the same player this many times (tracked per-player, resets after a perm-ban fires) automatically issues a ban instead of the Nth jail. maxJailsBeforePermBan must stay HIGHER than maxJailsBeforeTempBan, or the temp-ban tier never triggers (the perm-ban check runs first). The admin who triggered the auto-ban gets a direct in-game notice when this fires, in addition to the log line. |
moderation.jailSettings.maxJailsBeforePermBan | 6 | — |
moderation.jailSettings.tempBanDurationMinutes | 1440 | Duration (minutes) of the automatic temp-ban issued at the maxJailsBeforeTempBan threshold. Default 1440 = 24 hours. |
moderation.vanishSettings |
moderation.vanishSettings.enableVanishSystem | true | — |
moderation.vanishSettings.vanishOnJoin | false | Auto-vanish staff members when they join |
moderation.vanishSettings.hideFromTabList | true | Hide vanished players from the tab list |
moderation.vanishSettings.preventInteraction | true | Prevent vanished players from interacting with non-staff |
moderation.vanishSettings.broadcastToStaffVanish | false | Broadcast vanish toggles to online staff |
moderation.vanishSettings.BroadcastToAllVanish | false | Broadcast vanish actions to all players (fake join / quit message) |
moderation.vanishSettings.logVanishActions | true | Log vanish toggle actions |
moderation.freezeSettings |
moderation.freezeSettings.enableFreezeSystem | true | — |
moderation.freezeSettings.preventCommands | true | Prevent frozen players from using commands (except those listed in allowedCommands) |
moderation.freezeSettings.allowedCommands | ["help", "rules", "appeal"] | Commands frozen players are still allowed to use |
moderation.freezeSettings.freezeOnLogin | true | Keep players frozen when they reconnect |
moderation.freezeSettings.maxFreezeReason | 500 | — |
moderation.freezeSettings.defaultFreezeReason | "Frozen by an operator" | — |
moderation.freezeSettings.freezeMessage | "You have been frozen by {freezer}.\nReason: {reason}\nYou cannot move or interact until unfrozen." | — |
moderation.freezeSettings.unfreezeMessage | "You have been unfrozen by {unfreezer}" | — |
moderation.freezeSettings.freezeReminder | "You are currently frozen. Contact staff if you need assistance." | — |
moderation.freezeSettings.freezeReminderInterval | 30 | Interval in seconds to remind frozen players (0 = disabled) |
moderation.freezeSettings.logFreezeActions | true | Log all freeze / unfreeze actions |
moderation.kickSettings |
moderation.kickSettings.enableKickSystem | true | — |
moderation.kickSettings.maxKickReason | 500 | — |
moderation.kickSettings.defaultKickReason | "Kicked by an operator" | — |
moderation.kickSettings.broadcastKicks | false | Broadcast kick actions to online staff |
moderation.kickSettings.kickMessage | "You have been kicked from the server.\nReason: {reason}\nKicked by: {kicker}" | — |
moderation.kickSettings.kickAllMessage | "Server maintenance in progress. Please reconnect in a few minutes." | — |
moderation.kickSettings.notifyStaffOnKick | true | Notify online staff when a player is kicked |
moderation.kickSettings.logKickActions | true | Log all kick actions |
moderation.generalSettings |
moderation.generalSettings.staffNotificationPermission | "neoessentials.moderation.notify" | Permission required to receive staff moderation notifications |
chat |
chat.modMessagePrefix | "" | Prefix prepended to NeoEssentials command-feedback (success/error/warning/info) and in-game admin support notices. Accepts & and § color codes. Empty string hides the tag. Restore the old branded tag with "&8[&bNE&8] &r". Not the player chat-format. |
chat.chat-format |
chat.chat-format.default | "<{neoessentials_prefix} {neoessentials_displayname} {neoessentials_suffix}> {MESSAGE}" | — |
chat.chat-format.group:admin | "&c[Admin] {neoessentials_displayname}: {MESSAGE}" | — |
chat.chat-format.group:mod | "&2[Mod] {neoessentials_displayname}: {MESSAGE}" | — |
chat.chat-format.world:creative | "&b[C] {neoessentials_displayname}: {MESSAGE}" | — |
chat.enableChatEnhancements | true | Enable Phase 2 enhancements: clickable names, mentions, URL linking, [item] display |
chat.clickablePlayerNames | true | Make player names in chat clickable (hover for stats, click to message) |
chat.showProfileLinkInChat | true | Append a small clickable link icon after clickable player names in chat that opens their public dashboard profile (/lookup?player=<name>) in a browser. Requires clickablePlayerNames above AND a resolvable dashboard URL — webDashboard.externalDashboard.url (set via /dashboard pair) in "external" mode, or webDashboard.publicUrl in "internal" mode. Silently has no effect if neither URL is configured. |
chat.autoLinkUrls | true | Automatically linkify URLs in chat |
chat.allowItemLinks | true | Allow [item] placeholder to show the held item in chat |
chat.mentions |
chat.mentions.enabled | true | Enable @PlayerName mention system |
chat.mentions.highlightColor | "&e" | Color code applied to highlighted @mentions (e.g. &e = yellow) |
chat.mentions.playSound | true | Play a sound when a player is mentioned |
chat.mentions.soundName | "entity.experience_orb.pickup" | Sound name: entity.experience_orb.pickup, block.note_block.pling, etc. |
chat.mentions.soundVolume | 1.0 | — |
chat.mentions.requirePermission | false | Require 'neoessentials.chat.mention' permission to use @mentions |
chat.mentions.permission | "neoessentials.chat.mention" | — |
chat.badges |
chat.badges.enabled | true | Enable rank badges and status icons in chat |
chat.badges.badgePosition | "before_prefix" | Badge position: 'before_prefix' | 'after_prefix' | 'before_name' | 'after_name' |
chat.badges.useCustomImages | false | NOT FULLY IMPLEMENTED YET — see docs/Wiki/ChatSystem.md#custom-png-badge-images-current-limitations. Generates a resource pack from config/neoessentials/badges/<rank>.png files, but (a) the pack is never actually pushed to players (autoSendResourcePack below doesn't send anything despite the name — you'd have to host it yourself and set server.properties manually) and (b) even then, chat always shows the rankBadges emoji below, never the custom image. Leave this false and use rankBadges (emoji/text) instead — that part fully works today. |
chat.badges.customImageSize | 16 | Badge image size in pixels (16, 24, or 32) — only relevant once useCustomImages actually renders in chat |
chat.badges.customImagePath | "config/neoessentials/badges" | Path to badge images folder relative to server root |
chat.badges.autoSendResourcePack | false | Does NOT auto-send anything yet — only generates the pack + logs manual server.properties setup instructions on join. See the useCustomImages note above. |
chat.badges.requireResourcePack | false | Reserved for when auto-send is implemented — currently unused |
chat.badges.resourcePackUrl | "" | Public URL where the resource pack is hosted, for the manual server.properties setup above. |
chat.badges.resourcePackPrompt | "This server uses custom badge images. Please accept the resource pack for the best experience!" | Reserved for when auto-send is implemented — currently unused |
chat.badges.rankBadges — Emoji/text badge shown per rank (looked up by primary group, lowercased) — this is the part that actually works. A group with no entry, or an empty string, gets no badge. |
chat.badges.rankBadges.owner | "" | — |
chat.badges.rankBadges.admin | "⭐" | — |
chat.badges.rankBadges.moderator | "️" | — |
chat.badges.rankBadges.helper | "" | — |
chat.badges.rankBadges.vip | "" | — |
chat.badges.rankBadges.vipplus | "" | — |
chat.badges.rankBadges.mvp | "" | — |
chat.badges.rankBadges.builder | "" | — |
chat.badges.rankBadges.developer | "" | — |
chat.badges.statusIcons |
chat.badges.statusIcons.enabled | true | Show status icons (AFK, vanished, etc.) in chat |
chat.badges.statusIcons.iconPosition | "after_name" | Position: 'before_name' | 'after_name' | 'after_message' |
chat.badges.statusIcons.afk | "" | — |
chat.badges.statusIcons.vanished | "" | — |
chat.badges.statusIcons.streaming | "" | — |
chat.badges.statusIcons.muted | "" | — |
chat.antiSpam |
chat.antiSpam.enabled | true | Master switch for the anti-spam filter |
chat.antiSpam.capsFilter |
chat.antiSpam.capsFilter.enabled | true | Filter messages with excessive CAPS (shouting) |
chat.antiSpam.capsFilter.maxPercentage | 70 | Maximum percentage of uppercase letters allowed (1–100) |
chat.antiSpam.capsFilter.action | "lowercase" | Action: 'lowercase' | 'block' | 'warn' |
chat.antiSpam.capsFilter.bypassPermission | "neoessentials.chat.caps.bypass" | — |
chat.antiSpam.capsFilter.minimumLength | 5 | Minimum message length to check (avoids flagging short messages like "OK") |
chat.antiSpam.repeatFilter |
chat.antiSpam.repeatFilter.enabled | true | Prevent sending identical messages in quick succession |
chat.antiSpam.repeatFilter.cooldownSeconds | 5 | Seconds before the same message can be sent again |
chat.antiSpam.repeatFilter.action | "block" | Action: 'block' | 'warn' |
chat.antiSpam.repeatFilter.bypassPermission | "neoessentials.chat.repeat.bypass" | — |
chat.antiSpam.linkFilter |
chat.antiSpam.linkFilter.enabled | false | Filter URLs in chat |
chat.antiSpam.linkFilter.action | "allow" | Action: 'allow' (all) | 'block' (all) | 'whitelist' (only listed domains) |
chat.antiSpam.linkFilter.whitelist | ["minecraft.net", "neoforged.net", "github.com"] | — |
chat.antiSpam.linkFilter.bypassPermission | "neoessentials.chat.links.bypass" | — |
chat.antiSpam.spamFilter |
chat.antiSpam.spamFilter.enabled | true | Rate-limit chat to prevent message flooding |
chat.antiSpam.spamFilter.messagesPerPeriod | 5 | Maximum messages per period before blocking |
chat.antiSpam.spamFilter.periodSeconds | 10 | Period length in seconds |
chat.antiSpam.spamFilter.action | "block" | Action: 'block' | 'warn' |
chat.antiSpam.spamFilter.bypassPermission | "neoessentials.chat.spam.bypass" | — |
chat.formatTemplates |
chat.formatTemplates.enabled | false | When true, use 'activeTemplate' instead of 'chat-format' |
chat.formatTemplates.activeTemplate | "default" | Active template: 'default' | 'rpg' | 'modern' | 'minimal' | 'detailed' | 'ranked' | 'custom' |
chat.formatTemplates.templates |
chat.formatTemplates.templates.default | "<{neoessentials_prefix} {neoessentials_displayname} {neoessentials_suffix}> {MESSAGE}" | — |
chat.formatTemplates.templates.rpg | "&7[Lv.{neoessentials_level}] {neoessentials_prefix}{neoessentials_displayname}&r: {MESSAGE}" | — |
chat.formatTemplates.templates.modern | "● {neoessentials_prefix}{neoessentials_displayname} &8› &r{MESSAGE}" | — |
chat.formatTemplates.templates.minimal | "{neoessentials_displayname}: {MESSAGE}" | — |
chat.formatTemplates.templates.detailed | "&7[{neoessentials_world}] &r<{neoessentials_prefix}{neoessentials_displayname}{neoessentials_suffix}&r> {MESSAGE}" | — |
chat.formatTemplates.templates.ranked | "&7[{neoessentials_group}] {neoessentials_prefix}{neoessentials_displayname}&r: {MESSAGE}" | — |
chat.formatTemplates.templates.custom | "<{neoessentials_prefix} {neoessentials_displayname} {neoessentials_suffix}> {MESSAGE}" | — |
chat.richText |
chat.richText.enabled | false | Enable Phase 4 rich-text effects (gradients, rainbow). Can be performance-intensive. |
chat.richText.allowGradients | true | Allow <gradient:FF0000-0000FF>text</gradient> syntax |
chat.richText.allowRainbow | true | Allow <rainbow>text</rainbow> syntax |
chat.conditionalFormatting |
chat.conditionalFormatting.enabled | false | Enable Phase 4 conditional formatting (time / stat / state-based dynamic formats) |
chat.conditionalFormatting.allowTimeConditionals | true | Allow <if:time=morning>…</if> (morning/afternoon/evening/night/day/weekday/weekend) |
chat.conditionalFormatting.allowStatConditionals | true | Allow <if:health<50>…</if> (health/level/food/armor/xp with <, >, =, !=) |
chat.conditionalFormatting.allowStateConditionals | true | Allow <if:afk>…</if> (afk/vanished/flying/creative/survival/spectator/op/…) |
chat.channels |
chat.channels.enabled | true | — |
chat.channels.team |
chat.channels.team.enabled | true | — |
chat.channels.team.command | "team" | — |
chat.channels.team.aliases | ["t", "teamchat"] | — |
chat.channels.team.displayName | "&a⛨ Team" | — |
chat.channels.team.teamBased | true | — |
chat.channels.team.default | false | — |
chat.channels.team.discord |
chat.channels.team.discord.enabled | false | — |
chat.channels.team.discord.channelId | "" | — |
chat.channels.team.discord.webhookUrl | "" | No-bot-required alternative to channelId — a Discord webhook URL (Discord: Server Settings > Integrations > Webhooks). If both are set, both fire. |
chat.channels.local |
chat.channels.local.enabled | true | — |
chat.channels.local.radius | 100 | — |
chat.channels.local.command | "l" | — |
chat.channels.local.aliases | ["local", "lc"] | — |
chat.channels.local.prefix | "" | — |
chat.channels.local.default | true | — |
chat.channels.local.discord |
chat.channels.local.discord.enabled | false | Usually disabled: local chat is proximity-based, discord bridge is global |
chat.channels.local.discord.channelId | "" | Discord channel ID. Leave empty to use the default 'chat' channel. |
chat.channels.local.discord.webhookUrl | "" | — |
chat.channels.global |
chat.channels.global.enabled | true | — |
chat.channels.global.command | "g" | — |
chat.channels.global.aliases | ["global"] | "gc" was previously listed here too, but it collides with the built-in memory/TPS diagnostics command (/gc) — that command wins the registration, so the alias was silently unusable for switching channels. Use /g or /global instead. |
chat.channels.global.prefix | "!" | — |
chat.channels.global.default | false | — |
chat.channels.global.discord |
chat.channels.global.discord.enabled | true | — |
chat.channels.global.discord.channelId | "" | — |
chat.channels.global.discord.webhookUrl | "" | — |
chat.enable-chat-formatting | true | — |
chat.enable-color-codes | true | — |
chat.logChatToConsole | true | Log all chat messages to console/log. false = suppress chat from console entirely. |
chat.muteCommands | [] | Commands blocked when a player is muted |
chat.messaging |
chat.messaging.socialspyFormat | "" | SocialSpy broadcast format. Default: "&8[&eSocialSpy&8] &b{sender} &7→ &b{receiver}&7: &f{message}" |
chat.messaging.msgFormatTo | "" | /msg sender format. Default: "&7[&aTo &f{neoessentials_displayname}&7] &f{message}" |
chat.messaging.msgFormatFrom | "" | /msg receiver format. Default: "&7[&bFrom &f{neoessentials_displayname}&7] &f{message}" |
chat.messaging.replyFormatTo | "" | /reply sender format (blank = use msgFormatTo default) |
chat.messaging.replyFormatFrom | "" | /reply receiver format (blank = use msgFormatFrom default) |
chat.playerChatPermissions | [] | — |
chat.suppressVanillaJoinQuitMessages | false | — |
chat.customJoinMessage | "none" | — |
chat.customQuitMessage | "none" | — |
discordEmbedTemplate |
discordEmbedTemplate.enabled | true | Master switch. false = fall back to a plain "PlayerName: message" line. |
discordEmbedTemplate.authorName | "{player}" | Placeholders available in every field below: {player} - the sender's username {uuid} - the sender's UUID (for building an avatar URL yourself) {message} - the chat message content {channel} - the NeoEssentials chat channel name (e.g. "global") |
discordEmbedTemplate.authorIconUrl | "https://mc-heads.net/avatar/{uuid}" | — |
discordEmbedTemplate.description | "{message}" | — |
discordEmbedTemplate.color | "#5865F2" | Hex color for the embed's side bar, e.g. "#5865F2" (Discord blurple). Leave empty ("") for Discord's default embed color. |
discordEmbedTemplate.footerText | "" | Optional footer text/icon. Leave both empty to omit the footer entirely. |
discordEmbedTemplate.footerIconUrl | "" | — |
discordEmbedTemplate.showTimestamp | false | Show the current time as the embed's timestamp |
discordEmbedTemplate.join — Per-event-type overrides below — same fields as above (any field left out falls back to that event's own built-in default, NOT the chat template above). Only used by SDLink so far, for the same explicit-channel-override case chat's own embed above covers. {message} here means: join/leave - unused; mute/afk - the full built status line; advancement - just the advancement's name. |
discordEmbedTemplate.join.enabled | true | — |
discordEmbedTemplate.join.description | "**{player}** joined the server" | — |
discordEmbedTemplate.join.color | "#57F287" | — |
discordEmbedTemplate.join.showTimestamp | true | — |
discordEmbedTemplate.leave |
discordEmbedTemplate.leave.enabled | true | — |
discordEmbedTemplate.leave.description | "**{player}** left the server" | — |
discordEmbedTemplate.leave.color | "#ED4245" | — |
discordEmbedTemplate.leave.showTimestamp | true | — |
discordEmbedTemplate.mute |
discordEmbedTemplate.mute.enabled | true | — |
discordEmbedTemplate.mute.description | "{message}" | — |
discordEmbedTemplate.mute.color | "#FEE75C" | — |
discordEmbedTemplate.afk |
discordEmbedTemplate.afk.enabled | true | — |
discordEmbedTemplate.afk.description | "{message}" | — |
discordEmbedTemplate.advancement |
discordEmbedTemplate.advancement.enabled | true | — |
discordEmbedTemplate.advancement.description | "**{player}** earned the advancement **{message}**" | — |
discordEmbedTemplate.advancement.color | "#FAA61A" | — |
discordEmbedTemplate.advancement.showTimestamp | true | — |
discordEventChannels |
discordEventChannels.join | { "enabled": false, "channelId": "", "webhookUrl": "" } | — |
discordEventChannels.leave | { "enabled": false, "channelId": "", "webhookUrl": "" } | — |
discordEventChannels.mute | { "enabled": false, "channelId": "", "webhookUrl": "" } | — |
discordEventChannels.afk | { "enabled": false, "channelId": "", "webhookUrl": "" } | — |
discordEventChannels.advancement | { "enabled": false, "channelId": "", "webhookUrl": "" } | — |
discordEventChannels.privateMessage | { "enabled": false, "channelId": "", "webhookUrl": "" } | — |