🌸 Abloom API Mod

Elemental Combat System for Minecraft

Overview

Abloom is a comprehensive combat modification that introduces an elemental resonance system with 14 unique elements. Each element has its own accumulation mechanics, special status effects, and strategic applications.

Key Features:

Mechanics

Element Types & Resonance Effects

Element Resonance Effect Duration
PHYSICAL Physical resonance explosion, applies Rupture effect (target's armor reduced by 20%) 12 seconds (240 ticks)
FIRE Fire resonance explosion, applies Burning effect 12 seconds (240 ticks)
WIND Wind resonance explosion, applies Windswept effect. Applying any other elemental damage (except Wind) while this effect is active triggers the corresponding resonance explosion and can be triggered once every 5 seconds, and the duration of the resonance effect triggered by wind is half of its original value 15 seconds (300 ticks)
WATER Water resonance explosion, applies Wetness effect (increases target resonance accumulation by 50%) 15 seconds (300 ticks)
EARTH Earth resonance explosion, applies Stun effect (target cannot deal damage or move) 5 seconds (100 ticks)
ICE Ice resonance explosion, applies Freeze effect 14 seconds (280 ticks)
ELECTRIC Electric resonance explosion, applies Shock effect (target inflicts 20% less damage and has 20% attack speed reduction) 14 seconds (280 ticks)
ENERGY Energy resonance explosion, applies Overload effect (target's max health reduced by 15% and damage taken increased by 20%) 14 seconds (280 ticks)
NATURAL Natural resonance explosion, applies Bloom effect (reduces target's NATURAL resistance by 35% and PHYSICAL resistance by 15% and deals NATURAL damage over time) 12 seconds (240 ticks)
QUANTUM Quantum resonance explosion, applies Break effect (target's armor reduced by 100%) 8 seconds (160 ticks)
ETHER Ether resonance explosion, applies Corruption effect (reduces target's resistance to all damage types by 20% and deals ETHER damage over time) 12 seconds (240 ticks)
LIGHT Light resonance explosion, applies Dispersion effect that increases damage taken based on incoming damage element type: Physical +15%, Fire +15%, Wind +30%, Water +30%, Earth +15%, Ice +15%, Electric +30%, Energy +15%, Natural +15%, Quantum +15%, Ether +15%, Light +30%, Shadow +20%, Prismatic +30% 14 seconds (280 ticks)
SHADOW Shadow resonance explosion, applies Eclipse effect (target's max health reduced by 5% and armor reduced by 10%) 14 seconds (280 ticks)
PRISMATIC Prismatic damage does NOT accumulate resonance points. When the target has the Prism effect, prism damage converts to the stored elemental damage type. If no Prism effect is active, hitting a target with any resonance effect applies Prism effect for 40 seconds, and converts subsequent prism damage to that elemental damage type. 40 seconds (800 ticks)

Damage Priority System

The damage priority system resolves conflicts when multiple mods modify damage simultaneously. Modifiers are sorted by priority (highest to lowest) and called in registration order (FIFO) for equal priorities.

Priority Value Description When to Use
HIGHEST 300 Highest priority For critically important modifications
HIGH 200 High priority When processing BEFORE Abloom
NORMAL 0 Default priority For simple modifiers
LOW -100 Low priority (Abloom uses this) When processing AFTER most mods
LOWEST -300 Very low priority When processing last
Note: Abloom API uses priority LOW (-100) for damage processing. Mods with priority > 0 are called BEFORE Abloom, while mods with priority <= 0 are called AFTER Abloom.
Damage Formula:
finalDamage = currentDamage Γ— M_effect Γ— (1 βˆ’ effectiveResist) Γ— (1 + B_element) Γ— C_crit Γ— M_threshold

Where:
M_effect = SHOCK Γ— OVERLOAD Γ— BLOOM Γ— DISPERSION  |  effectiveResist = (R_resist + R_mod + R_armor) βˆ’ P_shred
R_resist = 0.0 / 0.5 / βˆ’0.5 (base tag: ZERO / RESIST / WEAKNESS)  |  R_mod = {ELEMENT}_RESIST_MOD (βˆ’1 to 1)
B_element = {ELEMENT}_DMG_BONUS (βˆ’1 to 1)  |  P_shred = {ELEMENT}_RES_SHRED (0 to 1)
R_armor = sum of armor resistance components (βˆ’0.99 to 0.99)  |  C_crit = 1.0 or (1.0 + totalCritDamage) Γ— 2.0 (multi-crit)
M_threshold = baseMultiplier + resonanceFrequency Γ— 0.01, where baseMultiplier = 2.00 / 2.25 / 2.50 (when triggered resonance explosion)

Resonance Points: pointsToAdd = round((baseAccum + effectiveAccumMultiplier) Γ— (1 βˆ’ effectiveResist))
effectiveAccumMultiplier = weaponAccum Γ— (1 + buildup) Γ— (1 + wetnessBonus)
effectiveResist is the same for both damage and accumulation β€” all resistance sources are combined

Status Effects

Abloom adds 16 custom status effects that can be applied through elemental resonance or other means:

Effect ID Description Color
Burn abloom:burn Deals periodic fire damage over time #FF5500
Wetness abloom:wetness Increases target resonance accumulation by 50% #0080FF
Stun abloom:stun Target cannot deal damage or move #8B4513
Freeze abloom:freeze Immobilizes and deals periodic ice damage #00BFFF
Shock abloom:shock Target inflicts 20% less damage and has 20% attack speed reduction #FF19FF
Break abloom:break Target's armor reduced by 100% #9400D3
Rupture abloom:rupture Target's armor reduced by 20% #C0C0C0
Bloom abloom:bloom Reduces NATURAL resistance by 35% and PHYSICAL resistance by 15% and deals NATURAL damage over time #32CD32
Resonance Gain abloom:resonance_gain Increases resonance frequency by 60 and resonance accumulation by +20% #FFD700
Overload abloom:overload Target's max health reduced by 15% and damage taken increased by 20% #FF00FF
Windswept abloom:windswept Applying other elemental damage triggers resonance explosion #00FFFF
Corruption abloom:corruption Reduces resistance to all damage types by 20% and deals ETHER damage over time #24B3A7
Taunt abloom:taunt Target will be attacked by hostile and neutral mobs #9B2D30
Dispersion abloom:dispersion Damage taken by target increases damage taken based on incoming damage element type: Physical +15%, Fire +15%, Wind +30%, Water +30%, Earth +15%, Ice +15%, Electric +30%, Energy +15%, Natural +15%, Quantum +15%, Ether +15%, Light +30%, Shadow +20%, Prismatic +30% #FFF1A5
Eclipse abloom:eclipse Target's max health reduced by 5% and armor reduced by 10% #4B0082
Critical Gain abloom:critical_gain +40% crit damage #FFD700
Prism abloom:prism Applied when Prism damage hits a target with an active resonance effect. Stores the converted element type so prism damage transforms into that element. #FFFFFF
Fluorescence abloom:fluorescence Beneficial effect stored on the attacker. When the attacker deals prismatic damage, Fluorescence is consumed and applies a corresponding Prism effect to the target, converting future prismatic damage to the stored element type. Lasts 60 seconds (1200 ticks). Obtained by killing an entity that has an active Prism effect. #FFD700
Suppression abloom:suppression Reduces critical damage by 30% #EE204D
Bleeding abloom:bleeding Reduces speed by 25% and deals physical damage when the entity is jumping #CC0033
Reinforcement abloom:reinforcement Adds 6 points to armor #6B8BA4

Weapon System

Weapons Registration

Weapons can be registered with elemental properties. Multi-stage weapons can have up to 4 attack stages, each with its own element type and accumulation multiplier. Stages reset after cooldown based on attack speed.

Multi-Stage Registration Example:

// Register a 2-stage weapon
ResourceLocation swordId = ResourceLocation.fromNamespaceAndPath("mymod", "dragon_sword");

// Stage 1: Fire element with 2x accumulation
ElementalWeaponRegistry.registerBuiltinWeaponWithStage(
    swordId,
    1,                              // stage number (1-4)
    ElementType.FIRE,
    2.0f,                           // accumulation multiplier
    0.15f,                          // crit chance (shared)
    0.5f                            // crit damage (shared)
);

// Stage 2: Physical element with 3x accumulation
ElementalWeaponRegistry.registerBuiltinWeaponWithStage(
    swordId,
    2,
    ElementType.PHYSICAL,
    3.0f,
    0.15f,
    0.5f
);

Single-Stage Registration Example:

For weapons that don't require multiple stages, use the simplified registration method:

// Register a simple fire staff with single-stage behavior
ResourceLocation staffId = ResourceLocation.fromNamespaceAndPath("mymod", "fire_staff");

ElementalWeaponRegistry.registerBuiltinWeapon(
    staffId,                        // weapon ID
    ElementType.FIRE,               // element type
    1.5f,                           // accumulation multiplier
    0.2f,                           // crit chance
    0.75f                           // crit damage
);

Critical Hit System

Abloom adds two custom attributes for critical hits:

Attribute ID Range Default Description
CRIT_CHANCE abloom:crit_chance -2 to 2 0 Critical hit chance (-200% to 200%). Maximum is clamped to 2.0 (200%) to enable multi-crit.
CRIT_DMG abloom:crit_dmg -10 to 10 0 Critical hit damage multiplier (-1000% to 1000%). Applied additively from entity attributes and weapon values.

Multi-Crit System

Abloom supports multi-critical hits, which deal double critical damage. The total crit chance (entity attributes + weapon values, summed additively) is clamped to a maximum of 2.0 (200%). When total crit chance exceeds 100% (1.0), any excess above 1.0 gives a chance to trigger a multi-crit, which multiplies the resulting critical damage by 2x.

How it works: If you have 150% crit chance (1.5), you're guaranteed at least one crit. The remaining 0.5 (50%) gives you a 50% chance to trigger a multi-crit, dealing double critical damage. Multi-crits are displayed with !!! in damage numbers, while normal crits show !!.
Important: Critical hits do NOT apply to resonance explosion damage. When the accumulation threshold (100 points) is reached and the resonance effect is triggered, the damage multiplier is applied without critical hit calculation. Critical hits only apply to the base damage before the resonance explosion multiplier.

Weapon Crit Values

// Get crit chance from weapon stack
float critChance = ElementalWeaponUtils.getCritChance(stack);

// Get crit damage from weapon stack
float critDamage = ElementalWeaponUtils.getCritDamage(stack);

// Register weapon with crit values
ElementalWeaponRegistry.registerWeapon(
    myItem,
    ElementType.FIRE,
    2.0f,       // accumulation
    0.25f,      // 25% crit chance
    0.75f       // 75% crit damage
);

// Get effective element type (checks enchantment override first)
ElementType element = ElementDamageHandler.getEffectiveElementType(stack);
if (element == ElementType.FIRE) {
    // Weapon has fire_aspect or flame enchantment
}

Resonance Accumulation Buildup Attribute

Abloom introduces a third custom attribute that controls how quickly elemental resonance accumulates:

Attribute ID Range Default Description
RESONANCE_ACCUMULATION_BUILDUP abloom:resonance_accumulation_buildup -1 to 1 0 Multiples the accumulation multiplier. At 0: no effect (1.0x). At 1: doubles accumulation (2.0x). At -1: disables resonance buildup (0.0x).

How It Works

The attribute value is applied as a multiplier to the effective accumulation multiplier during damage processing. The formula is:

effectiveAccumMultiplier *= (1.0f + buildupAttributeValue);

Examples

Attribute Value Multiplier Effect
0.0 (default) 1.0x No change to accumulation
0.5 1.5x +50% to accumulation speed
1.0 (max) 2.0x Doubles accumulation speed
-0.5 0.5x -50% to accumulation speed
-1.0 (min) 0.0x Completely disables resonance buildup

Setting the Attribute

import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.Attributes;
import com.auranite.abloom.init.AbloomModAttributes;

// On entity creation or modification
Entity entity = ...;
AttributeInstance buildupAttr = entity.getAttribute(
    AbloomModAttributes.RESONANCE_ACCUMULATION_BUILDUP
);
if (buildupAttr != null) {
    // Set absolute value
    buildupAttr.setBaseValue(0.5);  // +50% accumulation

    // Or add a modifier
    buildupAttr.addPermanentModifier(
        new java.util.UUID(123456, 789012),
        "mymod.buff.resonance_boost",
        0.3,
        java.util.UUID.randomUUID()
    );
}
Use Case: This attribute is useful for buffs, temporary power-ups, or mob-specific traits. For example, a boss mob might have RESONANCE_ACCUMULATION_BUILDUP = 0.5 to build resonance faster, while a cursed player debuff might set it to -0.5 to slow down resonance buildup.

Resonance Frequency (Weapon Property)

Weapons can have a resonance_frequency property that increases the damage multiplier when a resonance explosion is triggered. This property is configured in the weapon's datapack JSON.

Base Multipliers by Element

Element Base Resonance DMG Multiplier
WIND 250%
WATER 250%
PHYSICAL 225%
ELECTRIC 225%
ENERGY 225%
NATURAL 225%
LIGHT 225%
SHADOW 225%
FIRE 200%
EARTH 200%
ICE 200%
QUANTUM 200%
ETHER 200%

Resonance Frequency Bonus Attribute

Abloom introduces the RESONANCE_FREQUENCY_BONUS attribute that modifies the resonance frequency on the entity. This allows buffs, debuffs, or equipment to increase or decrease the resonance explosion damage.

Attribute ID Range Default Description
RESONANCE_FREQUENCY_BONUS abloom:resonance_frequency_bonus -500 to 500 0 Adds to the weapon's resonance_frequency. Each point = 0.01 to the final multiplier (1 unit = 1% additional resonance explosion damage).

Setting the Attribute

import com.auranite.abloom.init.AbloomModAttributes;

// Add +50 resonance frequency bonus to attacker
Entity attacker = ...;
AttributeInstance rfBonus = attacker.getAttribute(
    AbloomModAttributes.RESONANCE_FREQUENCY_BONUS
);
if (rfBonus != null) {
    rfBonus.setBaseValue(50);  // +50 resonance frequency
}

// Remove resonance frequency bonus
if (rfBonus != null) {
    rfBonus.setBaseValue(0);
}
Use Case: This attribute is useful for temporary buffs (potions, abilities), equipment bonuses, or mob-specific traits. For example, a "Resonance Amplifier" potion could grant RESONANCE_FREQUENCY_BONUS = +100 for 30 seconds, boosting LIGHT resonance from 225% to 325% damage. A debuff could set it to -50 to weaken resonance explosions.

Elemental Damage Bonus Attributes

Abloom adds 14 new attributes that directly modify damage for each element type. Each attribute has a range of -1.0 to 1.0, representing -100% to +100% damage modifier.

Attribute ID Range Default Element
FIRE_DMG_BONUS abloom:fire_dmg_bonus -1 to 1 0 FIRE
PHYSICAL_DMG_BONUS abloom:physical_dmg_bonus -1 to 1 0 PHYSICAL
WIND_DMG_BONUS abloom:wind_dmg_bonus -1 to 1 0 WIND
EARTH_DMG_BONUS abloom:earth_dmg_bonus -1 to 1 0 EARTH
WATER_DMG_BONUS abloom:water_dmg_bonus -1 to 1 0 WATER
ICE_DMG_BONUS abloom:ice_dmg_bonus -1 to 1 0 ICE
ELECTRIC_DMG_BONUS abloom:electric_dmg_bonus -1 to 1 0 ELECTRIC
ENERGY_DMG_BONUS abloom:energy_dmg_bonus -1 to 1 0 ENERGY
NATURAL_DMG_BONUS abloom:natural_dmg_bonus -1 to 1 0 NATURAL
QUANTUM_DMG_BONUS abloom:quantum_dmg_bonus -1 to 1 0 QUANTUM
ETHER_DMG_BONUS abloom:ether_dmg_bonus -1 to 1 0 ETHER
LIGHT_DMG_BONUS abloom:light_dmg_bonus -1 to 1 0 LIGHT
SHADOW_DMG_BONUS abloom:shadow_dmg_bonus -1 to 1 0 SHADOW
PRISMATIC_DMG_BONUS abloom:prismatic_dmg_bonus -1 to 1 0 PRISMATIC

How It Works

Each attribute value is applied as a multiplier to the final damage for that specific element. The formula is:

finalDamage *= (1.0f + elementDmgBonusValue);
// Example: fire_dmg_bonus = 0.3 β†’ finalDamage *= 1.3 (+30% fire damage)
// Example: ice_dmg_bonus = -0.5 β†’ finalDamage *= 0.5 (-50% ice damage)

Setting the Attribute

import com.auranite.abloom.init.AbloomModAttributes;

// Set fire damage bonus on an entity
Entity entity = ...;
AttributeInstance fireBonus = entity.getAttribute(
    AbloomModAttributes.FIRE_DMG_BONUS
);
if (fireBonus != null) {
    fireBonus.setBaseValue(0.5);  // +50% fire damage
}

// Set multiple element bonuses
AttributeInstance iceBonus = entity.getAttribute(
    AbloomModAttributes.ICE_DMG_BONUS
);
if (iceBonus != null) {
    iceBonus.setBaseValue(-0.3);  // -30% ice damage (vulnerability)
}
Use Case: These attributes are perfect for element-specific buffs/debuffs. For example, a fire potion could grant FIRE_DMG_BONUS = 0.25 for 60 seconds, while a cursed armor set could apply ICE_DMG_BONUS = -0.2 to reduce ice damage taken.

Elemental Resistance Modifier Attributes

Abloom adds 14 new attributes that directly modify elemental resistance for each element type. Each attribute has a range of -1.0 to 1.0, representing Β±100% resistance modifier.

Attribute ID Range Default Element
FIRE_RESIST_MOD abloom:fire_resist_mod -1 to 1 0 FIRE
PHYSICAL_RESIST_MOD abloom:physical_resist_mod -1 to 1 0 PHYSICAL
WIND_RESIST_MOD abloom:wind_resist_mod -1 to 1 0 WIND
EARTH_RESIST_MOD abloom:earth_resist_mod -1 to 1 0 EARTH
WATER_RESIST_MOD abloom:water_resist_mod -1 to 1 0 WATER
ICE_RESIST_MOD abloom:ice_resist_mod -1 to 1 0 ICE
ELECTRIC_RESIST_MOD abloom:electric_resist_mod -1 to 1 0 ELECTRIC
ENERGY_RESIST_MOD abloom:energy_resist_mod -1 to 1 0 ENERGY
NATURAL_RESIST_MOD abloom:natural_resist_mod -1 to 1 0 NATURAL
QUANTUM_RESIST_MOD abloom:quantum_resist_mod -1 to 1 0 QUANTUM
ETHER_RESIST_MOD abloom:ether_resist_mod -1 to 1 0 ETHER
LIGHT_RESIST_MOD abloom:light_resist_mod -1 to 1 0 LIGHT
SHADOW_RESIST_MOD abloom:shadow_resist_mod -1 to 1 0 SHADOW
PRISMATIC_RESIST_MOD abloom:prismatic_resist_mod -1 to 1 0 PRISMATIC

How It Works

Each attribute value is added to the base resistance value from the target's elemental tags. The formula is:

effectiveResist = baseResist + resistModValue;
damageMultiplier = 1.0 - effectiveResist;
// Example: baseResist = 0.5 (50% resist), resistMod = -0.3 β†’ effectiveResist = 0.2 β†’ multiplier = 0.8 (+60% damage taken)
// Example: baseResist = 0.0, resistMod = 0.4 β†’ effectiveResist = 0.4 β†’ multiplier = 0.6 (+40% resistance)

Setting the Attribute

import com.auranite.abloom.init.AbloomModAttributes;

// Set fire resistance modifier on an entity
Entity entity = ...;
AttributeInstance fireResist = entity.getAttribute(
    AbloomModAttributes.FIRE_RESIST_MOD
);
if (fireResist != null) {
    fireResist.setBaseValue(0.3);  // +30% fire resistance
}

// Reduce ice resistance (make entity more vulnerable)
AttributeInstance iceResist = entity.getAttribute(
    AbloomModAttributes.ICE_RESIST_MOD
);
if (iceResist != null) {
    iceResist.setBaseValue(-0.2);  // -20% ice resistance
}
Use Case: These attributes modify how much damage the target takes from a specific element. A positive value increases resistance (less damage), while a negative value decreases resistance (more damage). Useful for debuffs that weaken a target's defenses or buffs that enhance their elemental protection.

Elemental Resistance Shred Attributes

Abloom adds 14 new attributes that shred (reduce) the target's effective resistance. Each attribute has a range of 0 to 1, representing 0% to 100% resistance shred.

Attribute ID Range Default Element
FIRE_RES_SHRED abloom:fire_res_shred 0 to 1 0 FIRE
PHYSICAL_RES_SHRED abloom:physical_res_shred 0 to 1 0 PHYSICAL
WIND_RES_SHRED abloom:wind_res_shred 0 to 1 0 WIND
EARTH_RES_SHRED abloom:earth_res_shred 0 to 1 0 EARTH
WATER_RES_SHRED abloom:water_res_shred 0 to 1 0 WATER
ICE_RES_SHRED abloom:ice_res_shred 0 to 1 0 ICE
ELECTRIC_RES_SHRED abloom:electric_res_shred 0 to 1 0 ELECTRIC
ENERGY_RES_SHRED abloom:energy_res_shred 0 to 1 0 ENERGY
NATURAL_RES_SHRED abloom:natural_res_shred 0 to 1 0 NATURAL
QUANTUM_RES_SHRED abloom:quantum_res_shred 0 to 1 0 QUANTUM
ETHER_RES_SHRED abloom:ether_res_shred 0 to 1 0 ETHER
LIGHT_RES_SHRED abloom:light_res_shred 0 to 1 0 LIGHT
SHADOW_RES_SHRED abloom:shadow_res_shred 0 to 1 0 SHADOW
PRISMATIC_RES_SHRED abloom:prismatic_res_shred 0 to 1 0 PRISMATIC

How It Works

Each attribute value is subtracted from the effective resistance, reducing it directly. The formula is:

effectiveResist = (R_resist + R_mod + R_armor) βˆ’ resShredValue;
// Example: effectiveResist = 0.5 βˆ’ 0.3 = 0.2 (20% resist instead of 50% β†’ 80% damage taken)

Setting the Attribute

import com.auranite.abloom.init.AbloomModAttributes;

// Set fire resistance shred on an attacker
Entity attacker = ...;
AttributeInstance fireShred = attacker.getAttribute(
    AbloomModAttributes.FIRE_RES_SHRED
);
if (fireShred != null) {
    fireShred.setBaseValue(0.3);  // 30% fire resistance shred
}

// Reduce target's ice resistance by 50%
AttributeInstance iceShred = attacker.getAttribute(
    AbloomModAttributes.ICE_RES_SHRED
);
if (iceShred != null) {
    iceShred.setBaseValue(0.5);  // 50% ice resistance shred
}
Use Case: These attributes reduce the target's effective resistance by a flat amount. Unlike RESIST_MOD (which adds to base resistance), RES_SHRED directly subtracts from the final effective resistance. For example, a fire arrow with FIRE_RES_SHRED = 0.3 reduces any fire resistance the target has by 0.3.

Enchantment-Based Damage Type Override

Abloom supports overriding a weapon's elemental damage type through enchantments. This allows weapons to deal different elements based on enchantments like fire_aspect or flame, without requiring custom enchantment classes.

How It Works

The damage handler checks all enchantments on the attacker's main hand and offhand weapons before checking weapon registration or datapack configs. If a matching enchantment is found, its mapped ElementType overrides the weapon's default element. The mapping is stored in a public static final ConcurrentHashMap in ElementDamageHandler, making it directly accessible for other mods to extend.

Built-in Mappings

Enchantment ID Mapped Element Type
minecraft:fire_aspect FIRE Vanilla enchantment (sword)
minecraft:flame FIRE Vanilla enchantment (bow)

Registering Custom Enchantments (For Other Mods)

Other mods can register their custom enchantments to map to Abloom elements by directly adding entries to the public ENCHANTMENT_ELEMENT_MAP in ElementDamageHandler. Since the map is a public static final ConcurrentHashMap, no reflection is needed.

package com.example.mymod;

import com.auranite.abloom.handler.ElementDamageHandler;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

public class MyModEnchantments {

    // Register your custom enchantment normally
    public static final DeferredRegister ENCHANTMENTS =
        DeferredRegister.create(ForgeRegistries.ENCHANTMENTS, "mymod");

    public static final RegistryObject ICE_ASPECT =
        ENCHANTMENTS.register("ice_aspect", () -> new IceAspectEnchantment());

    public static final RegistryObject ELECTRIC_ASPECT =
        ENCHANTMENTS.register("electric_aspect", () -> new ElectricAspectEnchantment());

    /**
     * Called during mod initialization to register enchantment-to-element mappings.
     * Directly accesses Abloom's public ENCHANTMENT_ELEMENT_MAP (ConcurrentHashMap).
     */
    public static void registerEnchantmentMappings() {
        // Map custom enchantments to element types
        ResourceLocation iceAspectId = ResourceLocation.fromNamespaceAndPath("mymod", "ice_aspect");
        ElementDamageHandler.ENCHANTMENT_ELEMENT_MAP.put(
            iceAspectId,
            com.auranite.abloom.util.ElementType.ICE
        );

        ResourceLocation electricAspectId = ResourceLocation.fromNamespaceAndPath("mymod", "electric_aspect");
        ElementDamageHandler.ENCHANTMENT_ELEMENT_MAP.put(
            electricAspectId,
            com.auranite.abloom.util.ElementType.ELECTRIC
        );

        // Example: Map a thunder enchantment to ELECTRIC
        ResourceLocation thunderId = ResourceLocation.fromNamespaceAndPath("mymod", "thunder_strike");
        ElementDamageHandler.ENCHANTMENT_ELEMENT_MAP.put(
            thunderId,
            com.auranite.abloom.util.ElementType.ELECTRIC
        );
    }
}

Combat API

Dealing Elemental Damage

// Deal elemental damage
ElementDamageHandler.dealElementDamage(target, ElementType.FIRE, 10.0f);

// Deal with custom accumulation multiplier
ElementDamageHandler.dealElementDamage(target, ElementType.FIRE, 10.0f, 2.0f, attacker);

// Deal with specific accumulation points
ElementDamageHandler.dealElementDamage(target, ElementType.FIRE, 10.0f, 50);

// Instant damage (bypasses some modifiers)
ElementDamageHandler.applyElementalDamageInstant(target, source, ElementType.FIRE, 10.0f, 1.0f);

Managing Accumulation Points

// Add accumulation points
ElementDamageHandler.addElementPoints(entity, ElementType.FIRE, 25);

// Get current points
int points = ElementDamageHandler.getElementPoints(entity, ElementType.FIRE);

// Reset specific element
ElementDamageHandler.resetElementPoints(entity, ElementType.FIRE);

// Reset all elements
ElementDamageHandler.resetAllElementPoints(entity);

// Get progress (0-100%)
int progress = ElementDamageHandler.getAccumulationProgress(entity, ElementType.FIRE);

Elemental Projectiles

// Register projectile by entity type
ElementalProjectileRegistry.registerProjectile(EntityType.ARROW, ElementType.FIRE, 1.5f);

// Register by class
ElementalProjectileRegistry.registerProjectileByClass(
    MyCustomProjectile.class,
    ElementType.ICE,
    2.0f
);

// Check if elemental
boolean isElemental = ElementalProjectileRegistry.isElementalProjectile(projectile);

// Get element from projectile
Optional<ElementType> element = ElementalProjectileRegistry.getElementForEntity(projectile);

// Create and launch elemental projectile
Arrow projectile = ElementalProjectileRegistry.createAndLaunchElementalProjectile(
    level,
    shooter,
    EntityType.ARROW,
    1.5f,   // velocity
    0.1f    // inaccuracy
);

// Force specific element (overrides shooter's weapon)
Arrow projectile = ElementalProjectileRegistry.createElementalProjectileWithOverride(
    level,
    shooter,
    EntityType.ARROW,
    ElementType.FIRE,  // forced element
    1.5f,
    0.1f
);

// Enable/disable inheriting element from shooter (default: true)
ElementalProjectileRegistry.setInheritElementFromShooter(true);

Armor Resistances

// Register armor with single resistance
ArmorResistanceRegistry.registerArmor(myArmor, ElementType.FIRE, 0.3f);

// Register with multiple resistances
Map<ElementType, Float> resistances = Map.of(
    ElementType.FIRE, 0.3f,
    ElementType.WATER, 0.2f,
    ElementType.ICE, 0.4f
);
ArmorResistanceRegistry.registerArmor(myArmor, resistances);

// Low-level component API
ItemStack resistantStack = ElementalResistanceComponent.withResistance(
    stack,
    ElementType.FIRE,
    0.3f
);

// Get resistance value
float fireRes = ElementalResistanceComponent.getResistance(stack, ElementType.FIRE);

// Get all resistances
Map<ElementType, Float> allResistances = ElementalResistanceComponent.getAllResistances(stack);

Checking Resistances

// Get entity resistance
ElementResistanceManager.Resistance resistance =
    ElementResistanceManager.getResistance(entity, ElementType.FIRE);

// Check if has resistance
boolean hasResistance = ElementResistanceManager.hasResistanceFor(entity, ElementType.FIRE);

// Check if weak to element
boolean isWeak = ElementResistanceManager.isWeakness(entity, ElementType.FIRE);

// Check if immune
boolean isImmune = ElementResistanceManager.isImmune(entity, ElementType.FIRE);

// Calculate reduced damage
float reducedDamage = ElementResistanceManager.calculateReducedDamage(
    entity,
    ElementType.FIRE,
    10.0f
);

// Calculate accumulation points (takes resistance into account)
int points = ElementResistanceManager.calculateAccumulationPoints(
    entity,
    ElementType.FIRE,
    10
);

Damage Display

// Check if damage numbers enabled
boolean enabled = AbloomConfig.areDamageNumbersEnabled();

// Check if status texts enabled
boolean statusEnabled = AbloomConfig.areStatusTextsEnabled();

// Spawn damage number
ElementDamageDisplayManager displayManager = new ElementDamageDisplayManager();
displayManager.spawnDamageNumber(entity, 10.5f, ElementType.FIRE);

// Spawn status text
displayManager.spawnStatusText(
    entity,
    Component.translatable("elemental.tooltip.overheating"),
    0xFF5500
);

Mod Integration

Damage Modification System

Register damage modifiers with priorities to integrate with Abloom's damage pipeline:

// Register modifier with explicit priority
DamageModificationManager.registerModifier(myModifier, 200);  // HIGH - before Abloom
DamageModificationManager.registerModifier(myModifier, -100); // LOW - after Abloom

// Register with default priority (0 = NORMAL)
DamageModificationManager.registerModifier(myModifier);

// Process damage manually
float highPriorityDamage = DamageModificationManager.processHighPriorityDamage(
    target,
    source,
    baseDamage
);

float lowPriorityDamage = DamageModificationManager.processLowPriorityDamage(
    target,
    source,
    currentDamage
);

// Debug: get registered modifier count
int count = DamageModificationManager.getRegisteredModifierCount();

Entity Resistance Tags

Use predefined tags to register mob resistances in datapacks:

// Available tag keys
Tags.FIRE_RESISTANCE      Tags.FIRE_WEAKNESS
Tags.WATER_RESISTANCE     Tags.WATER_WEAKNESS
Tags.EARTH_RESISTANCE     Tags.EARTH_WEAKNESS
Tags.WIND_RESISTANCE      Tags.WIND_WEAKNESS
Tags.ICE_RESISTANCE       Tags.ICE_WEAKNESS
Tags.ELECTRIC_RESISTANCE  Tags.ELECTRIC_WEAKNESS
Tags.PHYSICAL_RESISTANCE  Tags.PHYSICAL_WEAKNESS
Tags.NATURAL_RESISTANCE   Tags.NATURAL_WEAKNESS
Tags.QUANTUM_RESISTANCE   Tags.QUANTUM_WEAKNESS
Tags.ETHER_RESISTANCE     Tags.ETHER_WEAKNESS
Tags.LIGHT_RESISTANCE     Tags.LIGHT_WEAKNESS
Tags.SHADOW_RESISTANCE    Tags.SHADOW_WEAKNESS

Complete Integration Example

package com.example.mymod;

import com.auranite.abloom.*;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Rarity;

public class MyModElements {

    public static final Item DRAGON_SWORD = new Item(new Item.Properties().rarity(Rarity.RARE));
    public static final Item ICE_BOW = new Item(new Item.Properties().rarity(Rarity.RARE));
    public static final Item IRON_CHESTPLATE = new Item(new Item.Properties().rarity(Rarity.COMMON));

    public static void init() {
        // Register elemental weapons
        registerElementalWeapons();

        // Register armor resistances
        registerArmorResistances();

        // Register projectiles
        registerProjectiles();
    }

    private static void registerElementalWeapons() {
        // Dragon sword: fire damage with 3x accumulation, 20% crit chance, 60% crit damage
        ElementalWeaponRegistry.registerBuiltinWeapon(
            DRAGON_SWORD,
            ElementType.FIRE,
            3.0f,
            0.2f,
            0.6f
        );

        // Ice bow: ice damage with 2x accumulation
        ElementalWeaponRegistry.registerBuiltinWeapon(
            ICE_BOW,
            ElementType.ICE,
            2.0f,
            0.05f,
            0.5f
        );
    }

    private static void registerArmorResistances() {
        // Iron chestplate: 30% fire resistance
        ArmorResistanceRegistry.registerArmor(
            IRON_CHESTPLATE,
            ElementType.FIRE,
            0.3f
        );
    }

    private static void registerProjectiles() {
        // Fireball projectiles: fire-elemental
        ElementalProjectileRegistry.registerProjectile(
            EntityType.FIREBALL,
            ElementType.FIRE,
            1.5f
        );

        // Arrows inherit element from shooter's weapon
        ElementalProjectileRegistry.setInheritElementFromShooter(true);
    }
}
Best Practices:
  1. Always check for null when getting elements from items
  2. Use config values instead of hardcoding display settings
  3. Register in common setup (not client or server only)
  4. Test with /reload when using datapacks during development
  5. Clamp resistance values between -0.99 and 0.99

Datapack Configuration

Directory Structure

your_datapack.zip
└── data
    └── abloom
        β”œβ”€β”€ damage_type/           # Custom damage types (optional)
        β”œβ”€β”€ elemental_weapons/     # Elemental weapon configurations
        β”œβ”€β”€ armor_resistances/     # Armor resistance configurations
        └── tags
            └── entity_type
                └── element_resistance/  # Mob elemental properties
                    β”œβ”€β”€ fire/
                    β”‚   β”œβ”€β”€ resistance.json
                    β”‚   └── weakness.json
                    └── [other elements]/

Elemental Weapons Configuration

Weapons can be configured with or without attack stages. Multi-stage weapons deal different element types and accumulation values per hit, while single-element weapons maintain consistent behavior.

Multi-Stage Weapon Example

Weapons can have multiple attack stages with different elements and accumulation multipliers:

{
  "item": "abloom:fire_stick",
  "stages": {
    "1": {
      "element": "PHYSICAL",
      "accumulation_multiplier": 10.0
    },
    "2": {
      "element": "PHYSICAL",
      "accumulation_multiplier": 10.0
    },
    "3": {
      "element": "FIRE",
      "accumulation_multiplier": 15.0
    },
    "4": {
      "element": "FIRE",
      "accumulation_multiplier": 35.0
    }
  },
  "base_element": "FIRE",
  "crit_chance": 0.5,
  "crit_damage": 1.0,
  "resonance_frequency": 125
}

Fields:

Example Breakdown: The fire_stick example shows a 4-stage weapon:

Single-Element Weapon Example (No Stages)

For simpler weapons that always deal the same element type without stage progression:

{
  "item": "abloom:water_blade",
  "base_element": "WATER",
  "accumulation_multiplier": 12.0,
  "crit_chance": 0.3,
  "crit_damage": 0.8,
  "resonance_frequency": 150
}

Fields for Single-Element Weapons:

Note: If stages is present, the accumulation_multiplier field at the root level is ignored. Use stages for complex weapons with evolving damage patterns, or omit stages for consistent single-element weapons.

Armor Resistances Configuration

{
  "item": "minecraft:leather_helmet",
  "resistances": {
    "ELECTRIC": 0.02,
    "ICE": 0.01
  }
}

Mob Elemental Properties

// data/abloom/tags/entity_type/element_resistance/fire/resistance.json
{
  "replace": false,
  "values": [
    "minecraft:blaze",
    "minecraft:magma_cube",
    "minecraft:wither",
    "minecraft:ender_dragon"
  ]
}

// data/abloom/tags/entity_type/element_resistance/fire/weakness.json
{
  "replace": false,
  "values": [
    "minecraft:snow_golem",
    "minecraft:dolphin",
    "minecraft:zombie",
    "minecraft:zombie_villager"
  ]
}

Loading Datapacks

  1. Place your datapack in .minecraft/saves/[worldname]/datapacks/
  2. Reload with /reload command
  3. Check logs for confirmation messages:
    • Loaded X elemental weapon configurations from datapacks
    • Loaded X armor resistance configurations from datapacks
Common Issues:
  • Verify item registry names are correct (use F3+H for advanced tooltips)
  • Ensure element values match exactly (FIRE, not fire)
  • Check that resistance values are within -0.99 to 0.99 range
  • Entity type IDs must be valid (e.g., minecraft:zombie)

Custom Elemental Types

Abloom supports loading custom elemental types from datapacks. Custom elements extend the elemental system beyond the 14 built-in types, allowing mod developers and players to create new elements with unique properties, resonance effects, and visual representations.

Directory Structure

your_mod_or_datapack/
└── data
    └── your_mod_id
        └── elemental_types/     # Custom element definitions
            └── your_element.json

JSON Format

Each custom element is defined in a JSON file with the following structure:

{
  "element_id": "yourmod:custom_element",
  "override_damage_types": ["yourmod:custom_element_damage", "minecraft:generic"],
  "color": "0x2B004C",
  "element_translation_key": "element.yourmod.custom",
  "resonance_translation_key": "resonance.yourmod.custom",
  "base_element": "FIRE",
  "can_resonance_accumulation": true,
  "resonance_dmg_multiplier": 2.0,
  "dispersion_bonus": 0.25,
  "resonance_effect": {
    "effect": "yourmod:custom_resonance_effect",
    "config": {
      "duration": 100,
      "amplifier": 0
    }
  },
  "resonance_display_effect": "yourmod:custom_effect"
}

Fields Reference

Field Type Required Description
element_id ResourceLocation Yes Unique identifier for the element (e.g., yourmod:void)
override_damage_types Array<ResourceLocation> No List of damage types to override when this element deals damage
color Integer or Hex String No Element color in decimal (16777215) or hex format (0xFFFFFF). Defaults to white (0xFFFFFF)
element_translation_key String No Translation key for element name (e.g., element.yourmod.custom). Falls back to element ID path if not provided
resonance_translation_key String No Translation key for resonance status text. Falls back to default message if not provided
can_resonance_accumulation Boolean No Whether this element can accumulate resonance points. Defaults to true
resonance_dmg_multiplier Double No Multiplier for resonance explosion damage. Formula: 2.0 Γ— resonance_dmg_multiplier + resonanceFrequency Γ— 0.01. Defaults to 1.0
dispersion_bonus Float No Damage bonus multiplier when the target has the DISPERSION effect. Applied as damageMultiplier *= 1.0f + dispersionBonus. For example, 0.25 gives +25% damage. Defaults to 0.0 (no bonus)
base_element String No Specifies the base element for damage bonus attributes and threshold multipliers. When set, the custom element uses the base element's attributes ({element}_dmg_bonus, {element}_resist_mod, {element}_res_shred). If resonance_dmg_multiplier is not specified, it defaults to the base element's threshold multiplier. For example, "FIRE" makes the custom element use fire_dmg_bonus and defaults resonance_dmg_multiplier to 2.0 (FIRE's threshold). Defaults to null (uses own attributes, resonance_dmg_multiplier defaults to 1.0)
resonance_effect Object No Resonance effect applied at 100 accumulation points. See below for structure
resonance_display_effect ResourceLocation No MobEffect ID used for resonance icon rendering in the UI (e.g., yourmod:custom_effect). If not set, the resonance_effect.effect is used as the display icon. Defaults to null

Resonance Effect Configuration

The resonance_effect field defines the MobEffect applied when the element reaches 100 accumulation points:

"resonance_effect": {
  "effect": "yourmod:custom_resonance_effect",
  "config": {
    "duration": 100,
    "amplifier": 0
  }
}
Field Type Description
effect ResourceLocation MobEffect to apply (e.g., yourmod:custom_effect)
config.duration Integer Effect duration in ticks (must be positive)
config.amplifier Integer Effect amplifier level (0 = level I, 1 = level II, etc.)

Translation Keys

Custom elements support translation keys for localization. Add entries to your mod's language file:

# en_us.json
"element.yourmod.custom": "Custom Element"
"resonance.yourmod.custom": "Custom Resonance Explosion!"

# ru_ru.json
"element.yourmod.custom": "Π‘ΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ Π­Π»Π΅ΠΌΠ΅Π½Ρ‚"
"resonance.yourmod.custom": "Π’Π·Ρ€Ρ‹Π² РСзонанса!"

Using Custom Elements in Code

Custom elements can be used through the IElementalType interface, which is implemented by both built-in ElementType enum values and custom CustomElementType records.

Lookup by Name
import com.auranite.abloom.util.IElementalType;
import com.auranite.abloom.util.ElementType;

// Lookup any elemental type (built-in or custom)
Optional<? extends IElementalType> customType = IElementalType.byName("VOID");
if (customType.isPresent()) {
    IElementalType type = customType.get();
    // Use with elemental damage API
    ElementDamageHandler.dealElementDamage(target, type, 10.0f);
}
Lookup by Damage Type ID
// Lookup by damage type ID (e.g., "void_dmg")
Optional<? extends IElementalType> type = IElementalType.byDamageTypeId("void_dmg");
if (type.isPresent()) {
    // Use with elemental API
}
Checking Element Type
IElementalType type = ...;

// Check if custom
if (type.isCustom()) {
    // Access custom element data
    Optional<CustomElementData> data = CustomElementRegistry.getData(type);
    if (data.isPresent()) {
        CustomElementData elementData = data.get();
        int color = elementData.color();
        double multiplier = elementData.resonanceDmgMultiplier();
        
        // Access resonance effect config
        if (elementData.resonanceEffect() != null) {
            CustomElementData.ResonanceEffectConfig resonance = elementData.resonanceEffect();
            ResourceLocation effectId = resonance.effect();
            int duration = resonance.duration();
        }
    }
}

// Get display name (works for both built-in and custom)
String displayName = type.getDisplayName();

// Get damage type ID
String damageTypeId = type.damageTypeId();
Dealing Custom Elemental Damage
import com.auranite.abloom.handler.ElementDamageHandler;
import com.auranite.abloom.util.IElementalType;

// Method 1: By name
Optional<? extends IElementalType> voidType = IElementalType.byName("VOID");
voidType.ifPresent(type -> {
    ElementDamageHandler.dealElementDamage(target, type, 15.0f, 2.0f, attacker);
});

// Method 2: From CustomElementRegistry
Optional<CustomElementData> data = CustomElementRegistry.byElementId(ResourceLocation.tryParse("yourmod:void"));
data.ifPresent(elementData -> {
    IElementalType type = ElementType.getCustomTypeByName(elementData.getElementName()).orElse(null);
    if (type != null) {
        ElementDamageHandler.dealElementDamage(target, type, 15.0f);
    }
});
Checking Custom Element Properties
import com.auranite.abloom.registries.CustomElementRegistry;
import com.auranite.abloom.datapack.CustomElementData;

// Get custom element data
Optional<CustomElementData> data = CustomElementRegistry.getData(type);
if (data.isPresent()) {
    CustomElementData elementData = data.get();
    
    // Check if can accumulate resonance
    if (elementData.canResonanceAccumulation()) {
        // Element supports resonance
    }
    
    // Get resonance multiplier
    float multiplier = CustomElementRegistry.getResonanceMultiplier(type);
    
    // Get base element (if set)
    String baseElement = CustomElementRegistry.getBaseElement(type);
    if (baseElement != null) {
        // This element uses base element's attributes and threshold multiplier
        // e.g., "FIRE" β†’ uses fire_dmg_bonus, fire_resist_mod, FIRE threshold (2.0)
    }
    
    // Get resonance effect config
    Optional<CustomElementData.ResonanceEffectConfig> resonanceEffect = 
        CustomElementRegistry.getResonanceEffectConfig(type);
    if (resonanceEffect.isPresent()) {
        CustomElementData.ResonanceEffectConfig config = resonanceEffect.get();
        // Apply resonance effect to target
        target.addEffect(new MobEffectInstance(
            BuiltInRegistries.MOB_EFFECT.getOptional(config.effect()).orElse(null),
            config.duration(),
            config.amplifier(),
            false,
            true
        ));
    }
}

Color Format

Colors support both decimal and hex format:

// Decimal format
"color": 2891628

// Hex format (recommended for readability)
"color": "0x2B004C"

Important Notes

Limitations:
  • Custom elements cannot participate in switch statements (they're records, not enum constants)
  • Use type.isCustom() to check if an element is custom before accessing custom-specific APIs
  • Resonance effects for custom elements are applied through CustomElementRegistry.getResonanceEffectConfig(), not through RESONANCE_EFFECT_MAP
  • Prismatic damage conversion works with custom elements β€” getActiveResonanceType() checks custom elements by their resonance effect instance
Best Practices:
  1. Always use IElementalType.byName() or IElementalType.byDamageTypeId() for lookup β€” these handle both built-in and custom types
  2. Check type.isCustom() before accessing custom element-specific methods
  3. Use translation keys for all user-facing text to support localization
  4. Validate custom element IDs follow the namespace:name format
  5. Test resonance effects with /reload during development to ensure they load correctly

Example: Void Element (without base_element)

Complete example of a void element definition:

{
  "element_id": "yourmod:void",
  "override_damage_types": ["yourmod:void_damage", "minecraft:generic"],
  "color": "0x2B004C",
  "element_translation_key": "element.yourmod.void",
  "resonance_translation_key": "resonance.yourmod.void",
  "can_resonance_accumulation": true,
  "resonance_dmg_multiplier": 2.5,
  "dispersion_bonus": 0.30,
  "resonance_effect": {
    "effect": "yourmod:void_resonance",
    "config": {
      "duration": 200,
      "amplifier": 1
    }
  },
  "resonance_display_effect": "yourmod:void_resonance"
}

With corresponding translation entries:

// en_us.json
{
  "element.yourmod.void": "Void",
  "resonance.yourmod.void": "Void Resonance Explosion!",
  "effect.yourmod.void_resonance": "Void Resonance"
}

// ru_ru.json
{
  "element.yourmod.void": "ΠŸΡƒΡΡ‚ΠΎΡ‚Π°",
  "resonance.yourmod.void": "Π’Π·Ρ€Ρ‹Π² ΠŸΡƒΡΡ‚ΠΎΡ‚Ρ‹!",
  "effect.yourmod.void_resonance": "РСзонанс ΠŸΡƒΡΡ‚ΠΎΡ‚Ρ‹"
}

Example: Blue Fire Element (with base_element)

A themed "Blue Fire" element that uses FIRE's attributes, but has its own custom resonance effect:

{
  "element_id": "yourmod:blue_fire",
  "color": "0x4488FF",
  "element_translation_key": "element.yourmod.blue_fire",
  "base_element": "FIRE",
  "resonance_dmg_multiplier": 1.5,
  "resonance_effect": {
    "effect": "yourmod:blue_burn",
    "config": {
      "duration": 240,
      "amplifier": 0
    }
  },
  "resonance_display_effect": "yourmod:blue_burn"
}

What this does:

Example: Blue Fire Element (without resonance_dmg_multiplier)

If resonance_dmg_multiplier is omitted, it defaults to the base element's threshold multiplier:

{
  "element_id": "yourmod:blue_fire",
  "color": "0x4488FF",
  "element_translation_key": "element.yourmod.blue_fire",
  "base_element": "FIRE",
  "resonance_effect": {
    "effect": "yourmod:blue_burn",
    "config": {
      "duration": 240,
      "amplifier": 0
    }
  }
}

What this does:

Registration: Custom elements are automatically loaded from datapacks during mod initialization via CustomElementRegistry.loadFromDatapacks() called from AbloomMod.setup(). No manual registration is required β€” just place your JSON files in the correct directory structure and they will be available at runtime.
Use Case: The base_element field is useful for themed elements that should share mechanics with an existing element. For example, "Blue Fire" (fire-themed but blue) uses fire attributes, while having its own visual appearance and custom resonance effect. If resonance_dmg_multiplier is not specified, it defaults to the base element's threshold multiplier, making it easy to create elements that share all mechanics except the resonance effect.