Monoceros
A Minecraft Server Mechanics and Gameplay Platform
Cross-version server infrastructure built on TabooLib, covering Minecraft 1.12.2 through 26.1.2, with Fluxon scripts driving everything.
What Is Monoceros?
Monoceros is designed for Minecraft server gameplay development. It provides a complete infrastructure layer for building custom server mechanics:
- A unified event listening and dispatching system
- A powerful Fluxon scripting engine as the replacement for Kether
- Visual-style action workflows and a flexible property system
- Packet-level tracing, interception, and rewriting
- Client-side illusions, fake blocks, fake world borders, and other volatile capabilities
- Five major gameplay mechanic domains: combat, regions, interactions, visuals, and sessions
- Configuration-driven design, hot-reload friendly, and far less hardcoding
Stop rebuilding the same foundation for every mechanic. Put your time back into gameplay design.
Core Features
1. Fluxon Scripting Engine
Monoceros uses Fluxon as its unified scripting runtime. Event listeners, commands, scheduled tasks, and workflow nodes can all be driven by scripts.
Scripts are loaded from the file system and support incremental hot reload, precompiled caching, SHA-256 change detection, and real-time FileWatcher monitoring.
Code (Text):
// script/dispatcher/player-join.fs
// Automatically runs when a player joins
print("Player ${&?player} joined the server")
// Automatically runs when a player joins
print("Player ${&?player} joined the server")
Code (Text):
// script/action/combat.hit-feedback.fs
// Combat hit feedback
dmg = &?damage ?: 0
print("[Combat] Hit feedback: damage=${&dmg}")
// Combat hit feedback
dmg = &?damage ?: 0
print("[Combat] Hit feedback: damage=${&dmg}")
Monoceros automatically imports cc.bkhk.monoceros.*, cc.bkhk.monoceros.api.*, org.bukkit.*, org.bukkit.entity.*, and org.bukkit.inventory.*, so manual imports are usually not required.
Scripts can directly access the Monoceros API through static calls. Relevant methods are annotated with @JvmStatic:
Code (Text):
api = static cc.bkhk.monoceros.Monoceros.api()
plugin = static cc.bkhk.monoceros.Monoceros.plugin()
session = &api.sessions().getOrCreate(&p.getUniqueId())
plugin = static cc.bkhk.monoceros.Monoceros.plugin()
session = &api.sessions().getOrCreate(&p.getUniqueId())
Monoceros registers seven categories of extension functions into the Fluxon runtime. They can be called directly from scripts without imports:
- JSON: jsonParse(str) / jsonStringify(obj) / jsonPretty(obj) - JSON parsing and serialization
- HTTP: httpGet(url) / httpPost(url, body) / httpRequest(...) - Asynchronous HTTP requests, consumed with await
- UUID: uuid() / uuidFromString(str) / uuidFromName(name) - UUID generation and parsing
- Cooldown: cooldown(key, ms) / hasCooldown(key) / getCooldown(key) - Cooldowns and rate limiting
- Color: colored(text) / uncolored(text) - Color-code conversion, including the :: colored() extension style
- Logging: logInfo(msg) / logWarn(msg) / logDebug(msg) / logError(msg) - Structured logging
- Regex: regex(pattern) / regexMatch(text, pattern) / regexReplace(...) - Regex matching and replacement
2. Event Dispatcher System
Monoceros manages event listeners through a unified Dispatcher system:
Code (Text):
# dispatcher/player-join.yml
id: player.join.welcome
listen-event: PlayerJoinEvent
listen-priority: NORMAL
weight: 20
execute:
route: script
value: dispatcher.player-join
variables:
triggerSource: join
id: player.join.welcome
listen-event: PlayerJoinEvent
listen-priority: NORMAL
weight: 20
execute:
route: script
value: dispatcher.player-join
variables:
triggerSource: join
- Three-level routing by event type, priority, and weight
- Multiple handlers under the same priority are sorted by weight
- Dynamic registration, dynamic unregistration, and automatic dispatch-table rebuilds after hot reload
- Five-stage pipeline: initPrincipal -> initVariables -> filter -> afterFilter -> postprocess
- Built-in cooldowns using Baffle, list filters, player extraction by reflection, and more
- Route targets include scripts, action workflows, and custom handlers
For states that Bukkit does not expose as native events, such as armor changes, Monoceros fills the gap through StateProbe.
3. Scheduler System
Monoceros supports four schedule types: delay ( DELAY), periodic ( PERIODIC), cron expression ( CRON), and conditional trigger ( CONDITIONAL).
Code (Text):
# schedule/broadcast.yml
id: world.tick.broadcast
type: periodic
delay: 20t
period: 200t
auto-start: true
async: false
max-runs: -1
execute:
route: script
value: schedule.world.tick.broadcast
variables:
triggerSource: periodic
id: world.tick.broadcast
type: periodic
delay: 20t
period: 200t
auto-start: true
async: false
max-runs: -1
execute:
route: script
value: schedule.world.tick.broadcast
variables:
triggerSource: periodic
- Maximum run count and maximum duration limits
- Pause, resume, and stop support, with full runtime control
- Prototype mode for parallel multi-instance execution
- Sender selectors: CONSOLE / ONLINE_PLAYER / PLAYER / WORLD / RANGE / AREA
- Lifecycle scripts: onStart / onStop / onPause / onResume
4. Action Workflows
Break complex logic into ordered node chains. Configuration becomes executable logic:
Code (Text):
# workflow/action/combat-hit.yml
id: combat.hit-feedback
failure-policy: continue
nodes:
- id: log-hit
type: log
message: "Combat hit feedback triggered"
- id: set-damage
type: set
key: damage
value: 10
- id: run-script
type: script
script: action.combat.hit-feedback
id: combat.hit-feedback
failure-policy: continue
nodes:
- id: log-hit
type: log
message: "Combat hit feedback triggered"
- id: set-damage
type: set
key: damage
value: 10
- id: run-script
type: script
script: action.combat.hit-feedback
- script - Calls a Fluxon script
- set - Sets a context variable
- log - Outputs a log message
- wait - Delays execution by ticks
- branch - Conditional branch using script evaluation and then/else paths
- loop - Iterates over values
- sound - Plays a sound
- tellraw - Sends rich text messages
- regex - Regex matching and capture-group extraction
- try-catch - Exception handling and fallback logic
- input - Waits for player input through chat capture with timeout support
- if-else - Conditional branch
- math - Math operations: abs, ceil, floor, round, sqrt, pow, min, max, random, sin, cos, tan, log
- coerce - Numeric range constraint
- dispatch - Dispatches to a child workflow, script, or dispatcher
Control flow supports Continue, Delay for asynchronous continuations without blocking, Branch for conditional branches, and Break for interruption.
5. Packet Listening with Wireshark
Low-level packet listening, filtering, tracing, interception, and rewriting:
Code (Text):
# wireshark/example.yml
id: example.packet.trace
direction:
- send
- receive
matcher:
type: packet-name
value: PacketPlayOutChat
tracking: true
parse: true
intercept: false
route:
type: script
value: debug.packet.trace
id: example.packet.trace
direction:
- send
- receive
matcher:
type: packet-name
value: PacketPlayOutChat
tracking: true
parse: true
intercept: false
route:
type: script
value: debug.packet.trace
Code (Text):
// script/debug/packet.trace.fs
name = &?packetName ?: "unknown"
cls = &?packetClass ?: ""
print("[Wireshark] Trace: ${&name} (${&cls})")
name = &?packetName ?: "unknown"
cls = &?packetClass ?: ""
print("[Wireshark] Trace: ${&name} (${&cls})")
- Supports PacketReceiveEvent and PacketSendEvent
- Player-level packet sessions through PacketSession, with per-player Tap enable/disable control
- Interception and rewriting are controlled by the global wireshark.allow-intercept switch and stay conservative by default
- Supports field-level rewriting through field-set
- Built-in MeteorInjector suppressor to automatically block external injector interference
6. Volatility
Client-side illusion effects that do not modify the real server state:
- Fake blocks: sendBlockChange / sendBlockChanges
- World borders: static borders and dynamically interpolated borders
- Entity metadata: glowing, invisibility, pose, health, riding state, and more
- Illusion sessions: each illusion effect is precisely identified through IllusionKey(viewerId, namespace, targetId), allowing multiple mechanics to write concurrently and roll back precisely by key
7. Property System
A unified property read/write framework covering core Bukkit objects:
- Location: x/y/z/yaw/pitch/world/block/chunk/direction, readable and writable
- Vector: complete 3D vector math including construction, arithmetic, geometry, and rotation
- Entity / LivingEntity / Player: chained access and writing for full property sets
- World: time, weather, difficulty, and player list
- ItemStack: type, amount, enchantments, flags, durability
- Block: type, light level, biome, and data
- Event: generic event properties plus dedicated property accessors for 15 specific event types
Six Extension Domains
Entity Domain
Entity operations: damage, healing, teleportation, potion effects, attribute toggles, and equipment setting.
Location operations: construction, cloning, modification, arithmetic, and distance calculation.
Vector operations: a complete 3D math library, including normalization, dot product, cross product, and rotation.
Event Domain
Event control: cancellation, ignore flags, property writing, and reply messages.
Asynchronous waiting: event.wait can wait asynchronously for a specified event to be triggered, with timeout support.
Illusion Domain
- Glowing effects with rollback support
- Visual warnings using Title, Subtitle, ActionBar, and world border pressure
- Breathing warnings based on sine-wave changes
- Fake blocks, fake health, and client-side holographic text
- Illusion context switching
Item Domain
Full item lifecycle: build items, change names, lore, enchantments, flags, durability, colors, and tags.
Item operations: consume, destroy, drop, and give.
Inventory operations: check, count, find, switch, and take out.
Potion operations: query, set, remove, and clear.
Memory Domain
Key-value storage across six scopes: GLOBAL / PLAYER / ENTITY / WORKFLOW / SCRIPT / SESSION.
TTL expiration is supported, such as 3000ms or 3s, with automatic expiration checks and thread-safe storage.
Target Domain
Nine target selection modes: self, world, whole server, radius, cuboid, nearest N targets, ring, specified player, and line-of-sight selection.
Target operations: filter by type, filter by script condition, and execute child workflows for each target.
Five Gameplay Mechanic Domains
Combat Mechanics
- Cooldown management: setCooldown / getCooldownRemaining / hasCooldown
- Combo tracking: recordHit, returning combo count, plus getComboCount and resetCombo
- Status stacking: apply with stacks/maxStacks and TTL, remove, and get
- Skill executor: five-stage execution chain CONDITION -> WINDUP -> EXECUTE -> RECOVERY -> COOLDOWN
Region Mechanics
- Region definitions: Cuboid and Sphere
- Region events: enter, leave, and stay, with configurable detection intervals
- Region effects: automatic Buff/Debuff application
- Region scripts: onEnter / onLeave / onStay
Interaction Mechanics
- Interaction types: right click, left click, sneak right click, sneak left click, and sneak toggle
- Material filters: trigger by item type
- Line-of-sight locking: getLookAtTarget obtains the target entity and distance
- Cooldown control: independent cooldowns per interaction definition
Visual Mechanics
- BossBar: create, update, show, and hide, with color and style support
- ActionBar: duration-based message pushing
- Title: complete control over fadeIn, stay, and fadeOut
- Message queue: priority sorting to prevent message overwrites
Session Mechanics
- Player sessions: get, set, remove, and has, with snapshot and restore support
- Mechanic participation: joinMechanic / leaveMechanic / getActiveMechanics
- Context isolation: each player has an independent session, so multiple mechanics do not interfere with each other
- Direct API access: Monoceros.api().sessions() returns the SessionService and is available from scripts in one line
Command System
Main command: /monoceros, alias: /mono, permission prefix: monoceros.command.
Code (Text):
/mono reload [service] Reload all services or a specific service
/mono version Show the version
/mono debug Toggle debug mode
/mono status Show all service states and the environment profile
/mono selfcheck Run self-check and output issues and suggestions
/mono script run <id> Run a script
/mono script debug <id> Run a script in debug mode and return synchronous cost
/mono script stop <id> Stop script tasks
/mono script task list List active tasks
/mono script reload Reload script definitions
/mono script preheat Preheat all scripts
/mono script stats Show cache statistics
/mono schedule start <id> Start a schedule
/mono schedule pause <id> Pause a schedule
/mono schedule resume <id> Resume a schedule
/mono schedule stop <id> Stop a schedule
/mono schedule detail [id] View schedule details with interactive operation buttons
/mono dispatcher reload Reload dispatchers
/mono dispatcher enable <id> Enable a dispatcher
/mono dispatcher disable <id> Disable a dispatcher
/mono version Show the version
/mono debug Toggle debug mode
/mono status Show all service states and the environment profile
/mono selfcheck Run self-check and output issues and suggestions
/mono script run <id> Run a script
/mono script debug <id> Run a script in debug mode and return synchronous cost
/mono script stop <id> Stop script tasks
/mono script task list List active tasks
/mono script reload Reload script definitions
/mono script preheat Preheat all scripts
/mono script stats Show cache statistics
/mono schedule start <id> Start a schedule
/mono schedule pause <id> Pause a schedule
/mono schedule resume <id> Resume a schedule
/mono schedule stop <id> Stop a schedule
/mono schedule detail [id] View schedule details with interactive operation buttons
/mono dispatcher reload Reload dispatchers
/mono dispatcher enable <id> Enable a dispatcher
/mono dispatcher disable <id> Disable a dispatcher
Configuration-Driven and Hot-Reload Friendly
All core features are driven by YAML configuration. Changes can be applied immediately with /mono reload:
Code (Text):
plugins/Monoceros/
├── config.yml # Main configuration
├── dispatcher/ # Event dispatcher definitions
│ └── player-join.yml
├── schedule/ # Schedule definitions
│ └── broadcast.yml
├── wireshark/ # Packet Tap definitions
│ └── example.yml
├── workflow/
│ └── action/ # Action workflow definitions
│ └── combat-hit.yml
├── script/ # Fluxon scripts
│ ├── dispatcher/
│ ├── schedule/
│ ├── action/
│ ├── command/
│ ├── debug/
│ └── shared/
└── lang/ # Internationalization files
├── zh_CN.yml
└── en_US.yml
├── config.yml # Main configuration
├── dispatcher/ # Event dispatcher definitions
│ └── player-join.yml
├── schedule/ # Schedule definitions
│ └── broadcast.yml
├── wireshark/ # Packet Tap definitions
│ └── example.yml
├── workflow/
│ └── action/ # Action workflow definitions
│ └── combat-hit.yml
├── script/ # Fluxon scripts
│ ├── dispatcher/
│ ├── schedule/
│ ├── action/
│ ├── command/
│ ├── debug/
│ └── shared/
└── lang/ # Internationalization files
├── zh_CN.yml
└── en_US.yml
Command reload uses delayed registration to avoid conflicts with Paper's asynchronous command-tree construction thread, keeping hot reload clean and error-free.
Cross-Version Support
Monoceros covers Minecraft 1.12.2 through 26.1.2. Version differences are handled through modular layers:
- module-legacy-api: legacy Material, NBT, and text compatibility
- module-modern: Data Components and modern ItemMeta support
- module-java17 / module-java21: isolation for Java-version-specific dependencies
- NMS differences are bridged through TabooLib nmsProxy, keeping business logic free from version checks
Operations and Diagnostics
- /mono selfcheck: automatically detects configuration errors, missing dependencies, and incompatible versions
- /mono diag dump: exports full runtime-state information
- /mono diag cache: exports cache hit rates and compilation statistics
- DiagnosticLogger: unified diagnostic logging with toggleable debug mode
- Reload reports: each reload outputs loaded / updated / failed / costMs
AI-Assisted Development Examples
Monoceros provides a Monoceros AI Skill that can be used directly in AI coding assistants with Skill support, such as Kiro. This Skill includes knowledge of Monoceros configuration formats, mechanic services, and Fluxon scripting syntax, helping the assistant generate more accurate configurations and scripts.
The Skill files are available in the repository: https://github.com/YsGqHY/Monoceros/tree/master/.claude/skills
How to use it: place the Skill files into the corresponding directory of your AI coding assistant, then describe your requirement in a conversation. The AI will automatically call the Monoceros Skill to retrieve the relevant knowledge before generating the result.
Example 1: Writing a Fluxon Script
Code (Text):
User: Write a Fluxon script that gives a player a glowing effect and sends a warning when their health drops below 30%.
AI automatically calls Skill: Monoceros
AI automatically calls Skill: Monoceros
Code (Text):
// script/mechanic/low-health-warning.fs
health = &?player.getHealth()
maxHealth = &?player.getMaxHealth()
ratio = &health / &maxHealth
if (&ratio < 0.3) {
&?player.setGlowing(true)
&?player.sendMessage("&cWarning: your health is below 30%!")
} else {
&?player.setGlowing(false)
}
health = &?player.getHealth()
maxHealth = &?player.getMaxHealth()
ratio = &health / &maxHealth
if (&ratio < 0.3) {
&?player.setGlowing(true)
&?player.sendMessage("&cWarning: your health is below 30%!")
} else {
&?player.setGlowing(false)
}
Code (Text):
User: Help me create a region guard mechanic. When a player enters a specified area, they take damage every 3 seconds. The effect stops after they leave.
AI automatically calls Skill: Monoceros
AI automatically calls Skill: Monoceros
Dispatcher configuration:
Code (Text):
# dispatcher/region-guard-enter.yml
id: region.guard.enter
listen-event: PlayerMoveEvent
listen-priority: NORMAL
weight: 10
execute:
route: action-workflow
value: region.guard.damage-loop
rules:
- type: script
value: |
loc = &?player.getLocation()
x = &loc.getX()
z = &loc.getZ()
&x > 100 && &x < 200 && &z > 100 && &z < 200
variables:
triggerSource: region-enter
id: region.guard.enter
listen-event: PlayerMoveEvent
listen-priority: NORMAL
weight: 10
execute:
route: action-workflow
value: region.guard.damage-loop
rules:
- type: script
value: |
loc = &?player.getLocation()
x = &loc.getX()
z = &loc.getZ()
&x > 100 && &x < 200 && &z > 100 && &z < 200
variables:
triggerSource: region-enter
Code (Text):
# schedule/region-guard-tick.yml
id: region.guard.tick
type: periodic
delay: 0t
period: 60t
auto-start: true
async: false
execute:
route: script
value: mechanic.region-guard.tick
id: region.guard.tick
type: periodic
delay: 0t
period: 60t
auto-start: true
async: false
execute:
route: script
value: mechanic.region-guard.tick
Code (Text):
// script/mechanic/region-guard.tick.fs
// Deals 2 damage to players inside the region every 3 seconds
players = static org.bukkit.Bukkit.getOnlinePlayers()
for p in &players {
loc = &p.getLocation()
x = &loc.getX()
z = &loc.getZ()
if (&x > 100 && &x < 200 && &z > 100 && &z < 200) {
&p.damage(2.0)
&p.sendMessage("&cYou are taking damage from the region guard!")
}
}
// Deals 2 damage to players inside the region every 3 seconds
players = static org.bukkit.Bukkit.getOnlinePlayers()
for p in &players {
loc = &p.getLocation()
x = &loc.getX()
z = &loc.getZ()
if (&x > 100 && &x < 200 && &z > 100 && &z < 200) {
&p.damage(2.0)
&p.sendMessage("&cYou are taking damage from the region guard!")
}
}
Code (Text):
User: Help me write a Wireshark configuration that traces all entity spawn packets sent to players.
AI automatically calls Skill: Monoceros
AI automatically calls Skill: Monoceros
Code (Text):
# wireshark/entity-spawn-trace.yml
id: debug.entity.spawn
direction:
- send
matcher:
type: packet-name
value: PacketPlayOutSpawnEntity
tracking: true
parse: true
intercept: false
route:
type: script
value: debug.entity-spawn
id: debug.entity.spawn
direction:
- send
matcher:
type: packet-name
value: PacketPlayOutSpawnEntity
tracking: true
parse: true
intercept: false
route:
type: script
value: debug.entity-spawn
Code (Text):
// script/debug/entity-spawn.fs
name = &?packetName ?: "unknown"
print("[Debug] Entity spawn packet: ${&name}")
print(" Target player: ${&?player}")
print(" Timestamp: ${&?now}")
name = &?packetName ?: "unknown"
print("[Debug] Entity spawn packet: ${&name}")
print(" Target player: ${&?player}")
print(" Timestamp: ${&?now}")
Code (Text):
User: Help me create a beginner guide workflow that sends a welcome message, gives items, and plays a sound in sequence.
AI automatically calls Skill: Monoceros
AI automatically calls Skill: Monoceros
Code (Text):
# workflow/action/newbie-guide.yml
id: newbie.guide
failure-policy: continue
nodes:
- id: welcome-title
type: tellraw
message: "&6&lWelcome to the server!"
- id: wait-a-bit
type: wait
ticks: 40
- id: give-item-script
type: script
script: action.newbie.give-starter-kit
- id: play-sound
type: sound
sound: ENTITY_PLAYER_LEVELUP
volume: 1.0
pitch: 1.0
- id: guide-message
type: tellraw
message: "&aYou have received a starter kit. Enjoy your adventure!"
id: newbie.guide
failure-policy: continue
nodes:
- id: welcome-title
type: tellraw
message: "&6&lWelcome to the server!"
- id: wait-a-bit
type: wait
ticks: 40
- id: give-item-script
type: script
script: action.newbie.give-starter-kit
- id: play-sound
type: sound
sound: ENTITY_PLAYER_LEVELUP
volume: 1.0
pitch: 1.0
- id: guide-message
type: tellraw
message: "&aYou have received a starter kit. Enjoy your adventure!"
Code (Text):
// script/action/newbie.give-starter-kit.fs
// Give starter kit
inv = &?player.getInventory()
sword = new org.bukkit.inventory.ItemStack(static org.bukkit.Material.IRON_SWORD)
meta = &sword.getItemMeta()
&meta.setDisplayName("&bStarter Sword")
&meta.setLore(["&7Made for new players"])
&sword.setItemMeta(&meta)
food = new org.bukkit.inventory.ItemStack(static org.bukkit.Material.COOKED_BEEF, 16)
&inv.addItem(&sword, &food)
&?player.sendMessage("&aStarter kit delivered!")
// Give starter kit
inv = &?player.getInventory()
sword = new org.bukkit.inventory.ItemStack(static org.bukkit.Material.IRON_SWORD)
meta = &sword.getItemMeta()
&meta.setDisplayName("&bStarter Sword")
&meta.setLore(["&7Made for new players"])
&sword.setItemMeta(&meta)
food = new org.bukkit.inventory.ItemStack(static org.bukkit.Material.COOKED_BEEF, 16)
&inv.addItem(&sword, &food)
&?player.sendMessage("&aStarter kit delivered!")
Quick Start
- Put the Monoceros plugin into your plugins/ directory.
- Start the server. Monoceros will generate the default configuration and example files automatically.
- Edit configuration files under dispatcher/, schedule/, script/, and related directories.
- Use /mono reload to hot-reload changes instantly.
- Use /mono status to inspect service states and /mono selfcheck to troubleshoot problems.
Why Choose Monoceros?
- Gameplay infrastructure: no need to develop a separate plugin foundation for every mechanic
- Configuration-driven: both server planners and developers can participate in gameplay design
- Fluxon scripts: a more modern and powerful scripting experience, closer to Kotlin-style scripting
- Built-in extension function library: JSON / HTTP / UUID / cooldown / color / logging / regex, ready out of the box
- Hot reload: configuration and script changes take effect in seconds
- Cross-version support: one configuration system covers Minecraft 1.12.2 through 26.1.2
- Modular architecture: 28 submodules composed by need, with clear responsibilities
Links
- GitHub repository: https://github.com/YsGqHY/Monoceros
- Discord community: https://discord.gg/Uz3EXh99T
- Issue tracker: https://github.com/YsGqHY/Monoceros/issues
- Releases: https://github.com/YsGqHY/Monoceros/releases
Quick facts
- Edition: Minecraft Java
- File type: .jar
- Minecraft versions listed: 1.12, 1.13, 1.14
- How to install: Install the matching mod loader (Forge, Fabric or NeoForge) for your Minecraft version. → Download the .jar. → Put it in the .minecraft/mods folder and launch that loader profile.
- Where to get it: Opens on Spigot — not every file is mirrored on our own servers.
Install steps are the general flow for this file type — How to install Minecraft Java mods & modpacks walks through it step by step.
Monoceros | With Fluxon scripts driving everything is a free Minecraft Java mod. Compatible with Minecraft 1.12, 1.13, 1.14, 1.15 and newer. Downloaded 6 times (via Spigot). Download it and open it directly in the game.