This page covers the current startup registration surface exposed by MnaJS.
mna:factions
Register with StartupEvents.registry("mna:factions", ...).
Use it for new factions with script-configurable grimoire, token, sounds, icon, colors, structure, and casting-resource routing.
Notable builder methods:
factionGrimoire(MnaItemId)tokenItem(MnaItemId)raidSound(MnaSoundId)hornSound(MnaSoundId)factionIcon(MnaTexture)manaweaveRGB("rgb(116, 182, 79)")sanctumStructure(MnaStructureId)castingResources(MnaCastingResourceId...)factionIconTextureSize(int)maxModifierBonus(Attribute, float)minModifierBonus(Attribute, float)resourceSelector((player, availableResources) => ...)
Example:
StartupEvents.registry("mna:factions", (event) => {event.create("kubejs:verdant_court", "basic").factionGrimoire("minecraft:book").tokenItem("minecraft:emerald").raidSound("minecraft:event.raid.horn").factionIcon("mna:textures/gui/cantrips/ward.png").manaweaveRGB("rgb(116, 182, 79)").sanctumStructure("mna:multiblock/council_circle_of_power").castingResources("mna:mana", "mna:council_mana");});
Notes:
manaweaveRGBaccepts frontend-style color strings.sanctumStructureis typed as a structure id, not a raw path hack.resourceSelectoris the deep hook for choosing which casting resource a player should use.
mna:ritual-effects
Register with StartupEvents.registry("mna:ritual-effects", ...).
Use it for the runtime handler that attaches behavior to a ritual recipe id.
Notable builder methods:
ritualName(MnaRitualId)applicationTicks(int | callback)applyEffect((context) => boolean)matchReagents(...)modifyReagents(...)canStart(...)applyStartCheckInCreative(boolean)particles(...)loopSound(...)
Example:
StartupEvents.registry("mna:ritual-effects", (event) => {/*** @type {Internal.CustomRitualEffect$Builder}*/const builder = event.create("kubejs:lightning_ritual_effect", "basic");builder.ritualName("kubejs:lightning_ritual").applicationTicks(20).applyEffect((context) => {const level = context.getLevel();if (level == null) return false;const lightning = EntityType.LIGHTNING_BOLT.create(level);if (lightning == null) return false;lightning.setPos(context.getCenter().x, context.getCenter().y, context.getCenter().z);level.addFreshEntity(lightning);return true;});});
Notes:
- Keep the builder in a typed local for Probe completion.
ritualName(...)should match the ritual recipe id you actually generate.
mna:components type basic
Register with StartupEvents.registry("mna:components", ...) and event.create(id, "basic").
Use it for a general spell effect component with fully scriptable applyEffect.
Notable builder methods:
guiIcon(MnaTexture)affinity(Affinity)initialComplexity(float)addAttribute(Attribute, base, min, max, step, complexity)baselineCooldown(int)soundEffect(MnaSoundId)factionRequirement(MnaFactionId)addReagent(MnaItemId, ...)addOptionalReagent(MnaItemId, ...)applyEffect(...)spawnParticles(...)canBeCastAt(...)getDescriptionTooltip(...)
Example:
StartupEvents.registry("mna:components", (event) => {/*** @type {Internal.CustomSpellEffect$Builder}*/const builder = event.create("kubejs:arcane_pulse", "basic");builder.guiIcon("mna:textures/gui/cantrips/ignite.png").affinity(Affinity.ARCANE).baselineCooldown(20).soundEffect("minecraft:entity.allay.item_given").factionRequirement("mna:council").addReagent("minecraft:lapis_lazuli").applyEffect((source, target, modificationData, context) => {return ComponentApplicationResult.SUCCESS;});});
mna:components type damage
Use event.create(id, "damage").
This is the damage-oriented spell effect surface. It inherits most of the common component API and adds damage-specific attributes and callbacks.
Notable additions:
addDamageAttribute(base, min, max, step, complexity)damageEntity((source, target, damage, context) => ...)isTargetFriendly(...)magnitudeHealthCheck(...)
Example:
/*** @type {Internal.CustomDamageComponent$Builder}*/const builder = event.create("kubejs:searing_arc", "damage");builder.affinity(Affinity.FIRE).soundEffect("minecraft:entity.blaze.shoot").addDamageAttribute(4.0, 2.0, 8.0, 1.0, 1.0).addOptionalReagent("minecraft:blaze_powder").damageEntity((source, target, damage, context) => {return ComponentApplicationResult.SUCCESS;});
mna:components type potion
Use event.create(id, "potion").
This is the potion-effect component surface.
Notable builder methods:
effect(MnaMobEffectId)modifiesDuration(boolean)addDurationAttribute(base, min, max, step, complexity)modifiesMagnitude(boolean)addMagnitudeAttribute(base, min, max, step, complexity)addPermanencyReagent(MnaItemId)permanentFor(MnaFactionId...)
Example:
/*** @type {Internal.CustomPotionEffectComponent$Builder}*/const builder = event.create("kubejs:swiftstep", "potion");builder.affinity(Affinity.WIND).effect("minecraft:speed").modifiesDuration(true).addDurationAttribute(60, 20, 180, 20, 1.0).modifiesMagnitude(true).addMagnitudeAttribute(1, 1, 3, 1, 1.25).addPermanencyReagent("minecraft:ghast_tear").permanentFor("mna:fey");
mna:shapes
Register with StartupEvents.registry("mna:shapes", ...).
Use it for custom spell target selection logic.
Notable builder methods:
guiIcon(MnaTexture)initialComplexity(float)spawnsTargetEntity(boolean)isChanneled(boolean)baselineCooldown(int)affectsCaster(boolean)addReagent(MnaItemId, ...)target((source, level, modificationData, recipe) => SpellTarget[])targetNPCCast(...)allowChanneledComponents(...)maxChannelTime(...)
Example:
StartupEvents.registry("mna:shapes", (event) => {event.create("kubejs:anchored_burst", "basic").guiIcon("mna:textures/gui/cantrips/ward.png").initialComplexity(1.5).spawnsTargetEntity(false).isChanneled(false).affectsCaster(true).target((source, level, modificationData, recipe) => {return [SpellTarget.NONE];});});
mna:modifiers
Register with StartupEvents.registry("mna:modifiers", ...).
Use it for custom spell modifiers with explicit attribute coverage and craftability checks.
Notable builder methods:
basedOn(Modifier)guiIcon(MnaTexture)attributes(Attribute...)addAttribute(Attribute)requiredXPForRote(int)tier(int)isUseableByPlayers(boolean)isCraftable(...)canBeCastAt(...)
Example:
StartupEvents.registry("mna:modifiers", (event) => {/*** @type {Internal.CustomModifier$Builder}*/const builder = event.create("kubejs:steady_focus", "basic");builder.guiIcon("mna:textures/gui/cantrips/ignite.png").attributes(Attribute.RANGE, Attribute.PRECISION).tier(1).requiredXPForRote(75);});
mna:construct_task
Register with StartupEvents.registry("mna:construct_task", ...).
Current support depth is for task metadata plus reuse of an existing AI implementation.
Notable builder methods:
basedOn(ConstructTask)icon(MnaTexture)aiTask(ConstructTask)outputs(int)lodestarAssignable(boolean)lowTierAssignable(boolean)condition(boolean)
Example:
StartupEvents.registry("mna:construct_task", (event) => {/*** @type {Internal.CustomConstructTask$Builder}*/const builder = event.create("kubejs:scripted_wait", "basic");builder.basedOn(MnaConstructTasks.WAIT).icon("mna:textures/gui/cantrips/ignite.png").outputs(2).lowTierAssignable(true);});
Notes:
- You can reuse an existing AI class from another task.
- A brand-new JS-authored
ConstructAITaskimplementation is not currently exposed as a first-class script surface.
mnajs:construct_material
Register with StartupEvents.registry("mnajs:construct_material", ...).
This is the custom construct material registry added by MnaJS.
Notable builder methods:
basedOn(MnaConstructMaterialId)texture(MnaTexture)health(int)speed(float)knockbackResistance(float)explosionResistance(float)equivalentTier(Tier)cooldownMultiplier("cast_spell", float)armorBonus("head", int)toughnessBonus("torso", int)damageBonus(float)rangedDamageBonus(float)rangedManaCost(float)manaStorage(int)intelligenceBonus(int)backpackCapacityBoost(int)castingTierEquivalent(int)deathLoot(...)modelSet(String)headModels(...)torsoModels(...)legModels(...)armModels(...)
Example:
StartupEvents.registry("mnajs:construct_material", (event) => {/*** @type {Internal.CustomConstructMaterial$Builder}*/const builder = event.create("kubejs:moonsteel", "basic");builder.basedOn("mna:iron").texture("mna:textures/entity/animated_construct/armor_iron.png").modelSet("iron").health(5).damageBonus(2.0).manaStorage(750).cooldownMultiplier("cast_spell", 0.85).armorBonus("head", 3).toughnessBonus("torso", 1);});
Notes:
ConstructSlotandConstructCapabilitycan be passed as typed ids or stable lower-case strings.- This custom registry is separate from M&A's built-in hardcoded material list, but MnaJS bridges registered materials into M&A lookup and model registration.
item type construct_part
Register with StartupEvents.registry("item", ...) and event.create(id, "construct_part").
Use it for custom construct parts that reference built-in or custom construct materials.
Notable builder methods:
basedOn(ItemConstructPart)material(MnaConstructMaterialId)slot(MnaConstructSlotId)modelMutex(int)- stat overrides such as
armor,toughness,attackDamage,manaCapacity - capability controls such as
actionSpeed,enabledCapabilities,addCapability attackSpeedModifier(int)inventorySizeBonus(int)backpackCapacityBoost(int)allowInLoot(boolean)
Example:
StartupEvents.registry("item", (event) => {/*** @type {Internal.CustomConstructPartItem$Builder}*/const builder = event.create("kubejs:moonsteel_basic_head", "construct_part");builder.material("kubejs:moonsteel").slot("head").modelMutex(ConstructMutexHead.BASIC).armor(3).intelligenceBonus(10);});
Notes:
- A part can reference a custom material registered in the same startup load.
- Custom material lookup is intentionally lazy, so same-pass registration is supported.
- Prefer string ids like
"head"and"cast_spell"or typed ids, not raw catch-all values.
item type mana_battery_item
Use it for mana-storage items with Curios and inventory tick hooks.
Notable builder methods:
maxMana(float)manaPerTick(int)manaPerOperation(float)curiosTick((entity, index, stack) => boolean)tickEffect((stack, player, level, slot, mana, selected) => boolean)onUseTick((level, living, stack, remainingUseDuration) => ...)
Example:
event.create("kubejs:reserve_battery", "mana_battery_item").maxMana(500).manaPerTick(10).manaPerOperation(25).curiosTick((entity, index, stack) => true).tickEffect((stack, player, level, slot, mana, selected) => {if (selected && mana >= 25) {PlayerMagic.addMana(player, 1);return true;}return false;});
item type tiered_item
Use it for script-defined mana items with faction, ire, tooltip, and player-use behavior.
Notable builder methods:
tier(int)faction(MnaFactionId)minIre(float)maxIre(float)sneakBypass(boolean)doesSneakBypassUse(...)appendHoverText(...)usedByPlayer(...)
Example:
event.create("kubejs:court_signet", "tiered_item").tier(2).faction("mna:council").minIre(0.0).maxIre(0.02).sneakBypass(true).usedByPlayer((player) => {PlayerMagic.addMana(player, 10);});
block type spell_interactible
Use it for blocks that react when struck by an M&A spell.
Notable builder method:
onHitBySpell((level, pos, spell) => boolean)
Example:
event.create("kubejs:spell_echo_anchor", "spell_interactible").onHitBySpell((level, pos, spell) => true);
block type manaweave_notifiable
Use it for blocks that receive manaweave pattern notifications.
Notable builder method:
onNotify((level, pos, state, patterns, caster) => boolean)
Example:
event.create("kubejs:manaweave_listener", "manaweave_notifiable").onNotify((level, pos, state, patterns, caster) => {return patterns != null && !patterns.isEmpty();});