EasySpec is a lightweight, server-side-only Fabric mod that lets players toggle Spectator Mode instantly by typing a configurable trigger word in chat. It also provides a full command system (/easyspec) for administrators to manage configuration at runtime. No client-side installation required — just type and go.
⚡ Type
!s(configurable) in chat to enter spectator mode. Type it again to return to exactly where you were.
🤖 AI-Generated Notice: This mod's source code is entirely generated by artificial intelligence (specifically Claude, an Anthropic AI assistant). It serves as a practical exploration of AI-assisted Minecraft mod development. While every effort has been made to ensure correctness, the code may contain patterns or decisions that differ from traditional handwritten mods. Use at your own discretion.
- One-key toggle — Type
!s(or your custom trigger) to switch to spectator; type it again to restore. - Full state preservation — Your game mode (survival/creative/adventure), position (x/y/z), rotation (yaw/pitch), and dimension are all saved and restored.
- Survives server restarts — Player states are persisted to the world save via Minecraft's
SavedDatasystem. Restart the server, and toggling back still works perfectly. - Per-world scoping — Data is stored per world save file, not globally. Different worlds have independent state tracking.
- Fully server-side — No client mod needed. Works with vanilla clients.
- Silent trigger — The trigger message is intercepted and never broadcast to other players. Can be disabled via
hideTrigger: false. - Multilingual — 9 languages supported; messages show the actual trigger word you configured.
- Config auto-repair — Missing or invalid config fields are automatically reset with a warning, keeping your settings intact.
- ModMenu support — Description translation key included for ModMenu compatibility.
- Thread-safe — Safe for use with chat plugins and proxy environments (Velocity, BungeeCord).
- Runtime configuration — Change any config option on the fly with
/easyspec set, no server restart needed. - LuckPerms integration — Permission nodes
easyspec.commandandeasyspec.triggerfor fine-grained control via LP. Config-based permission levels fall back automatically when no permission mod is present. - Dual permission control — Separate permission levels for
/easyspeccommands (permissionLevel) and trigger word (triggerPermissionLevel). - Modular config system — Refactored configuration with
ConfigKeydescriptors; adding new options requires only one constant.
- Player types
!s(or configured trigger) in chat. - The server intercepts the message, cancels it (other players don't see it), and saves the player's current state.
- Player is switched to spectator mode.
- Typing
!sagain restores the saved state — game mode, position, rotation, and dimension.
The whole mod runs on the server thread via server.execute(...), so it's safe with Netty-based chat handling.
Persistence: Player states are saved to
world/data/easyspec-player-states.datvia Minecraft'sSavedDatasystem. This means toggling back works correctly even after a server restart — the original game mode, position, and dimension are never lost.
- Install Fabric Loader (≥0.19.2) on your server.
- Drop the
easyspec-2.0.0+1.20.1.jarinto your server'smods/folder. - Restart the server. That's it — clients need nothing.
| Dependency | Version | Required |
|---|---|---|
| Fabric Loader | ≥0.19.2 | ✅ |
| Fabric API | ≥0.92.11 | ✅ |
| LuckPerms | any | ❌ (optional) |
| ModMenu | any | ❌ (optional) |
The config file is located at config/easyspec.json in your server's root directory. It is automatically created on first run.
{
"_comment1": "Language: en_us, zh_cn, ja_jp, ko_kr, fr_fr, de_de, es_es, ru_ru, pt_br",
"language": "en_us",
"_comment2": "Trigger word: type '!' + this in chat to toggle spectator. Default: s (i.e. !s)",
"trigger": "s",
"_comment3": "Hide the trigger message from chat (default: false). Set true to hide it so other players don't see it in chat.",
"hideTrigger": false,
"_comment4": "--- Permission: /easyspec command (permission node: easyspec.command) ---",
"_comment4a": "Without LuckPerms: vanilla operator level 0-4. Default 2 (operator), 0 = all players.",
"_comment4b": "With LuckPerms: this value is IGNORED. Use '/lp group <group> permission set easyspec.command true' instead.",
"permissionLevel": 2,
"_comment5": "--- Permission: !s trigger word (permission node: easyspec.trigger) ---",
"_comment5a": "Without LuckPerms: vanilla operator level 0-4. Default 0 (all players), 2+ = operators only.",
"_comment5b": "With LuckPerms: this value is IGNORED. Use '/lp group <group> permission set easyspec.trigger true' instead.",
"triggerPermissionLevel": 0
}| Field | Type | Default | Description |
|---|---|---|---|
language |
string | "en_us" |
Language for feedback messages. See supported languages below. |
trigger |
string | "s" |
The word after ! used to toggle. E.g. "spec" → type !spec. Matching is case-sensitive. |
hideTrigger |
boolean | false |
Whether to hide the trigger message from chat. Set true to hide it. |
permissionLevel |
integer | 2 |
Required permission level (0–4) for /easyspec commands. Ignored when LuckPerms is installed. |
triggerPermissionLevel |
integer | 0 |
Required permission level (0–4) for using the trigger word. Ignored when LuckPerms is installed. |
With LuckPerms: Use
/lp group <group> permission set easyspec.command trueand/lp group <group> permission set easyspec.trigger trueinstead. The mod will warn you when adjusting these values via/easyspec setif LP is active.
Tip: The messages shown to players always reflect the actual trigger configured. For example, if
triggeris set to"spec", your players will see "Type !spec to toggle."
| Code | Language |
|---|---|
en_us |
English (US) |
zh_cn |
简体中文 (Chinese Simplified) |
ja_jp |
日本語 (Japanese) |
ko_kr |
한국어 (Korean) |
fr_fr |
Français (French) |
de_de |
Deutsch (German) |
es_es |
Español (Spanish) |
ru_ru |
Русский (Russian) |
pt_br |
Português (Brazilian Portuguese) |
- Join your server.
- Type
!s(or your configured trigger) in chat. - You are now in spectator mode — fly through walls, observe players, explore freely.
- Type
!sagain to return to your original position and game mode.
Trigger permission: Controlled by
triggerPermissionLevel(default 0 — all players). With LuckPerms, use theeasyspec.triggerpermission node instead. Players without permission are silently ignored.
The required permission for /easyspec commands uses the easyspec.command permission node via Fabric Permissions API. Without a permission mod (e.g. LuckPerms), it falls back to the permissionLevel config option (default: 2 — operator).
| Command | Description |
|---|---|
/easyspec reload |
Reload config from config/easyspec.json |
/easyspec reset |
Reset all config to default values and save |
/easyspec reset <key> |
Reset a single config option to its default value |
/easyspec set <key> <value> |
Set a config option to the given value |
/easyspec info |
Display all current configuration values |
/easyspec reloadre-reads the config file from disk without restarting the server./easyspec reset <key>resets one field only. Available keys:language,trigger,hideTrigger,permissionLevel,triggerPermissionLevel./easyspec set <key> <value>modifies a config option at runtime and persists it to disk. Supports tab-completion for keys and valid values. When LuckPerms is active and the key ispermissionLevelortriggerPermissionLevel, displays a warning that LP overrides./easyspec infodisplays all config values. When LuckPerms is installed, also shows which permission nodes are actually in effect.
If you want to customize or add a language, the translation files are located in the mod JAR at assets/easyspec/lang/. Each file is a simple JSON with the following keys:
| Key | Purpose |
|---|---|
mod.easyspec.name |
Mod display name |
modmenu.descriptionTranslation.easyspec |
ModMenu description |
message.easyspec.toggled |
Message when entering spectator (use %s for the trigger word) |
message.easyspec.restored |
Message when returning from spectator |
message.easyspec.reloaded |
Message shown after /easyspec reload |
message.easyspec.reset |
Message shown after /easyspec reset |
message.easyspec.reset_key |
Message shown after /easyspec reset <key> |
message.easyspec.set_success |
Confirmation after /easyspec set |
message.easyspec.set_error_invalid_key |
Error when an unknown config key is used |
message.easyspec.set_error_invalid_value |
Error when an invalid value is provided |
message.easyspec.info |
/easyspec info output template |
message.easyspec.no_permission |
Message when a player lacks trigger permission |
message.easyspec.lp_warning_command |
Warning when adjusting permissionLevel with LP active |
message.easyspec.lp_warning_trigger |
Warning when adjusting triggerPermissionLevel with LP active |
message.easyspec.lp_info |
Info notice in /easyspec info when LP is installed |
git clone https://github.com/LuoBingbing1145/easyspec.git
cd easyspec
./gradlew buildThe built JAR will be in build/libs/.
Requirements:
- Java 17+
- Gradle (bundled via Gradle Wrapper)
EasySpec's core is intentionally minimal:
src/main/java/lbb/easyspec/
├── EasySpec.java # Mod entrypoint — registers commands, announces permission nodes
├── SpectatorManager.java # Toggle logic & SavedData-backed persistence
│ └── PlayerStateStore # Inner SavedData: persists states per-world
├── command/
│ └── EasySpecCommand.java # /easyspec reload, reset, set, info commands
├── config/
│ ├── ConfigKey.java # Typed descriptor for one config option (name, type, default, validator, parser)
│ ├── ConfigKeys.java # Registry of all ConfigKey constants + ordered ALL list
│ ├── ConfigData.java # Immutable key-value snapshot
│ ├── ConfigManager.java # Singleton orchestrator — load/save/validate/reset/reload
│ └── Messages.java # Translation system with 9 languages
└── mixin/
└── ChatMessageMixin.java # Chat interception mixin with Fabric Permissions API support
Modular config system: The old monolithic Config.java has been replaced with a ConfigKey descriptor pattern. Each config option is a typed constant (ConfigKey<T>) registered in ConfigKeys.java. Adding a new option requires only one constant — serialization, validation, tab-completion, and info display pick it up automatically.
Permission system: Commands and trigger word now use Fabric Permissions API (Permissions.check()). When LuckPerms is installed, the mod's permissionLevel and triggerPermissionLevel config values are ignored in favor of easyspec.command and easyspec.trigger permission nodes. The mod announces these nodes on server startup so they appear in LP's editor without manual entry.
Persistence design: SpectatorManager.PlayerStateStore extends SavedData and is obtained via server.overworld().getDataStorage().computeIfAbsent(...). States are serialized as JSON inside a single NBT CompoundTag string field, stored at world/data/easyspec-player-states.dat.
This project is available under the CC0-1.0 license. Feel free to learn from it, modify it, and incorporate it into your own projects.
Authors: LBB285, MotherWang
Repository: github.com/LuoBingbing1145/easyspec