Skip to main content
Version: 26.1.2 (Latest)

Research Datagen

Research content is authored via datagen. The ResearchProvider orchestrator collects bundles from ResearchSubProviders and writes JSON files.

DataGenerators wiring

DataGenerators.gatherData requires a shared LanguageProviderCache and ResearchCache:

var langCache = new LanguageProviderCache("en_us");
var researchCache = new ResearchCache();

generator.addProvider(true, NeoBookProvider.of(event, langCache, researchCache,
new DemoBook(),
new DemoIndexBook(),
new DemoLeaflet()
));
generator.addProvider(true, NeoResearchProvider.of(event, langCache, researchCache, new DemoResearch(Modonomicon.MOD_ID)));
generator.addProvider(true, new EnUsProvider(generator.getPackOutput(), langCache));

NeoBookProvider.of() (and platform equivalents) take LanguageProviderCache and ResearchCache parameters. NeoResearchProvider, FabricResearchProvider, and ForgeResearchProvider are the platform-specific research providers.

Key classes

ClassPurpose
ResearchProviderTop-level orchestrator, collects bundles from sub-providers
SingleResearchSubProviderAbstract base for authoring one research bundle
ResearchDataBuilderLow-level collector for facts, values, nodes, hooks
ResearchNodeBuilderFluent builder for complex research nodes
ResearchIngressHelperFluent helper for research ingress from external events
ResearchCacheShared cache for merging book-generated and authored research

Declaring facts and values

var fact = this.fact("mymod/my_fact");
var value = this.value("mymod/my_counter");

Creating nodes

// Simple node requiring a fact
var node = this.node("mymod/my_node", fact);

// Node via fluent builder
this.nodeBuilder(this.node("mymod/my_node"))
.withFact(fact)
.withValue(new ResearchNodeSpec.ValueRequirement(value, 10))
.build();

Research ingress

// When an entry is viewed, grant a fact
this.ingress().onEntryViewedOnce(entryId).grantFact("mymod/my_hook", fact);

// When an item is crafted, increment a value
this.ingress().onItemCrafted(stackTemplate)
.incrementValue("mymod/my_hook", value, 1);

// When an advancement is earned, grant a fact
this.ingress().onAdvancementEarned(advancementId)
.declareFact("mymod/advancement_fact");

Generic Ingress

For custom trigger types, use the generic ingress entry point with typed targets:

this.ingress().on(myTriggerType, target)
.declareFact("mymod/my_hook");

The target type must match the trigger type's target type (e.g. Identifier for entry/advancement triggers, ItemStackTemplate for item triggers).

See Custom Research Hooks for details.

Multi-stage nodes

var stage1Ref = this.stageRef("mymod/stage1");
var stage2Ref = this.stageRef("mymod/stage2");

this.nodeBuilder(this.node("mymod/my_node"))
.withFact(someFact)
.withStage(ResearchStageSpec.valuesOnly(stage1Ref, List.of(
new ResearchNodeSpec.ValueRequirement(someValue, 10)
)))
.withStage(ResearchStageSpec.valuesOnly(stage2Ref, List.of(
new ResearchNodeSpec.ValueRequirement(someValue, 25)
)))
.build();

Toast notifications

var toast = new ResearchToastDefinition(
"research_toast.mymod.node_unlocked", // title key
List.of(), // title args
"research_toast.modonomicon.research.node", // description key
someIcon // optional icon
);

this.nodeBuilder(this.node("mymod/my_node"))
.withToast(toast)
.build();

Config

  • ClientConfig.showResearchToasts (default: true) — controls toast notifications for research events