This guide describes the public API in the current source version 0.8.0. Use the dependency guidance below and check that the mod is loaded when integrating conditionally.

FFEntityDirt — Modding API

The API covers wound marks: what a hit leaves on the Damage layer. You can add your own wounds, restyle the built-in ones, assign item and entity type tags to them, and pick wounds in code. Dirt, soot and snow have no public API; they are built on FFEntityPainting's API.

Minecraft1.21.1, 1.21.11 and 26.x (Fabric 26.1 to 26.3, NeoForge 26.1.2 and 26.2)
LoaderNeoForge, Fabric
Mod IDffentitydirt
API packagecom.fyxe.ffentitydirt.api
Mavencom.fyxe.ffentitydirt:ffentitydirt-<minecraft>-<loader>:0.8.0 on the Fyxe Gitea Maven registry

Dependency (optional, NeoForge shown; on Fabric use "suggests" or "depends" in fabric.mod.json):

[[dependencies.yourmod]]
    modId="ffentitydirt"
    type="optional"
    versionRange="[0.8.0,)"
    ordering="NONE"
    side="BOTH"

Call the API from code that only loads when ffentitydirt is installed. Wounds are decided on the server, so register them on both sides (common setup), during mod construction or setup. Everything is thread safe.

How a wound is picked

  1. Resolvers added with WoundAPI.addResolver, in order. The first registered wound ID returned wins.
  2. Melee: the attacker's main-hand item (for an Epic Fight attack, the item of the hand that swung) against the wound item tags. Every wound checks <namespace>:wounds/<path> plus any tags assigned with assignItems, highest wound priority first.
  3. Melee: the item's Better Combat weapon category (when Better Combat is installed), through the damage.wounds.betterCombatCategories setting; then its Epic Fight weapon category (when Epic Fight is installed), through damage.wounds.epicFightCategories; then words in the item's ID through damage.wounds.itemKeywords.
  4. The projectile's entity type (or, for melee, the attacker's) against the wound entity type tags, the same way.
  5. Fallbacks: projectileWound for projectiles, weaponWound for an item with attack damage or in #c:tools/melee_weapon, else unarmedWound.

With damage.wounds.enabled off, melee always slashes and projectiles always puncture.

Classes

ClassWhat it does
WoundAPIregister(id, shape[, priority]), replaceShape(id, shape), shape(id), isRegistered(id), ids(), itemTag(id), entityTag(id), assignItems(tag, id), assignEntities(tag, id), addResolver(resolver), resolve(context). Constants for the 15 built-in wounds: SLASH, GASH, CLEAVE, STAB, PUNCTURE, TRIPLE_PUNCTURE, BRUISE, CRUSH, SCRATCH, CLAW, BITE, GORE, LASH, STING, SPLATTER.
WoundShapeWhat a wound looks like: strokes and dots in texture pixels, optional spatter, a color tint and a minimum size. Built with WoundShape.builder(Sizing).
WoundContextThe hit a resolver sees: victim, source, attacker, direct, weapon (never null), projectile, damage.
WoundResolverFunctional interface: return a registered wound ID for a hit, or null to pass.

Shapes

Coordinates are texture pixels of the part that was hit, at full size, with the hit spot at (0, 0). x runs along the wound's main axis and y across it. The built-in slash is one stroke from (-2, 0) to (2, 0).

Example: a new wound

import com.fyxe.ffentitydirt.api.WoundAPI;
import com.fyxe.ffentitydirt.api.WoundShape;

public static final ResourceLocation SERRATED = ResourceLocation.fromNamespaceAndPath("mymod", "serrated");

// In common setup, only when ffentitydirt is loaded:
WoundAPI.register(SERRATED, WoundShape.builder(WoundShape.Sizing.LINE)
        .line(-2.5f, 0, 2.5f, 0, 1.2f)                 // the main cut
        .stroke(-2, 0.8f, 2, 0.8f, 0.4f, 0.6f, 0.3f)   // a torn edge
        .spatter(3, 1.5f, 3.5f, 0.3f, 0.6f)            // a few drops
        .minScale(0.5f)
        .build());
// Items in #mymod:wounds/serrated now leave it. Assign more tags if you like:
WoundAPI.assignItems(TagKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath("mymod", "saw_blades")), SERRATED);

On 1.21.11, use Identifier where this shows ResourceLocation.

Example: assign tags or decide in code

// Your claw gauntlets rake like a cat.
WoundAPI.assignItems(MyTags.CLAW_GAUNTLETS, WoundAPI.CLAW);
// Your werewolf bites when unarmed.
WoundAPI.assignEntities(MyTags.WEREWOLVES, WoundAPI.BITE);
// Or decide per hit: a charged spear crushes instead of stabbing.
WoundAPI.addResolver(context -> context.weapon().is(MyItems.SPEAR) && MySpear.isCharged(context.weapon())
        ? WoundAPI.CRUSH : null);

Notes