Farmstead Mods
RU

Moderation

Bans, temporary bans, IP bans, kicks, mutes, jail, vanish and freeze.

On this page

Commands 42#

CommandSyntaxAliasesPermissionDescription
/ban/ban <player> [reason]—neoessentials.moderation.banBan a player<player> — StringArgumentType.word, online first (case-insensitive), otherwise the server's profile cache; offline bans are possible. Without [reason], moderation.banSettings.defaultBanReason is used. Gated by neoessentials.moderation.ban on the root. Banning the same UUID again returns false while the record is active.
/banip/banip <ip> [reason]—neoessentials.moderation.banipBan an IP address<ip> — one word; only an IPv4 of four octets 0–255 is accepted, you cannot pass a name. Kicks everyone online with that address. enableIPBans: false → banIP returns false. Permission neoessentials.moderation.banip. Without a reason — defaultBanReason.
/banlist/banlist [players | ips]—neoessentials.moderation.banlistList banned playersWithout an argument the players branch runs. players archives expired temp bans on read if autoExpireTempBans is on. ips returns the raw ipBans Map without an expiry filter. Permission neoessentials.moderation.banlist.
/clearwarnings/clearwarnings <player>—neoessentials.moderation.warnClear all warnings for a playerErases all of the target's warnings. Permission neoessentials.moderation.warn.
/deljail/deljail <name>—neoessentials.moderation.setjailDelete a jail locationSame permission as setjail. Does not release inmates — only warns how many there were. While the location is missing, canPlayerMove returns true, but isPlayerJailed stays true until /unjail or a login (logging in without a location clears the jail by itself).
/freeze/freeze <player> [reason]—neoessentials.moderation.freezeFreeze a playerOnline only (getPlayerByName). Without a reason — freezeSettings.defaultFreezeReason. Already frozen — error. Writes the freezes collection. Permission neoessentials.moderation.freeze.
/freezeall/freezeall [reason]—neoessentials.moderation.freezeallFreeze all playersThe tree has an optional greedy reason. Does not affect the sender or those already frozen. Permission neoessentials.moderation.freezeall.
/freezelist/freezelist—neoessentials.moderation.freezelistList frozen playersPermission neoessentials.moderation.freezelist.
/history/history <player>—neoessentials.moderation.historyView a player's moderation history (alias)dispatcher.redirect to the modhistory node. Registered only if commands.modhistory is on. The same permission neoessentials.moderation.history.
/jail/jail <player> <jail> [duration_or_reason]—neoessentials.moderation.jailJail a player<jail> — the location name. The tail is greedy, as in /mute: a 30m/1h/… token is the duration, otherwise the whole string is the reason for an indefinite jailing. Offline via the profile cache. Permission neoessentials.moderation.jail. Requires an existing location (and at least one, if requireJailLocation).
/jailfor/jailfor <player> <jail> <duration> [reason]—neoessentials.moderation.jailJail a player for a set duration<duration> is required and must match the same regexp as /jail, otherwise invalid_duration. Access: neoessentials.moderation.jail.timed or neoessentials.moderation.jail (validateAnyPermission; in LuckPerms the parent node does not imply .timed).
/jailinfo/jailinfo [jail]—neoessentials.moderation.jailinfoShow info about a jailWithout a name — all locations; with a name — one plus the number of inmates. The argument is a cell name, not a player. Permission neoessentials.moderation.jailinfo.
/jaillist/jaillist—neoessentials.moderation.jaillistList all jail locationsContrary to the /help catalog, this is a list of jailed players, not locations. Locations — /jailinfo without an argument. Permission neoessentials.moderation.jaillist.
/jails/jails—neoessentials.moderation.jaillistList all jail locations (alias)A separate literal with the same executeJailList as /jaillist (jailed players, not locations). Permission neoessentials.moderation.jaillist. Not a redirect.
/kick/kick <player> [reason]—neoessentials.moderation.kickKick a playerOnline only. You cannot kick yourself. Without [reason] the tree hardcodes "Kicked by an operator", not defaultKickReason from the config. Screen — kickSettings.kickMessage with {reason}/{kicker}. Writes the kicks collection. Permission neoessentials.moderation.kick.
/kickall/kickall [reason]—neoessentials.moderation.kickallKick all playersKicks everyone except the sender. Without a reason the tree hardcodes "Server maintenance"; the screen text is kickAllMessage. Permission neoessentials.moderation.kickall.
/modhistory/modhistory <player>—neoessentials.moderation.historyView a player's full moderation history (bans/mutes/kicks/warns)Online, otherwise profile cache — like PublicModerationEndpoint. Sections for bans, mutes, kicks and warnings, 5 lines each. Shows the reason, issuer, date, whether the record is active and a permanent duration. Permission neoessentials.moderation.history.
/mute/mute <target> [duration_or_reason]—neoessentials.chat.muteMute a player<target> — EntityArgument.player(), online only. The root is gated by neoessentials.chat.mute (the console passes). duration_or_reason is greedy: a first word like 30m/1h/1d/2w is taken as the duration, the rest is the reason; without such a word the whole string is the reason and the mute is permanent. A target with neoessentials.chat.mute.exempt (hasPermissionExplicit) is not muted. A separate silence literal copies this tree; it is not listed on this page.
/mutelist/mutelist—neoessentials.chat.muteList muted playersNo arguments. The root is gated by neoessentials.chat.mute. Expired entries are lazily removed via isMuted. The console is allowed.
/note/note <player> <text>—neoessentials.moderation.noteAdd a staff note to a player's record<text> is required (greedy). The first note for an offline player with no existing notes does not resolve — the profile cache is not consulted. Permission neoessentials.moderation.note.
/notes/notes <player>—neoessentials.moderation.notesView staff notes for a playerUp to 5 records, no pages. Permission neoessentials.moderation.notes (separate from note).
/removenote/removenote <player> <noteId>—neoessentials.moderation.noteRemove a specific note by IDAn 8-character prefix, as with removewarn. Permission neoessentials.moderation.note.
/removewarn/removewarn <player> <warnId>—neoessentials.moderation.warnRemove a specific warning by ID<warnId> — word; an 8-character prefix from /warnings is enough. Permission neoessentials.moderation.warn.
/report/report <player> <reason>—neoessentials.moderation.reportReport a player for staff reviewPlayer only, not the console; you cannot report yourself. Target: online or profile cache. The neoessentials.moderation.report node is granted to everyone by default. Online staff with neoessentials.moderation.reports get an English line in chat; the report is written to reports either way.
/reports/reports—neoessentials.moderation.reportsView the pending report queueThe PENDING queue, up to 8 lines, no pages. Permission neoessentials.moderation.reports.
/reviewreport/reviewreport <id> accept|dismiss [notes]—neoessentials.moderation.reportsAccept or dismiss a player reportThe branches are the literals accept and dismiss, not a free word. <id> is resolved via findById (a short prefix, if the manager searches that way). Statuses REVIEWED / DISMISSED. Permission neoessentials.moderation.reports.
/setjail/setjail <name> [sphere <radius> | cuboid]—neoessentials.moderation.setjailSet jail locationPlayer only. Bare /setjail <name>: WorldEdit cuboid → otherwise a sphere at your feet with jailSettings.defaultSphereRadius. sphere <radius> — Double ≥ 1.0 at the current position. cuboid requires a WE selection. Permission neoessentials.moderation.setjail.
/tempban/tempban <player> <duration> [reason]—neoessentials.moderation.tempbanTemporarily ban a player<duration> — word, not greedy: "30m", "2h", "1d", not "1h 30m". Parsed by BanManager.parseDuration; 0 or an unknown format → invalid_duration. Target as in /ban (online, otherwise cache). Permission neoessentials.moderation.tempban. enableTempBans: false blocks issuing.
/tempbanip/tempbanip <ip> <duration> [reason]—neoessentials.moderation.tempbanipTemporarily ban an IP addressThe same IPv4 filter as /banip, the same word <duration> as /tempban. Kicks online players with that IP. expireTime is stored in ip_bans. Permission neoessentials.moderation.tempbanip.
/togglejail/togglejail <player>—neoessentials.moderation.jailToggle a player's jail stateOnline only. If already jailed — unjail; otherwise jails into getAllJailLocations().getFirst() with the reason "Toggled by staff" and no duration. An empty location list → error. Permission neoessentials.moderation.jail.
/unban/unban <player>—neoessentials.moderation.unbanUnban a playerThe name is looked up in active bans, then in the profile cache. Removes by UUID, writes unbannedBy/unbannedAt; the record stays in the same player_bans collection with active: false. Permission neoessentials.moderation.unban.
/unbanip/unbanip <ip>—neoessentials.moderation.unbanipUnban an IP addressRemoves an active IP ban and archives it with unbannedBy. Completion — the current ip_bans keys. Permission neoessentials.moderation.unbanip.
/unfreeze/unfreeze <player>—neoessentials.moderation.unfreezeUnfreeze a playerLooks in the frozen list first (offline too), otherwise online. Permission neoessentials.moderation.unfreeze.
/unfreezeall/unfreezeall—neoessentials.moderation.unfreezeallUnfreeze all playersUnfreezes everyone in freezes, including offline players. Permission neoessentials.moderation.unfreezeall.
/unjail/unjail <player>—neoessentials.moderation.unjailRelease a player from jailOnline or profile cache. Teleports to originalLocation if it was recorded (online at the time of jailing). Permission neoessentials.moderation.unjail.
/unmute/unmute <target>—neoessentials.chat.muteUnmute a playerAgain EntityArgument.player() — you cannot unmute an offline player by command, although the record lives in mutes. The root is gated by neoessentials.chat.mute. Registration is skipped if chat or commands.unmute is off.
/unvanish/unvanish [player]—neoessentials.moderation.vanishDisable vanish modeForces vanish off. Without an argument — yourself; another player — vanish.others. Root permission neoessentials.moderation.vanish. Target online only.
/v/v [player]—neoessentials.moderation.vanishToggle vanish mode (alias)A full copy of /vanish, not a Brigadier redirect. Registered together with vanish; there is no separate commands.v.
/vanish/vanish [player]—neoessentials.moderation.vanishToggle vanish modeWithout an argument — yourself (player only). Another <player> is gated by neoessentials.moderation.vanish.others; the target must be online. Root — neoessentials.moderation.vanish. A toggle: calling again removes vanish. The state is written to vanishes. /v copies this tree if commands.vanish is on.
/vanishlist/vanishlist—neoessentials.moderation.vanishlistList vanished playersOffline players still in vanishes are shown by UUID. Permission neoessentials.moderation.vanishlist.
/warn/warn <player> [reason]—neoessentials.moderation.warnIssue a warning to a playerWithout a reason — "No reason given.". UUID: online, otherwise existing warns (the profile cache is not used — there is no first warning for an offline player without history). Permission neoessentials.moderation.warn.
/warnings/warnings <player>—neoessentials.moderation.warningsView warnings for a player<player> is required. Prints up to 5 records, no paging. Permission neoessentials.moderation.warnings.

Examples#

Block the IP, not the name, and check the duration#

An alt on the same address must not get in after the main account is banned. You need both a permanent and a temporary IP ban.

/banip 203.0.113.10 griefing
/banlist ips
/tempbanip 203.0.113.20 2h proxy
/unbanip 203.0.113.10

/banip and /tempbanip take an address, not a name: "Steve" fails isValidIP (exactly 4 octets 0–255). Everyone online from 203.0.113.10 is disconnected immediately with the ipBanMessageFormat template. The record lives in the ip_bans collection of the same storage.type as the rest of the mod; the web panel writes there too via POST /api/moderation/ipban. A temporary ban stores expireTime: isIPBanned on login and the scheduler every checkExpiredBansInterval seconds (300 by default), with autoExpireTempBans: true, archive it with unbannedBy = null. /banlist ips does not print the expiry in the line — unlike /banlist players.

Temporary player ban and shared history with the panel#

Issue 30 minutes, make sure the player can join after it expires and the record was not erased — and that the panel shows the same as the game.

/tempban Steve 30m cheating
/banlist
/modhistory Steve
/unban Steve

Steve is kicked with tempBanMessageFormat ({reason}, {bannedBy}, {expiry}). The UUID resolves online or from the cache — an offline tempban works if the player has ever joined. /banlist without an argument = players and archives expired entries on read. /modhistory reads BanManager.getBanHistory + MuteManager + KickManager + WarnManager — the same collections as GET /api/moderation/bans/{uuid} and the public lookup. /unban does not delete the document: active: false, unbannedBy/unbannedAt are filled in. A repeated /ban of the same UUID while the ban is active does not stack on top.

Jail for a duration and tell /jail from /jailfor#

A cell at spawn, Steve for two hours, Alex strictly via a separate command. On expiry — automatic release without /unjail.

/setjail spawn
/jail Steve spawn 2h griefing
/jailfor Alex spawn 30m
/jaillist
/jailinfo spawn

/setjail spawn without a tail places a sphere of radius defaultSphereRadius (10.0) at your feet if there is no wand/WE selection. /jail's tail is greedy: the word 2h matched the duration regexp — a timed jailing, expireAt = now+2h, reason griefing. The tree has no /jailfor without duration. Once a second (20 ticks) and on login, checkJailTimeout releases expired inmates and writes jail.released_expired. /jaillist prints inmates; cell coordinates — /jailinfo. The maxJailsBeforeTempBan/PermBan counter (3 and 6 in the template) lives only in process memory: after a restart escalation starts from zero; the third jail in the same session brings auto_tempban_notice, the sixth a permban instead of jailing.

Vanish survives a rejoin; "see vanished" does not#

Hide, leave, join again — stay invisible. Understand why a colleague without a separate tier cannot see you even with OP.

/vanish
/vanishlist
/unvanish

The UUID and the priority number are written to the vanishes collection and loaded at startup. onPlayerLeave does not clear the state; on join, hide packets are sent again after 1 tick. vanishOnJoin is a separate flag: with true anyone with neoessentials.moderation.vanish is vanished automatically, even if they were not hidden before (false in the template). Who sees vanished players: the node neoessentials.vanish.priority. from the series 1000, 500, 250, 100, 50, 25, 10, 5, 1, checked with hasPermissionStrict — OP and a bare neoessentials.* give no tier. An equal or higher tier sees a lower one; tier 0 sees nobody. The viewerPriorities map (session "see vanished") is not written to DataStore and no command fills it: there is no /vanish see literal in the tree.

An hour-long mute in game — and why IP mutes are panel-only#

Mute an online offender for a duration so that /mutelist, /modhistory and the panel show a single record. Understand the command's limits compared to the panel.

/mute Steve 1h spam in chat
/mutelist
/modhistory Steve
/unmute Steve

Steve must be online: EntityArgument.player() does not accept offline players, although MuteManager keys by lowercase name and survives restarts (the mutes collection). 1h is taken as the duration, spam in chat is the reason; the target immediately gets target_notification. Chat, /msg and mail are blocked by isMuted by name. The panel's POST /api/moderation/mute hits the same MuteManager (duration there is in seconds, not "1h"). IP mute — only POST /api/moderation/ipmute → the ip_mutes collection: there is no in-game command, and ChatMuteGuard does not call isIPMuted, so an IP mute by itself does not silence chat. /unmute again requires an online target.

Edge cases#

One punishment store: game and panel#

BanManager, MuteManager, KickManager, WarnManager, NoteManager, ReportManager, JailManager, FreezeManager, VanishManager write to the collections player_bans, ip_bans, mutes, ip_mutes, kicks, warns, notes, reports, jails, jail_locations, freezes, vanishes of the active storage.type. ModerationEndpoint and PublicModerationEndpoint call the same methods as the commands, not a separate table. The exception is time units: the panel body passes duration in seconds (durationSeconds * 1000), the game uses 30m/2h tokens. duration: -1 in POST /api/moderation/ban = a permanent ban.

What to do: After banning from the panel check /banlist and /modhistory <player> — it is not "another database". Do not confuse API seconds with command suffixes.

Ban duration: what removes it by itself#

expireTime > 0 && now > expireTime — expired. For players, /banlist (players), isPlayerBanned on login and the checkExpiredBansInterval scheduler archive the record (unbannedBy empty). For IPs the scheduler and isIPBanned on login do the same, but /banlist ips returns the raw map and may show an already dead temp ban until the next cleanup tick. autoExpireTempBans: false leaves the key in the map, the checks return "not banned", and there is no archive. parseDuration understands s/m/h/d/w/mo/y; for /tempban* the argument is a word, so "1h 30m" with a space does not fit the tree; "1h30m" as one word becomes 130 minutes (the digits are concatenated and the hm suffix falls to the default = minutes).

What to do: For a compound duration write one word with a single unit, or several separated by commas without the argument-separating space. Do not expect /banlist ips to hide expired entries instantly — check on login or wait for the interval.

/mute, /unmute, /mutelist are node-gated and work on online players only#

The root of all three commands is gated by neoessentials.chat.mute: without a grant they are not in the tree or in tab-complete (the console passes). <target> is EntityArgument.player(); an offline player can be neither muted nor unmuted, although the record in mutes survives restarts. /mute is always registered (plus the silence literal); /unmute and /mutelist are not attached if chat or their flag in commands is off. The duration in the first greedy word: the regexp has no mo/y, so /mute Steve 1mo takes 1mo as the reason, not a month.

What to do: Grant moderators neoessentials.chat.mute. Offline mute — POST /api/moderation/mute by name.

Vanish is in vanishes; viewer priority is session-only and has no command#

The vanished UUID+priority are persisted. viewerPriorities ("see vanished" mode) is deliberately not written and not migrated from the legacy file. enableSeeVanished / toggleSeeVanished exist in the manager, but nothing in Brigadier calls them — there is no /vanish see. Actual viewing: neoessentials.vanish.priority.<tier> via hasPermissionStrict (no OP bypass, no bare neoessentials.*). Tier 0 does not see vanished players. vanishOnJoin vanishes staff with neoessentials.moderation.vanish on join; this is not the same as restoring an already recorded vanishes entry.

What to do: Give staff who must see colleagues a specific neoessentials.vanish.priority.50 (or higher than the target). Do not count on OP by itself seeing vanished players.

Jail duration and auto-escalation#

expireAt is in the jails collection. Checked every second for online players and on login; an offline player stays jailed until they join, even if the time is up, until checkJailTimeout runs. /jail <p> <jail> 2h reason and /jailfor write the same path. The repeat-jailing counter (jailCounts) is not serialized: /neoe reload/a restart resets it, but within an uptime the 3rd jailing (template maxJailsBeforeTempBan) gives a temp ban of tempBanDurationMinutes (1440), the 6th a permanent ban by System / "Exceeded maximum jailings"; no jailing is created and the caller gets auto_*ban_notice. The perm check runs first: if both thresholds are equal, the temp branch is dead.

What to do: Keep maxJailsBeforePermBan strictly above temp. When testing /jail on a single account, either raise the thresholds or restart to reset the counter.

/jaillist is not a list of cells; /deljail does not release#

executeJailList prints getAllJailedPlayers(). Locations — /jailinfo without an argument. /jails — the same list of inmates. /deljail deletes from jail_locations, inmates stay in jails: movement no longer returns them to the cell (canPlayerMove is true if there is no location), breaking/attacking are still blocked by isPlayerJailed. On the next login without a location the player is released automatically.

What to do: Before removing a cell go through /jaillist and /unjail. Check cell coordinates with /jailinfo, not /jaillist.

Who resolves offline and who does not#

/ban//tempban//jail//report//modhistory — online, then the profile cache. /warn//note — online, then only existing warns/notes: there will be no first warning or note for someone who is not in game and has no history, even if they are in the cache. /freeze//vanish//kick//mute//togglejail — online only. /unfreeze checks the freeze list first (offline players can be unfrozen).

What to do: Issue the first /warn//note while the target is in game, or straight through the panel (it resolves the name by its own rules).

/banip accepts neither a name nor IPv6#

The in-game isValidIP accepts only dotted IPv4. The panel also lets IPv6 through before BanManager/MuteManager. You cannot ban a "player's IP" by passing a name to /banip: you get invalid_ip. Kicking by IP compares the getPlayerIP string as is.

What to do: Take the address from the login log or the panel. IPv6 bans — only via dashboard /api/moderation/ipban.

A frozen player cannot chat; vanish silences footsteps#

ChatHandler cancels chat if FreezeManager.isPlayerFrozen. Vanish sets setSilent(true) — neighbours do not hear footsteps. Freeze survives restarts (freezes) and sends a reminder on join; the freeze position is filled in if it was empty.

What to do: Nothing to fix; if a player "cannot chat" after /freeze, that is by design — do not confuse it with a mute.

Known issues#

An IP mute from the panel does not block chat#

MuteManager.muteIP / the ip_mutes collection / the /api/moderation/ipmute routes exist, and isIPMuted is declared. ChatMuteGuard and ChatHandler check only isMuted by player name; there are no other isIPMuted calls in the mod. There is no in-game IP mute command either. A record appears in storage, while chat, /msg and mail work as usual.

What to do: Mute the name via /mute or POST /api/moderation/mute. An IP ban (/banip) still keeps the player off the server — that is a different mechanism.

The staff ping for /report is not localized#

/modhistory uses localized strings and a calm format with the reason, issuer and date. After /report, online players with neoessentials.moderation.reports still get the raw line [Report] <nick> reported <nick>: <reason>, bypassing lang.

What to do: View punishment history with /modhistory <player>. For pings about new reports use the panel if you need a Russian-language interface.

Permissions 41#

NodeIn registryWhat it grants
neoessentials.jail.allow-attackregistry: noAttack entities while jailed
neoessentials.jail.allow-breakregistry: noBreak blocks while jailed
neoessentials.jail.allow-interactregistry: noInteract with blocks/items while jailed
neoessentials.jail.allow-placeregistry: noPlace blocks while jailed
neoessentials.jail.bypassregistry: noBuild/break inside jail cells (maintenance)
neoessentials.moderation.banregistry: noBan players
neoessentials.moderation.banipregistry: noBan IP addresses
neoessentials.moderation.banlistregistry: noView ban list
neoessentials.moderation.clearwarningsregistry: noClear all warnings for a player
neoessentials.moderation.deljailregistry: noDelete jail locations
neoessentials.moderation.freezeregistry: noFreeze players
neoessentials.moderation.freezeallregistry: noFreeze all players
neoessentials.moderation.freezelistregistry: noView frozen players list
neoessentials.moderation.jailregistry: noJail players, indefinitely or for a set duration (/jail, /jailfor)
neoessentials.moderation.jail.timedregistry: noJail players for a set duration (/jailfor) - neoessentials.moderation.jail grants this too
neoessentials.moderation.jailinforegistry: noView jail location info
neoessentials.moderation.jaillistregistry: noView jailed players
neoessentials.moderation.kickregistry: noKick players
neoessentials.moderation.kickallregistry: noKick all players
neoessentials.moderation.noteregistry: noAdd/remove staff notes on a player (/note, /removenote)
neoessentials.moderation.notesregistry: noView a player's staff notes (/notes)
neoessentials.moderation.notificationsregistry: noReceive moderation event broadcasts
neoessentials.moderation.notifyregistry: noReceive moderation notifications
neoessentials.moderation.reportregistry: yesReport another player (/report)
neoessentials.moderation.reportsregistry: noView and resolve the report queue (/reports, /reviewreport)
neoessentials.moderation.seevanishedregistry: noSee vanished players
neoessentials.moderation.setjailregistry: noCreate jail locations
neoessentials.moderation.stafflogregistry: noReceive the private in-game moderation log
neoessentials.moderation.tempbanregistry: noTemporarily ban players
neoessentials.moderation.tempbanipregistry: noTemporarily ban an IP address
neoessentials.moderation.togglejailregistry: noToggle a player's jail state
neoessentials.moderation.unbanregistry: noUnban players
neoessentials.moderation.unbanipregistry: noUnban IP addresses
neoessentials.moderation.unfreezeregistry: noUnfreeze players
neoessentials.moderation.unfreezeallregistry: noUnfreeze all players
neoessentials.moderation.unjailregistry: noUnjail players
neoessentials.moderation.vanishregistry: noVanish self
neoessentials.moderation.vanish.othersregistry: noVanish other players
neoessentials.moderation.vanishlistregistry: noView vanished players list
neoessentials.moderation.warnregistry: noIssue warnings to players (/warn)
neoessentials.moderation.warningsregistry: noView player warning history (/warnings)

Detailed guide#

The section below is the project's original documentation (docs/Wiki/ModerationSystem.md). Links to other wiki pages are rewritten to this site; the guides themselves are not edited, so upstream syncs stay conflict-free.

Version: 1.0.5+build.54 · Config: config.json → moderation / storage sections


Overview#

Comprehensive player moderation — ban, temp-ban, IP ban, kick, mute (with IP mutes), jail (timed), freeze, vanish, warnings, staff notes, and player reports — all with persistent storage, full history/audit trails, permission integration, and event enforcement.

Bans, mutes, kicks, warnings, notes, and reports are backed by a single canonical store per feature (see Storage Backend below) — there is exactly one code path that enforces each punishment, and the Web Dashboard's moderation API reads and writes through the same managers, so in-game commands and dashboard actions always agree.


Bans#

Commands#

Command Syntax Permission Description
/ban /ban <player> [reason] neoessentials.moderation.ban Permanently ban a player
/tempban /tempban <player> <duration> [reason] neoessentials.moderation.tempban Temporarily ban (e.g. 30m, 2h, 1d)
/unban /unban <player> neoessentials.moderation.unban Unban a player
/banip /banip <ip> [reason] neoessentials.moderation.banip Ban an IP address (takes the IP directly, not a player name)
/tempbanip /tempbanip <ip> <duration> [reason] neoessentials.moderation.tempbanip Temporarily ban an IP
/unbanip /unbanip <ip> neoessentials.moderation.unbanip Unban an IP
/banlist /banlist [players\|ips] neoessentials.moderation.banlist View active bans (defaults to players)

Duration format: 30s · 5m · 2h · 1d · 1w

History & Audit Trail#

Every ban (player and IP) is stored with a unique ID, an active flag, optional evidence, and — once lifted — who unbanned it and when (unbannedBy / unbannedAt). Expired temp-bans are archived the same way (auto-marked inactive, no "unbanned by" staff member). Unbanning and re-banning a player never destroys their prior ban records; they remain queryable as history via the dashboard's /api/moderation/bans/{uuid} and /api/moderation/ipbans routes (see Web Dashboard).

Moderation History#

Command Syntax Permission Description
/modhistory /modhistory <player> neoessentials.moderation.history View a player's full moderation history — bans, mutes, kicks, and warns — in one summary
/history alias for /modhistory same Alias

Kicks#

Command Syntax Permission Description
/kick /kick <player> [reason] neoessentials.moderation.kick Kick a player
/kickall /kickall [reason] neoessentials.moderation.kickall Kick all players

Every kick (including dashboard-initiated kicks) is recorded with a timestamp, reason, and issuing staff member, and is queryable as history via the dashboard's /api/moderation/kicks / /api/moderation/kicks/{name} routes — there is no in-game command to view kick history.


Mutes#

Command Syntax Permission Description
/mute /mute <player> [reason] neoessentials.chat.mute Mute a player (indefinite)
/silence alias for /mute same Alias
/unmute /unmute <player> neoessentials.chat.mute Unmute a player
/mutelist /mutelist neoessentials.chat.mute List muted players

Muted players cannot chat, send private messages, or send mail. The mute system is implemented in the chat module (com.zerog.neoessentials.chat), not the moderation module — all three commands share the single neoessentials.chat.mute permission (there's no separate exempt/list/unmute node), plus neoessentials.chat.mute.exempt to make a player un-mutable.

⚠️ Unlike every other moderation command, /mute//unmute//mutelist have no root permission gate at registration — neoessentials.chat.mute is only checked deep inside the command body, not at the point Brigadier registers the command. This means all three are visible to every player in /help and can be attempted by anyone, though the body-level check should still reject an unauthorized caller — worth verifying directly if you rely on this restriction, rather than assuming registration-time enforcement like most other commands.

Like bans, every mute tracks reason, issuing staff member, an active flag, and — once lifted — unmutedBy / unmutedAt, with full history preserved. IP mutes are also supported (mute an IP directly rather than a player name) — currently exposed via the dashboard's /api/moderation/ipmute / /api/moderation/ipmutes routes rather than an in-game command.


Jail#

Jail teleports the player to a set jail location and blocks movement, interaction, combat, and teleport until released.

Commands#

Command Syntax Permission Description
/jail /jail <player> <jail> [duration] [reason] neoessentials.moderation.jail Jail permanently or for a set duration
/jailfor /jailfor <player> <jail> <duration> [reason] neoessentials.moderation.jail.timed or neoessentials.moderation.jail Jail for a set duration
/unjail /unjail <player> neoessentials.moderation.unjail Release a player from jail
/setjail /setjail <name> (auto-detect shape) · /setjail <name> sphere <radius> · /setjail <name> cuboid neoessentials.moderation.setjail Create a jail location — see Jail Region Shapes below
/deljail /deljail <name> neoessentials.moderation.setjail Delete a jail location (same permission as /setjail)
/jailwand /jailwand neoessentials.jail.wand Give yourself the jail-region selection wand
/jaillist /jaillist neoessentials.moderation.jaillist List all jail locations
/jailinfo /jailinfo [name] neoessentials.moderation.jailinfo Show info for one jail, or all jails if no name given
/jails alias for /jaillist same Alias
/togglejail /togglejail <player> neoessentials.moderation.jail Toggle jail on/off for a player

Jail Region Shapes#

A jail location can be either a sphere (radius around a point) or a cuboid (two-corner box):

  • /setjail <name> — auto-detects: uses a wand or WorldEdit cuboid selection if one is active, otherwise falls back to a sphere at your current position using moderation.jailSettings.defaultSphereRadius.
  • /setjail <name> sphere <radius> — explicit sphere at your current position.
  • /setjail <name> cuboid — cuboid from the current wand/WorldEdit selection.
  • /jailwand gives an item (configurable via moderation.jailSettings.wandItem) — right-click sets corner 1, left-click sets corner 2, then run /setjail <name> cuboid.

Jail Enforcement#

While jailed, the following are blocked: - Movement outside jail radius - Teleport commands (redirected back to jail on respawn too) - Breaking/placing blocks (unless neoessentials.jail.allow-break / allow-place) - Interactions (unless neoessentials.jail.allow-interact) - Attacking entities (unless neoessentials.jail.allow-attack)

Timed jails auto-release when the duration expires (checked every second and on login). Durations use s, m, h, d, or w, for example /jail Steve spawn-jail 2h griefing.


Freeze#

Command Syntax Permission Description
/freeze /freeze <player> [reason] neoessentials.moderation.freeze Freeze a player in place
/unfreeze /unfreeze <player> neoessentials.moderation.unfreeze Unfreeze a player
/freezeall /freezeall neoessentials.moderation.freezeall Freeze all online players
/unfreezeall /unfreezeall neoessentials.moderation.unfreezeall Unfreeze all players
/freezelist /freezelist neoessentials.moderation.freezelist List frozen players

Vanish#

Command Syntax Permission Description
/vanish /vanish [player] neoessentials.moderation.vanish (self) + neoessentials.moderation.vanish.others (targeting another player) Toggle vanish for yourself or another
/v alias same Alias
/unvanish /unvanish [player] same as above Force-disable vanish
/vanishlist /vanishlist neoessentials.moderation.vanishlist List vanished players

Broadcasting vanish toggles to staff/everyone and console logging are all config-driven (moderation.vanishSettings.broadcastToStaffVanish, etc. — see below).


Warnings#

Command Syntax Permission Description
/warn /warn <player> [reason] neoessentials.moderation.warn Issue a warning to a player
/warnings /warnings <player> neoessentials.moderation.warnings View a player's warnings and total count
/clearwarnings /clearwarnings <player> neoessentials.moderation.warn Clear all warnings for a player
/removewarn /removewarn <player> <warnId> neoessentials.moderation.warn Remove a single warning by its ID (accepts the short 8-char ID prefix)

Warnings persist for offline players and are shown with a truncated ID, timestamp, reason, and issuing staff member.


Staff Notes#

Freeform notes staff can leave on a player's record — for context that isn't a punishment (e.g. "watch this player, borderline behavior last week").

Command Syntax Permission Description
/note /note <player> <text> neoessentials.moderation.note Add a note to a player's record
/notes /notes <player> neoessentials.moderation.notes View a player's notes (paginated, 5 per page)
/removenote /removenote <player> <noteId> neoessentials.moderation.note Remove a note by ID (accepts the short 8-char prefix)

Notes persist for offline players and record author, timestamp, and text. Also available via the dashboard's /api/moderation/notes/{name} and /api/moderation/note routes.


Player Reports#

Lets players flag misbehavior even while no staff are online — reports persist and show up in the review queue whenever staff next check.

Command Syntax Permission Description
/report /report <player> <reason> neoessentials.moderation.report Report a player (default: granted to everyone)
/reports /reports neoessentials.moderation.reports Staff: view the pending review queue (8 per page)
/reviewreport /reviewreport <id> <accept\|dismiss> [notes] neoessentials.moderation.reports Staff: resolve a report, optionally with review notes

Submitting a report also immediately notifies any online staff with neoessentials.moderation.reports, in addition to persisting for later review. Reports track reporter, target, reason, timestamp, and status (PENDING / REVIEWED / DISMISSED) plus who reviewed it and when. Also available via the dashboard's /api/moderation/reports, /api/moderation/reports/all, /api/moderation/reports/{id}, and /api/moderation/reports/{id}/review routes.


Data Files & Storage Backend#

Bans, mutes (including IP mutes), kicks, warnings, notes, and reports are persisted through a pluggable DataStore abstraction rather than bespoke JSON files — configured under config.json → storage:

"storage": {
  "type": "json",
  "autoMigrate": true,
  "sqlite": { "file": "data.db" },
  "mysql": { "host": "localhost", "port": 3306, "database": "neoessentials", "username": "neoessentials", "password": "", "useSSL": false, "poolSize": 10 }
}
Key Default Description
type "json" Backend to use: json, yaml, sqlite, or mysql
autoMigrate true On first boot with an empty store, import each manager's existing legacy JSON data automatically and losslessly
sqlite.file "data.db" SQLite database filename (under neoessentials/store/)
mysql.* — Connection details for a shared MySQL database — point every server in a network at the same database to share bans/mutes/etc. in real time

Each punishment type is one collection (a schema-less table of JSON documents keyed by ID):

Collection Contents
player_bans Player bans — active and historical, with unban audit trail
ip_bans IP bans — active and historical, with unban audit trail
mutes Player mutes — active and historical, with unmute audit trail
ip_mutes IP mutes — active and historical
kicks Kick history
warns Warnings
notes Staff notes
reports Player reports
jails / jail_locations Active jail state / named jail locations
freezes / vanishes Frozen player state / vanish state

With the default json backend, collections live at neoessentials/store/<collection>.json. With yaml, neoessentials/store/<collection>.yml. With sqlite, all collections live as tables in neoessentials/store/data.db. With mysql, all collections live as tables in the configured database. If MySQL is unreachable at boot, the mod automatically falls back to the JSON backend rather than failing to start.

As of this release, storage.type covers the entire mod, not just moderation — economy, homes/warps/spawn, kits, chat (AFK/ignore/chat-format), holograms, shops, permissions (including group inheritance), the dashboard's own accounts, and the Auction House are all backed by the same DataStore system now. See Storage Backend for the complete collection list and per-system breakdown.


Config (config.json → moderation)#

Settings are nested under per-feature sub-objects, not flat keys directly under moderation.

moderation.banSettings#

Key Default Description
broadcastBans false Announce bans to all players
logBanActions — Log ban details to console
defaultBanReason (built-in default) Reason used when none is given
maxBanReason — Max reason length
enableIPBans — Enable/disable IP bans
enablePermanentBans — Enable/disable permanent (non-timed) bans
enableTempBans — Enable/disable temp bans
autoExpireTempBans — Automatically lift temp bans when they expire
checkExpiredBansInterval — How often (seconds) to check for expired temp bans
banMessageFormat / tempBanMessageFormat / ipBanMessageFormat — Disconnect screen message templates

moderation.kickSettings#

Key Default Description
enableKickSystem true Enable/disable the kick system
broadcastKicks false Announce kicks to all players
logKickActions true Log kick details to console
notifyStaffOnKick true Notify staff (players with neoessentials.moderation.notifications) on kick, independent of broadcastKicks
kickMessage "You have been kicked from the server.\nReason: {reason}\nKicked by: {kicker}" Default kick screen message
kickAllMessage "Server maintenance in progress. Please reconnect in a few minutes." /kickall screen message
defaultKickReason "Kicked by an operator" Reason used when none is given
maxKickReason 500 Max reason length

moderation.freezeSettings#

Key Default Description
enableFreezeSystem true Enable/disable the freeze system
defaultFreezeReason "Frozen by an operator" Reason used when none is given
maxFreezeReason 500 Max reason length
freezeMessage / unfreezeMessage — Message templates sent to the frozen/unfrozen player ({reason}, {freezer} / {unfreezer})
freezeReminder — Periodic reminder message shown while frozen
freezeReminderInterval 30 Seconds between freeze reminders
logFreezeActions true Log freeze/unfreeze to console
freezeOnLogin true Re-apply freeze if a frozen player logs back in
preventCommands true Block command use while frozen
allowedCommands [] Commands still allowed while frozen

moderation.vanishSettings#

Key Default Description
enableVanishSystem — Enable/disable the vanish system
preventInteraction true Block interactions while vanished
broadcastToStaffVanish false Announce vanish toggles to staff
BroadcastToAllVanish — Announce vanish toggles to all players (note the config's mixed-case key)
hideFromTabList — Hide vanished players from the tab list
vanishOnJoin — Re-apply vanish if a vanished player logs back in
logVanishActions — Log vanish/unvanish to console

moderation.jailSettings#

Key Default Description
defaultJailReason — Reason used for /jail when none is given
logJailActions — Log jail/unjail to console
preventJailEscape — Block movement out of the jail region
jailMessageFormat — Message template shown to the jailed player
wandItem — Item ID used as the jail-region selection wand (given by /jailwand)
defaultSphereRadius — Radius used by /setjail <name> auto-detect and /setjail <name> sphere when no explicit radius is given
maxJailsBeforeTempBan — Number of times a player can be jailed before an automatic temp-ban escalation

Notes & Reports Permissions#

Node Default Description
neoessentials.moderation.note 🔒 Add/remove staff notes (/note, /removenote)
neoessentials.moderation.notes 🔒 View a player's staff notes (/notes)
neoessentials.moderation.report ✅ granted Submit a player report (/report)
neoessentials.moderation.reports 🔒 View and review the report queue (/reports, /reviewreport)

Back to Wiki Home