Build a Spell — Cross-Mod Integration Guide
This document describes how other NeoForge mods can interact with Build a Spell’s player attribute system to modify mana, spell power, and casting behavior.
Dependency Setup
Add buildaspell as a dependency in your neoforge.mods.toml:
[[dependencies.yourmodid]]
modId = "buildaspell"
type = "required" # or "optional" if you check at runtime
versionRange = "[1.0,)"
ordering = "AFTER"
side = "BOTH"
For compile-time access, add the Cyber’s Build A Spell jar to your build.gradle:
dependencies {
compileOnly files("libs/buildaspell-<version>.jar")
}
Custom Attributes
All three attributes are registered on EntityType.PLAYER and live in the buildaspell namespace. They are standard vanilla Attributes backed by RangedAttribute, so any system that applies AttributeModifiers (equipment, potions, mob effects, events) works out of the box.
| Registry ID | Default | Min | Max | Description |
|---|---|---|---|---|
buildaspell:mana_pool |
100.0 | 0.0 | 10,000.0 | Maximum mana capacity |
buildaspell:mana_regen |
5.0 | 0.0 | 1,000.0 | Mana regenerated per tick cycle |
buildaspell:spell_power |
10.0 | 0.0 | 1,000.0 | Spell damage and effectiveness scaling |
Enchantment bonuses from Cyber’s Build A Spell’s own enchantments are applied on top of the attribute value, so attribute modifiers and enchantments stack naturally.
Accessing Attributes at Compile Time
If you depend on Cyber’s Build A Spell directly, you can reference the DeferredHolder fields:
import buildaspell.registry.ModAttributes;
// Read current effective value (includes all modifiers)
double mana = player.getAttributeValue(ModAttributes.MANA_POOL);
double regen = player.getAttributeValue(ModAttributes.MANA_REGEN);
double power = player.getAttributeValue(ModAttributes.SPELL_POWER);
Accessing Attributes by Registry ID (No Hard Dependency)
If you want to keep Cyber’s Build A Spell as an optional dependency, look up the attribute holders at runtime using the registry:
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.ai.attributes.Attribute;
Holder<Attribute> manaPool = BuiltInRegistries.ATTRIBUTE
.getHolder(Identifier.parse("buildaspell:mana_pool"))
.orElse(null);
if (manaPool != null) {
double value = player.getAttributeValue(manaPool);
}
Adding Attribute Modifiers
Transient Modifiers (Runtime Only)
Transient modifiers are not saved and are removed when the player logs out or the source is cleared. Useful for temporary buffs from events, abilities, or auras.
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
Identifier modifierId = Identifier.parse("yourmod:mana_boost");
AttributeInstance instance = player.getAttribute(ModAttributes.MANA_POOL);
if (instance != null && instance.getModifier(modifierId) == null) {
instance.addTransientModifier(new AttributeModifier(
modifierId,
50.0, // +50 mana
AttributeModifier.Operation.ADD_VALUE // flat addition
));
}
Permanent Modifiers (Saved with Player)
Permanent modifiers persist across sessions. Useful for progression systems or permanent unlocks.
AttributeInstance instance = player.getAttribute(ModAttributes.MANA_POOL);
if (instance != null && instance.getModifier(modifierId) == null) {
instance.addPermanentModifier(new AttributeModifier(
modifierId,
50.0,
AttributeModifier.Operation.ADD_VALUE
));
}
Removing Modifiers
AttributeInstance instance = player.getAttribute(ModAttributes.MANA_POOL);
if (instance != null) {
instance.removeModifier(modifierId);
}
Modifier Operations
All three vanilla AttributeModifier.Operation types work:
| Operation | Effect | Example |
|---|---|---|
ADD_VALUE |
Flat addition to base | +50 mana pool |
ADD_MULTIPLIED_BASE |
Multiplied by base, then added | +0.2 = +20% of base |
ADD_MULTIPLIED_TOTAL |
Multiplied by total after all other ops | +0.1 = +10% of final |
Evaluation order: (base + ADD_VALUE) * (1 + sum(ADD_MULTIPLIED_BASE)) * (1 + sum(ADD_MULTIPLIED_TOTAL))
Common Integration Patterns
Custom Item That Boosts Mana Pool
Apply the modifier when the item is equipped, remove it when unequipped. The standard way is to add it to the item’s AttributeModifiers component via data or in code:
// In your item's constructor or via data generation
ItemAttributeModifiers modifiers = ItemAttributeModifiers.builder()
.add(ModAttributes.MANA_POOL,
new AttributeModifier(
Identifier.parse("yourmod:staff_mana"),
25.0,
AttributeModifier.Operation.ADD_VALUE),
EquipmentSlotGroup.MAINHAND)
.build();
Mob Effect That Increases Spell Power
public class SpellPowerEffect extends MobEffect {
public SpellPowerEffect() {
super(MobEffectCategory.BENEFICIAL, 0x7B68EE);
addAttributeModifier(
ModAttributes.SPELL_POWER,
Identifier.parse("yourmod:spell_power_effect"),
5.0, // +5 per level
AttributeModifier.Operation.ADD_VALUE
);
}
}
Notes
- Modifier IDs must be unique
Identifiers scoped to your mod (e.g.,yourmod:my_modifier). Adding a modifier with a duplicate ID to the same attribute instance is a no-op. - Attribute values are automatically clamped to the min/max range defined by the
RangedAttribute. - These attributes are only registered on players. They are not present on other
LivingEntitytypes. - All attribute reads happen server-side. On the client, synced attribute data is available through the same
player.getAttributeValue()calls.