Naruto Destination API
Official server-side add-on API for Naruto Destination. Register content, read and write player data, hook gameplay events, and reuse the same rule gates the base mod uses.
What You Can Build
NarutoDestinationApi nd = NarutoDestinationApi.get();
Setup
The API artifact is compile-time only. Runtime classes ship inside the Naruto Destination
mod jar, so your add-on must load after narutodestination.
repositories {
maven { url = "<the NarutoDestination maven>" }
}
dependencies {
compileOnly "de.yatzufusa.narutodestination:narutodestination-api:0.13.0"
}
[[dependencies.yourmodid]]
modId = "narutodestination"
type = "required"
ordering = "AFTER"
Register a Jutsu
Extend CustomJutsu, provide a flat global id, define its tuning, then register
it from your mod constructor. Prefix ids with your mod id.
public final class ShadowStitchJutsu extends CustomJutsu {
public ShadowStitchJutsu() {
super("mymod_shadow_stitch", "Shadow Stitch", "minecraft:ink_sac",
JutsuDefinition.builder()
.require("clan:nara")
.cooldown(200)
.chakra(180, 0.02)
.damage(20.0).scale("ninjutsu", 0.04)
.build());
}
@Override
public boolean onCast(JutsuCaster caster) {
ServerLevel level = (ServerLevel) caster.entity().level();
// Apply your server-side effect here.
return true;
}
}
public MyAddon(IEventBus modBus) {
NarutoDestinationApi nd = NarutoDestinationApi.get();
nd.jutsus().register(new ShadowStitchJutsu());
nd.skillTree().registerNode("mymod_shadow_stitch",
SkillNodeDefinition.jp("Shadow Stitch", 4, -20, -4,
"minecraft:ink_sac", "mymod_shadow_stitch", List.of("clan")));
}
- Generated config under
config/narutodestination/jutsu/ - Jutsu Picker and scroll binding presence
- Validated costs, requirements, cooldowns, effects, and mastery
- Skill-tree progression through
grants_jutsu
Player Data
NinjaPlayer is a live server-side view over one player's Naruto Destination
data. Mutators validate, clamp, sync, and persist through the mod's normal save path.
NarutoDestinationApi nd = NarutoDestinationApi.get();
NinjaPlayer ninja = nd.player(serverPlayer);
int chakra = ninja.resource(ResourceKind.CHAKRA);
ninja.grantRelease("fire");
ninja.learnJutsu("fireball");
ninja.addMasteryXp("fireball", 50);
ninja.setStat(NinjaStats.NINJUTSU, 120);
ninja.addExperience(500);
| resource(kind) | Read chakra, sen, stamina, or another resource pool. |
| consumeResource(kind, amount) | Spend a pool all-or-nothing. |
| grantRelease(id) | Give nature releases, kekkei genkai, or dojutsu flags. |
| learnJutsu(id) | Teach a jutsu so it can be bound in the picker. |
| chargeRyo(amount) | Charge player money all-or-nothing. |
| stageMode(id, delta) | Move a Mode Wheel mode through the validated path. |
Events
Events are posted on the NeoForge game bus. Use cancelable pre-events to veto work before state changes, and post-events to mirror completed changes into external systems.
@SubscribeEvent
static void onCast(JutsuCastEvent.Pre event) {
if (inSafeZone(event.caster().entity())) {
event.setCanceled(true);
}
}
@SubscribeEvent
static void onJoin(AffiliationJoinEvent event) {
if (housing(event.server(), event.affiliationId()) <= members(event.affiliationId())) {
event.refuse("There is nowhere to live in " + event.affiliationId() + " yet.");
}
}
JutsuCastEvent.Pre/PostModeStageEvent.Pre/PostNinjaPlayerLoadedEventSkillNodeUnlockEventQuestAcceptedEventandQuestCompletedEventDialogNodeShownEventandDialogReplyEventAffiliationJoinEventAffiliationMembershipChangedEventAffiliationRankChangedEventAffiliationTitleChangedEventElectionStartedEventandElectionConcludedEventScrollBindEvent
Combat
CombatApi gives add-ons the same PvP gate, damage attribution, personalized
i-frames, and jutsu-block durability behavior used by built-in jutsus.
CombatApi combat = nd.combat();
if (combat.canAffect(caster, target)) {
combat.hurtWithIFrames(level, target,
combat.jutsuDamage(level, caster, "fire"),
6.0F,
caster,
combat.jutsuIFrameKey("mymod_shadow_stitch"),
10);
}
combat.damageJutsuBlocks(level, impact, 2.5, 30.0F);
combat.setPvpZoneRule((attacker, defender) -> !myTerritory.protects(defender));
Territory
Territory queries are read-only snapshots. Re-query instead of caching, because site radius can change when village membership changes.
TerritoryApi map = nd.territory();
map.siteAt(level, pos).ifPresent(site ->
LOGGER.info("{} ({}) held by {}, r={}m",
site.id(), site.kind(), site.affiliation(), site.radius()));
if (map.isInsideAffiliation(player, "konoha")) {
// Home turf logic.
}
map.nearestSite(level, pos).ifPresent(frontier ->
player.displayClientMessage(Component.literal(
"%.0fm to %s".formatted(frontier.distanceTo(pos), frontier.id())), true));
Affiliations, Merit, and Elections
The affiliation API covers villages, organizations, membership, ranks, titles, merit, treasury balances, and Kage or Akatsuki leadership seats.
AffiliationApi villages = nd.affiliations();
villages.meritOf(server, player).ifPresent(m -> {
LOGGER.info("{} merit, next {} at {}{}",
m.merit(), m.nextRankId(), m.nextThreshold(),
m.eligible() ? " (eligible)" : "");
});
villages.addMerit(server, player, 3, "escort_delivered");
villages.seatHolder(server, "konoha").ifPresent(kage -> greet(kage));
ElectionApi votes = nd.elections();
votes.active(server, "konoha").ifPresent(e ->
LOGGER.info("{} election, {} candidates, closes {}",
e.kind(), e.candidates().size(), e.endsAtMillis()));
String refusal = votes.start(server, "konoha", 24);
votes.history(server, "konoha", 5);
NPCs, Quests, and Dialogs
NPCs can be found or spawned, dialogs can be opened through the mod's own conversation session, and quests are given through the same gate used by boards and dialogs.
NpcApi npcs = nd.npcs();
QuestApi quests = nd.quests();
DialogApi dialogs = nd.dialogs();
NpcView guard = npcs.spawn(level, pos, "konoha_jonin").orElseThrow();
guard.talk(player);
dialogs.open(player, guard.entity(), "my_briefing");
quests.give(player, "bandit_cull")
.ifPresent(reason -> player.sendSystemMessage(Component.literal(reason)));
if (dialogs.gate(player).test("quest_done:bandit_cull")) {
// They finished it.
}
Quests and dialog nodes are server config, not API registrations:
config/narutodestination/quest/ and
config/narutodestination/dialog/.
Permissions
Server gates use NeoForge PermissionAPI nodes under
narutodestination.. Ask the same question the mod asks, and your add-on
follows the server's permissions plugin setup.
PermissionApi perms = nd.permissions();
if (!perms.has(player, "admin.npc_editor")) {
return;
}
String node = perms.register("myaddon.arena.edit", "Edit arena layouts");
// narutodestination.myaddon.arena.edit
Package Map
apiNarutoDestinationApi entry point.api.castJutsuCaster, the entity-agnostic casting adapter.api.jutsuCustomJutsu, JutsuApi, JutsuView, JutsuDefinition, requirements, mastery formulas.api.playerNinjaPlayer, NinjaStats, ResourceKind.api.modeModeApi and ModeDefinition.api.skillSkillTreeApi, SkillNodeDefinition, NodeKind.api.combatCombatApi and JutsuBlockInfo.api.affiliationVillages, ranks, titles, treasury, merit, and seats.api.electionLive elections, history, petitions, and operator doors.api.territoryTerritoryApi and SiteInfo for claim queries.api.npcNpcApi and NpcView.api.questQuestApi and QuestInfo.api.dialogDialogApi and DialogInfo.api.permissionPermissionApi for mod nodes and add-on nodes.api.eventNeoForge events for casts, modes, quests, dialogs, villages, elections, and scrolls.api.genjutsuGenjutsuApi and GenjutsuEffects.