本页面尚未翻译成简体中文,因此以英文显示。 英文版本

Quest format (datapack JSON)

This page is the contract quest packs are written against: every field of a quest and a chapter, every objective and reward type, the custom_event channel syntax, what NeroQuests publishes when a quest completes, and the validation rules for each source. If you ship quests inside your own mod, read Shipping a quest pack next — it is the step-by-step version.

NeroQuests is datapack-driven. Every quest and every chapter of the quest book is a JSON file, so mods, modpacks and servers add, change or remove content without touching code.

data/<namespace>/neroquests/quests/<path>.json     -> quest   <namespace>:<path>
data/<namespace>/neroquests/chapters/<path>.json   -> chapter <namespace>:<path>

The id comes from the file path, never from the file body: data/mypack/neroquests/quests/start/first_steps.json defines the quest mypack:start/first_steps. Ship a file with an id that already exists and yours replaces it. Definitions are read from the server's datapacks; everything is server-authoritative and the client only displays what the server sends.

Sources

Every quest and chapter has a source, decided by its namespace when it loads:

SourceNamespaceWhat it isEditable in game
spineneroquestsNeroQuests' own story chaptersNever
packany other datapack namespaceA mod's quest pack (shipped in that mod's jar) or a server's own datapackNever
customcustomReserved for quests made in gameYes, by authorised players

A datapack file in the custom namespace is dropped — that namespace belongs to the in-game store. Spine and pack quests can never be changed, hidden, deleted or re-rewarded at runtime.

Quest file

{
  "title": "quest.mypack.start.first_steps.title",
  "description": "quest.mypack.start.first_steps.desc",
  "icon": "minecraft:iron_pickaxe",
  "prerequisites": ["mypack:start/wake_up"],
  "objectives": [
    { "type": "neroquests:craft_item", "item": "minecraft:iron_pickaxe" }
  ],
  "rewards": [
    { "type": "neroquests:xp", "amount": 50 }
  ],
  "scope": "player",
  "visible_gate": "nerolandcore:industrial_power"
}
FieldTypeRequiredDefaultMeaning
titlestringyes—A translation key. Packs must use a key (see Validation); the recommended shape is quest.<namespace>.<path with / as .>.title.
descriptionstringno""Longer text in the quest detail panel. A translation key (….desc).
iconitem idnominecraft:bookItem shown as the quest's node icon.
prerequisiteslist of quest idsno[]The quest stays locked until all of these are complete.
objectiveslist of objectivesyes—At least one. All must be done to complete the quest.
rewardslist of rewardsno[]Granted once per player, on completion, in order.
scopeplayer | servernoplayerplayer — everyone completes it for themselves. server — one shared completion for the whole world (a "world log" quest).
visible_gategate idnononeA Neroland Core progression gate. While it is closed for a player the quest is hidden from them entirely.

Chapter file

A chapter is one page of the quest book: a title, an icon, and the quests placed on it.

{
  "title": "chapter.mypack.start.title",
  "icon": "minecraft:crafting_table",
  "show_when_absent": false,
  "allow_server_scope": false,
  "quests": [
    { "quest": "mypack:start/wake_up",     "x": 0, "y": 0 },
    { "quest": "mypack:start/first_steps", "x": 2, "y": 0 }
  ]
}
FieldTypeRequiredDefaultMeaning
titlestringyes—Chapter tab name — a translation key (chapter.<namespace>.<path>.title).
iconitem idnominecraft:written_bookItem shown on the chapter tab.
questslist of entriesno[]The quests on this page. Each entry is { "quest": <id>, "x": <int>, "y": <int> }; x/y default to 0 and are grid units, not pixels.
show_when_absentbooleannofalsePacks only. Keep this chapter visible even when the pack's mod is not installed: its quests show a "needs a mod that is not installed" badge and can never be completed.
allow_server_scopebooleannofalsePacks only. The quests this chapter lists may use "scope": "server".

Dependency lines are not stored. The book draws them from each quest's prerequisites, so a layout can never contradict the real progression graph. A quest should appear in one chapter; if two chapters list it, the alphabetically first chapter id keeps it. A pack chapter may list only its own namespace's quests.

Objective types

An objective is { "type": "<id>", ... }. Ten types ship. Objectives has the full behaviour of each (how progress moves, server scope, missing content).

TypeDone whenFields (* = required)
neroquests:collect_itemYou hold this many matching items (or hand them in)item* | tag*, count (1), consume (false)
neroquests:craft_itemYou crafted this many matching itemsitem* | tag*, count (1)
neroquests:kill_entityYou killed this many matching creaturesentity* | tag*, count (1)
neroquests:reach_dimensionYou set foot in a dimensiondimension*
neroquests:visit_structureYou stood inside a generated structurestructure* | tag*
neroquests:gate_openA Neroland Core gate is open for you (read-only)gate*
neroquests:quest_completeAnother quest is complete for the same holderquest*
neroquests:custom_eventA mod published a matching threshold crossingchannel*, event_scope, direction (any), min_value, max_value, count (1), audience (world)
neroquests:economyYou sold, bought or earned on the server economy (needs an economy mod)event* (sold | bought | earned), item | tag, count (1)
neroquests:manualA quest author confirmed it for youlabel* (a translation key shown as the objective's text)

* with | means exactly one of the two. Tags are written without #. Counts are integers ≥ 1.

  • manual never advances by itself. An authorised person ticks it for an online player with /neroquests manual complete <quest> <player> (see Commands) — use it for "build a thing" quests the game cannot detect.
  • visit_structure is checked once a second for players who have the quest in progress, against the structure pieces of the chunk they stand in. Once visited it stays done.
  • economy loads without an economy mod but never advances; earned never counts NeroQuests' own payouts.

neroquests:custom_event — channels and the audience rule

A channel is a quantity another mod tracks, named <modid>:<channel>. When it crosses a threshold the publisher fires a threshold crossing on Neroland Core's event bus, and NeroQuests listens. Neither mod imports the other.

{ "type": "neroquests:custom_event", "channel": "nerocolonies:oxygen", "direction": "rising" }

A crossing carries exactly five things — channel, a scope key (where: a colony id, a region, a dimension), value, threshold and whether it was rising — and those are all you can match on. A crossing never names a player. So the quest author must say who hears it:

audienceWho is creditedNeeds
world (default)The quest's shared counter, once per crossing"scope": "server" (a pack also needs allow_server_scope on its chapter)
everyoneEvery online player who has the quest available and unfinished—

A custom_event left on the default world inside a "scope": "player" quest could never advance, so that quest is dropped with the reason. rising means "crossed upward" — recovery on one channel, worsening on another; read the publisher's documentation. The namespace of the channel must be the publishing mod's id; for a pack quest the channel counts as present whenever the pack is loaded.

Reward types

A reward is { "type": "<id>", ... }. Seven types ship. Rewards has the full behaviour (order, kept rewards, server scope, degradation).

TypePays outFields (* = required)Allowed for
neroquests:itemA stack of itemsitem*, count (1–2304)all
neroquests:xpExperience pointsamount* (1–1,000,000)all
neroquests:currencyCredits (budgeted when an economy mod is installed)amount* (1–1,000,000), currency (nerolandcore:credits), once_per_world (false)all
neroquests:loot_tableOne roll of a loot tabletable*all
neroquests:mod_hookTells your mod "this player finished it" (see below)gate* — <own namespace>:hook/<id>spine and packs
neroquests:gateOpens a Neroland Core progression gategate*spine only
neroquests:reputationStanding with a factionfaction, amountspine only

Rewards are paid once per player per quest — a revoke and re-completion does not pay again unless an operator asks for it — and each reward is isolated, so one that fails never stops the rest.

neroquests:mod_hook — your mod's own reward

{ "type": "neroquests:mod_hook", "gate": "mypack:hook/star_chart" }

A pack that wants a custom effect (unlock a page, refill a tank, grant a cosmetic) ships a record gate in its own jar, data/mypack/neroland_gates/hook/star_chart.json, and names it here:

{ "scope": "player", "title": "Star chart bonus" }

The scope must be written out: a Core gate defaults to server scope.

On completion NeroQuests opens that gate for the player through Neroland Core (it works for an offline player too). Your mod listens on Core's gate events — CoreEvents.onProgression or GateEvents.onChange, where the change's target is the player's UUID string — applies its effect, and may close the gate again to re-arm it for a repeat. Rules:

  • The gate must be in the quest's own namespace and its path must start with hook/.
  • It must be a player-scope gate with no requires. An undefined gate (your mod is not installed) or one of the wrong shape is reported once in the log and nothing is written.
  • Hook gates are records that gate nothing. Never check a hook gate to allow or deny access to anything — that is why they are written even when the server sets gateWritesEnabled=false.

Completion signals

Whenever a quest completes, NeroQuests publishes an anonymous crossing on Core's ThresholdEvents bus (publisher neroquests). Any mod can listen — you need no dependency on NeroQuests:

ChannelWhenscopevalue / thresholdrising
neroquests:quest_completedEvery completion of any questThe quest idHow many times that quest has now been completed in this worldtrue
neroquests:chapter_completedA completion that finished every quest of its chapter for that playerThe chapter idHow many times that chapter has now been completed in this worldtrue

These say that something was completed, never who. A server-scope quest completes once, so it publishes once. Use them for world effects; use mod_hook when the effect belongs to the player.

Validation rules

NeroQuests never crashes on bad content. Every problem is logged at WARN naming the resource id, the smallest sensible thing is dropped, and /neroquests reload-check lists it with the rule it broke.

Every source

ProblemWhat happens
Malformed JSON, a wrong field type, or a value outside its rangeThe quest/chapter is dropped (never half-loaded).
An objective or reward type that is not registeredThe whole quest is dropped.
objectives empty or missingThe quest is dropped.
A custom_event on audience: world in a scope: player questThe quest is dropped.
An id that does not resolve although its mod is loaded (a typo)The quest is dropped, naming the objective.
A mod_hook gate outside the quest's namespace or without the hook/ prefixThe quest is dropped.
A prerequisite that does not existThat prerequisite is ignored; the quest is kept.
A prerequisite cycle (including a quest requiring itself)Every quest in or behind the cycle is dropped.
A chapter lists a quest that does not exist (or was dropped)That entry is ignored; the chapter is kept.
The same quest in two chaptersThe first chapter by id keeps it.
A file in the reserved custom namespaceDropped.

Packs (any namespace other than neroquests)

RuleIf broken
No neroquests:gate or neroquests:reputation rewards — packs record progress, they never unlock itQuest dropped
"scope": "server" only when a chapter of the same namespace lists the quest and sets "allow_server_scope": trueQuest dropped
Prerequisites and quest_complete objectives may name only quests of the same namespace or the neroquests spineQuest dropped
title and description must be translation keys (lower-case, digits, _ . -, at least one dot) — not literal textQuest dropped
A chapter's title must be a translation keyChapter dropped
A chapter may list only quests of its own namespaceThat entry ignored

Custom quests (made in game)

Custom quests come from the world's editor store, not from files, but pass the same validation plus these rules. A spine or pack quest that breaks the first one is dropped; the rest are checked when an author saves (see Editor permissions).

RuleIf broken
A spine or pack quest may not depend on a custom quest (prerequisite or quest_complete)That spine/pack quest dropped
scope: player only; no visible_gateCustom quest dropped
1–12 objectives of collect_item, craft_item, kill_entity, reach_dimension, gate_open, quest_complete, custom_event, visit_structure, manual; counts 1–1,000,000Custom quest dropped
At most 9 rewards of item (one stack each), loot_table, xp, currency, within the server's capsCustom quest dropped
Title, description and manual labels are plain text (sanitised, at most 64 / 512 / 64 characters)Custom quest dropped
A custom chapter lists only custom quests; no other chapter may list oneThat entry ignored

Packs follow their mod

  • A pack whose namespace is a mod that is not installed loads nothing — no error, it is a smaller install. reload-check lists it as "mod not installed".
  • With "show_when_absent": true on a chapter, that chapter and the quests it lists stay visible with a badge, and are never completable.
  • A namespace that is not a mod id (a server's own datapack) always loads.
  • Pack quests never use the missingModObjectivePolicy=autocomplete escape hatch: a pack only loads when its mod is present, so an absent piece of it is simply skipped.

Log lines carry resource ids only — never player names, UUIDs or other personal data (see ../PRIVACY.md).

Two complete examples

A player quest (inside a mod's pack)

data/mypack/neroquests/chapters/start.json

{
  "title": "chapter.mypack.start.title",
  "icon": "mypack:wrench",
  "quests": [
    { "quest": "mypack:start/first_wrench", "x": 0, "y": 0 },
    { "quest": "mypack:start/workshop",     "x": 2, "y": 0 }
  ]
}

data/mypack/neroquests/quests/start/workshop.json

{
  "title": "quest.mypack.start.workshop.title",
  "description": "quest.mypack.start.workshop.desc",
  "icon": "mypack:workbench",
  "prerequisites": ["mypack:start/first_wrench", "neroquests:groundwork/first_tools"],
  "objectives": [
    { "type": "neroquests:craft_item", "item": "mypack:workbench" },
    { "type": "neroquests:collect_item", "tag": "c:ingots/iron", "count": 16, "consume": true }
  ],
  "rewards": [
    { "type": "neroquests:xp", "amount": 100 },
    { "type": "neroquests:item", "item": "mypack:wrench", "count": 1 },
    { "type": "neroquests:mod_hook", "gate": "mypack:hook/workshop_blueprint" }
  ]
}

assets/mypack/lang/en_us.json

{
  "chapter.mypack.start.title": "Getting Started",
  "quest.mypack.start.workshop.title": "Set Up Shop",
  "quest.mypack.start.workshop.desc": "Build a workbench and hand in sixteen iron ingots."
}

A server world-log quest

data/mypack/neroquests/chapters/world_log.json

{
  "title": "chapter.mypack.world_log.title",
  "icon": "minecraft:filled_map",
  "allow_server_scope": true,
  "quests": [
    { "quest": "mypack:world_log/first_meltdown_averted", "x": 0, "y": 0 }
  ]
}

data/mypack/neroquests/quests/world_log/first_meltdown_averted.json

{
  "title": "quest.mypack.world_log.first_meltdown_averted.title",
  "description": "quest.mypack.world_log.first_meltdown_averted.desc",
  "icon": "minecraft:blue_ice",
  "scope": "server",
  "objectives": [
    {
      "type": "neroquests:custom_event",
      "channel": "mypack:reactor_heat",
      "direction": "falling",
      "audience": "world"
    }
  ],
  "rewards": [
    { "type": "neroquests:xp", "amount": 200 }
  ]
}

The world completes it once; its player rewards go to every online player who has it available at that moment, each paid once.

Reloading

Definitions are cached per server. A vanilla /reload is picked up within a second; restarting the world also picks up changed files. /neroquests reload-check reports what the running server loaded, per source. Existing progress is kept when definitions change; progress for a quest that no longer exists is inert and comes back if the quest returns.

See also

在所有 Nero 模组百科中搜索。百科内容目前为英文。