NimBlock runs plugins that are written as JSON rules instead of compiled Java.
You drop one jar on your server. Your plugins are .json files in plugins/NimBlock/specs/. The engine reads them and executes them: when this happens, if these conditions hold, then do that.
What a plugin looks like
Diamond ore below Y=16 is reserved to players with a permission. That is the whole file, nothing omitted:
{
"specVersion": 1,
"name": "Diamond guard",
"rules": [
{
"name": "Diamond ore below Y=16 is permission-only",
"trigger": { "type": "block.break" },
"conditions": [
{ "type": "text.equals", "params": { "text": "{block}", "value": "DIAMOND_ORE" } },
{ "type": "number.compare", "params": { "left": "{y}", "operator": "<", "right": "16" } },
{ "type": "player.has_permission", "params": { "permission": "mine.diamond" }, "not": true }
],
"actions": [
{ "type": "cancel_event" },
{ "type": "player.send_actionbar", "params": { "message": "&cThat ore is reserved." } }
]
}
]
}
Save it as plugins/NimBlock/specs/diamond-guard.json, run /nimblock reload, and it is live. No build, no restart, no jar of your own.
Why this isn't a code generator
Nothing generates Java anywhere. There is no compilation step, no jar to rebuild, nothing to recompile when the server updates. Your rules are data; the engine is the only thing that ever needs to change.
The consequence that actually matters: when a new Minecraft version lands, it isn't your plugin that breaks, it's the engine that takes the hit once, for everyone.
What it can do, exactly
The grammar is closed and published: 9 triggers, 8 conditions, 14 actions. Every one of them, with its parameters, is on a public page before you download anything:
- Grammar: https://nimblock.com/en/grammar
- JSON Schema: https://nimblock.com/spec/plugin-1.schema.json
Anything outside that catalogue is impossible, not "on the roadmap". Three limits worth knowing before you spend an evening on it:
- Conditions don't nest.
all/any, plus anotper condition. No boolean tree. - The engine has no memory between events. It reacts to what just happened; it does not store anything about a player from one session to the next. "First time a player joins" is not expressible in version 1, and neither is a counter.
- A rule can't ask the server questions. It reads what its trigger hands it (
{player},{block},{x},{y},{z},{message},{world},{killer},{args}) plus four things about that player: permission, op status, current world, current health. No block lookups, no player counts, no inventory checks.
If you need a guild system with its own database and GUI, this is the wrong tool and it always will be.
Compatibility promise
Specs declare specVersion. It is 1, and the engine refuses outright a spec whose specVersion it doesn't know, rather than running half of it. A spec written today keeps running on later engines of the same specVersion. That is the whole point of freezing the grammar.
Which Paper versions
Paper 1.21.4 or newer, on Java 21 or newer. Declared: 1.21.4, 1.21.6, 1.21.7, 1.21.8, 1.21.10, 1.21.11, 26.1.2, 26.2.
Below 1.21.4 the engine refuses to load, and that is deliberate: two catalogue actions have nothing to bind to there (player.give_effect needs Registry.MOB_EFFECT, which lands in 1.21.4, and player.heal needs Attribute.MAX_HEALTH, which lands in 1.21.3). A plugin that loads quietly and throws the day a rule fires is worse than one that refuses on startup, so api-version is 1.21.4 and Paper does the refusing itself.
Two kinds of proof, because one of them is not enough. Five of those versions were actually started on a running server, console read, one spec firing all nine triggers: 1.21.4, 1.21.8, 1.21.11, 26.1.2 and 26.2. All eight also pass a link check, which reads the jar's constant pool and verifies that every class, field and method it calls exists in that API. The engine uses no reflection, so what the link check sees is everything it can ever call: exhaustive, where a live run is a sample.
1.21.5 and 1.21.9 are missing from the middle of the range on purpose, and nothing breaks there. PaperMC has never promoted a stable build for either one (111 and 20 builds, all alpha). The engine links cleanly against both. If you run one of them it will very likely work, there is simply no stable build for anyone to say so with.
Installing
- Drop the jar in
plugins/. - Start the server once. It creates
plugins/NimBlock/specs/. - Put a
.jsonspec in that folder. /nimblock reloadre-reads specs without a restart./nimblock listshows what's loaded.
A command created by a spec only appears after a restart: Paper only accepts new command names during startup. The contents of a command reload live.
A spec is accepted or rejected as a whole, never rule by rule: a protection plugin missing the rule that protects would be invisible in game. Rejections are one red line in the console.
Network use
None. No telemetry, no stats, no license check, no outbound connection of any kind. The only compile dependency is paper-api.
Where the specs come from
You can write them by hand against the schema, or build them in a visual editor at https://nimblock.com : same grammar, same file. The editor is a convenience, not a requirement: the engine only ever reads the file you put on your server.
Requires Paper 1.21.4 or newer, on Java 21 or newer. Not an official Minecraft service. Not approved by or associated with Mojang or Microsoft.

