Repository navigation
Writing an Addon
Since JustQuests 0.4.6, other mods can add their own objective types. The Create Addon is built this way, and its source code is a complete example.
This page is for mod developers. It applies to the mod builds, not to the plugin.
-
Write the objective as a class that implements
QuestObjective, with a codec for its JSON fields. -
Register it with
QuestObjective.registerwhile your mod loads, before any quest is read. -
Count it by calling
QuestProgressService.advancewhen the thing happens in the game.
public record PolishGemObjective(ItemMatcher item, int count, boolean distinct) implements QuestObjective {
public static final String TYPE_ID = "mymod:polish_gem";
public static final MapCodec<PolishGemObjective> MAP_CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
ItemMatcher.CODEC.fieldOf("item").forGetter(PolishGemObjective::item),
Codec.INT.fieldOf("count").forGetter(PolishGemObjective::count),
Codec.BOOL.optionalFieldOf("distinct", false).forGetter(PolishGemObjective::distinct)
).apply(instance, PolishGemObjective::new));
@Override
public String typeId() {
return TYPE_ID;
}
@Override
public int requiredCount() {
return count;
}
/** Plain English, for logs and diagnostics. */
@Override
public String displayName() {
return "Polish " + count + "x " + item.label();
}
/** With the count: /quest list and /quest progress show this. */
@Override
public Component display() {
return Component.translatable("mymod.goal.polish_count", count, item.name());
}
/** Without the count: the quest book and the tracker show "5/8" in front of it. */
@Override
public Component goal() {
return Component.translatable("mymod.goal.polish", item.name());
}
/** The item the quest book shows, or null for a plain book. */
@Override
public Item icon() {
List<Item> items = item.items();
return items.isEmpty() ? null : items.get(0);
}
}goal() and icon() are optional. Without them, the book shows display() and a plain book icon.
label and group work on your objective without any extra code, because JustQuests reads them itself.
@Mod("mymod")
public final class MyMod {
public MyMod() {
QuestObjective.register(PolishGemObjective.TYPE_ID, PolishGemObjective.MAP_CODEC);
}
}Tell JustQuests how much an event adds to each objective. Return 0 for objectives it isn't about:
QuestProgressService.advance(player, QuestProgressService.kind(stack), obj ->
obj instanceof PolishGemObjective p && p.item().matches(stack) ? stack.getCount() : 0);The second argument, the kind, is what makes distinct work: it names the item, block or mob this event is about. Use QuestProgressService.kind(...) with an ItemStack, a Block or an EntityType. There is also a version without a kind, for events that aren't about one kind of thing.
Accepted quests, team quests, completion messages and rewards are all handled for you.
Require JustQuests 0.4.6 or newer on both sides. On NeoForge, in neoforge.mods.toml:
[[dependencies.mymod]]
modId="justquests"
type="required"
versionRange="[0.4.6,)"
ordering="AFTER"
side="BOTH"JustQuests only needs to be on the compile classpath, not inside your jar.
- On the server: quests that use your objective are skipped, with a message in the log.
- On a client: those quests stay off the quest book, and the rest of the book works.
So it is safe for a pack to contain quests for an optional addon, as long as the log message is acceptable.
Modrinth · CurseForge · Discord · Issues
Getting started
Writing quests
Running a server
Addons
Help