This guide describes the public API in the current source version 0.7.2. Use the dependency guidance below and check that the mod is loaded when integrating conditionally.
FFInjury — Modding API
Use this guide when integrating another mod with FFInjury (ffinjury).
| Minecraft | 1.21.1 |
| Loader | NeoForge 21.1.x |
| Mod ID | ffinjury |
| API package | com.fyxe.ffinjury.api |
| Source version | 0.7.2 |
Dependency (optional):
[[dependencies.yourmod]]
modId="ffinjury"
type="optional"
versionRange="[0.6.0,)"
ordering="NONE"
side="BOTH"
Use ModList.get().isLoaded("ffinjury") or an optional compile-only dependency before calling API classes.
Core concepts
- Server-authoritative. Mutations only apply on the logical server (
ServerPlayer). Client query methods work; client mutations are no-ops. - Persisted on the player via NeoForge attachment
InjuryAttachments.INJURY_DATA. - Cleared on death. Non-death clones keep state.
- Adrenaline suppresses injury potion effects and attribute modifiers while active.
- Treated injuries (bandaged) suppress their own effects/attributes until treatment expires. Increasing an injury's tier clears treated + heal timers.
- Injury types are dynamic — datapack JSON at
data/<ns>/ffinjury/injuries/and/orInjuryAPI.registerInjury. - Hurt level is the highest active injury tier. Rules live in
data/<ns>/ffinjury/hurt_levels/and are off unlesshurt_level.enabledis true. - Creative suppression. If
general.enableInjuriesInCreativeis false, creative/instabuild players: do not gain injuries, do not heal them, hide HUD/inventory icons, and skip injury/adrenaline effects. Query withInjuryAPI.isGameplaySuppressed(player).
Registering custom injuries
Prefer a datapack file so names, icons, effects, and damage weights exist on both sides:
data/mymod/ffinjury/injuries/fracture.json
Id becomes mymod:fracture. See README.md for the full JSON schema.
Code fallback (overridden by datapack JSON with the same id):
import com.fyxe.ffinjury.api.InjuryAPI;
InjuryAPI.registerInjury("mymod:fracture", "Bone Fracture", "minecraft:bone");
All injuries share general.defaultMaxTier. Per-injury max tiers are gone.
Queries
import com.fyxe.ffinjury.api.InjuryAPI;
import com.fyxe.ffinjury.injury.InjuryType;
import net.minecraft.world.entity.player.Player;
boolean any = InjuryAPI.hasAnyInjury(player);
int count = InjuryAPI.getInjuryCount(player);
int hurtLevel = InjuryAPI.getHurtLevel(player); // max tier, 0 if none
InjuryType type = InjuryAPI.getInjuryType("bleeding").orElse(null);
boolean has = InjuryAPI.hasInjury(player, type);
int tier = InjuryAPI.getTier(player, type);
boolean treated = InjuryAPI.isTreated(player, type);
boolean healing = InjuryAPI.isHealing(player, type);
boolean adrenaline = InjuryAPI.isAdrenalineActive(player);
long expireTick = InjuryAPI.getAdrenalineExpireTick(player);
Optional<ActiveInjury> ai = InjuryAPI.getActiveInjury(player, type);
List<ActiveInjury> list = InjuryAPI.getInjuries(player); // unmodifiable
Collection<InjuryType> allTypes = InjuryAPI.getRegisteredInjuryTypes();
boolean suppressed = InjuryAPI.isGameplaySuppressed(player);
boolean hurtOn = InjuryAPI.isHurtLevelEnabled();
double regenMul = InjuryAPI.getHurtLevelRegenMultiplier(player); // 1.0 if feature off
Config mirrors:
boolean creative = InjuryAPI.areInjuriesEnabledInCreative();
int maxActive = InjuryAPI.getMaxActiveInjuries();
int maxTier = InjuryAPI.getDefaultMaxTier();
Built-in convenience constants still exist: InjuryType.BLEEDING, InjuryType.BURN, etc.
Mutations (server only)
InjuryAPI.setInjuryTier(player, type, 2); // 0 removes
int newTier = InjuryAPI.addOrIncreaseInjury(player, type);
InjuryAPI.reduceInjury(player, type, 1);
int healed = InjuryAPI.healTiers(player, 2);
InjuryAPI.treatInjury(player, type, 60); // treat 60s + start heal timer
InjuryAPI.clearAllInjuries(player);
InjuryAPI.grantAdrenaline(player, 20 * 15);
All mutations refresh potion effects, attribute modifiers, sync the client HUD, and fire the relevant API events.
Raising a tier via setInjuryTier / addOrIncreaseInjury clears that injury's treated and heal timers.
Events (NeoForge bus)
Listen with @SubscribeEvent on NeoForge.EVENT_BUS.
| Event | Cancellable | When |
|---|---|---|
InjurySelectEvent | Yes | After damage-table selection, before apply. Can change type. |
InjuryAppliedEvent | No | After an injury is added or tier increased. |
InjuryHealedEvent | No | When tiers are reduced (sleep, apple, bandage heal, API, tick heal). |
InjuryTreatedEvent | No | When a bandage or InjuryAPI.treatInjury starts treatment. getTreatmentItem() may be empty for API calls. |
AdrenalineGrantedEvent | Yes | Before adrenaline is applied; can adjust duration. |
Package: com.fyxe.ffinjury.api.event.
Example:
@SubscribeEvent
public void onSelect(InjurySelectEvent e) {
if (e.getInjuryType().getId().equals("bleeding")) {
e.setCanceled(true); // block bleeding from this hit
}
}
Injury types
Resolve by id: InjuryType.fromId("bleeding") or InjuryType.of("bleeding") (fallback handle).
| Default ID | Display |
|---|---|
twisted_ankle | Twisted Ankle |
ankle_fracture | Ankle Fracture |
broken_leg | Broken Leg |
bruised_ribs | Bruised Ribs |
broken_ribs | Broken Ribs |
concussion | Concussion |
bleeding | Bleeding |
burn | Burn |
InjuryType live-resolves display name, description, icon, effects, and attributes from the current datapack definition.
ActiveInjury
ActiveInjury ai = ...;
InjuryType type = ai.getType();
int tier = ai.getTier();
boolean treated = ai.isTreated(currentGameTick);
boolean healing = ai.isHealing();
long treatedUntil = ai.getTreatedUntilTick();
long healAt = ai.getHealAtTick();
Do not call setTier / timer setters from other mods unless you also refresh status and sync. Prefer InjuryAPI.
Hurt level (datapack)
Path: data/<namespace>/ffinjury/hurt_levels/<id>.json
{
"min_hurt_level": 2,
"stop_regen": false,
"regen_multiplier": 0.5,
"effects": [
{ "effect": "minecraft:slowness", "amplifier": 0 }
],
"attributes": [
{ "attribute": "minecraft:generic.movement_speed", "amount": -0.05, "operation": "add_multiplied_total" }
]
}
Matching rules (hurt >= min_hurt_level) combine: lowest regen multiplier wins, any stop_regen stops regen, effects/attributes stack. Feature toggle: hurt_level.enabled (default false).
Attribute modifiers
- Per-injury modifiers live on the injury JSON (
attributesarray). - Hurt-level modifiers live on hurt-level JSON (
attributesarray), not in server config.
Operations: add_value, add_multiplied_base, add_multiplied_total.
Applied by InjuryStatusApplier and suppressed by adrenaline / treatment / creative gameplay suppression.
Notes for integrators
- Prefer
InjuryAPIover direct attachment access so status (effects + attributes) stays consistent. - Check
isGameplaySuppressedbefore applying your own injury-related effects in creative. - Damage chance is config (
damage_sources.chances); weighted injury picks come from JSONdamage_weights. Intercept selection withInjurySelectEvent. - Custom injuries defined only on the server datapack may show fallback icons/names on clients that lack the same JSON.
- Bandages refuse to start their use animation when they cannot apply (no injuries, or all treated for non-ethereal).