Attributes determine the properties that your modded entity can possess. Using Fabric, you can create your own custom attributes that enhance gameplay mechanics and apply vanilla ones as well.
Creating a Custom Attribute
Let's create a custom attribute named AGGRO_RANGE. This attribute will control the distance an entity can detect and react to potential threats from.
Defining the Attribute Class
Begin by creating a Java class to manage the definition and registration of your attributes under your mod's code structure. This example will create the following functions in a class named ModAttributes.
First, start with a basic helper method to register your mod's attributes. This method will accept the following parameters and register an attribute.
- A
Stringthat will be the name of your attribute - A
doublethat will be the default value of the attribute - A
doublethat will be the lowest value your attribute will reach - A
doublethat will be the highest value your attribute will reach - A
booleanthat dictates whether the attribute will be synced to clients
java
private static Holder<Attribute> register(
String name, double defaultValue, double minValue, double maxValue, boolean syncedWithClient
) {
ResourceLocation identifier = ResourceLocation.fromNamespaceAndPath(ExampleMod.MOD_ID, name);
Attribute entityAttribute = new RangedAttribute(
identifier.toLanguageKey(),
defaultValue,
minValue,
maxValue
).setSyncable(syncedWithClient);
return Registry.registerForHolder(BuiltInRegistries.ATTRIBUTE, identifier, entityAttribute);
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
We'll then register an attribute named AGGRO_RANGE with the name aggro_range, a default value of 8.0, a minimum value of 0, and a maximum value set as high as it can be. This attribute will not be synced to players.
java
public static final Holder<Attribute> AGGRO_RANGE = register(
"aggro_range",
8.0,
0.0,
Double.MAX_VALUE,
false
);1
2
3
4
5
6
7
2
3
4
5
6
7
Translating Custom Attributes
To display the attribute name in a human-readable format, you must modify assets/example-mod/lang/en_us.json to include:
json
{
"attribute.name.example-mod.aggro_range": "Aggro Range"
}1
2
3
2
3
Initialization
To make sure the attribute is registered properly, you'll need to ensure it is initialized during mod startup. This can be done by adding a public static initialize method to your class and call it from your mod's initializer class. Currently, this method doesn't need anything inside it.
java
public static void initialize() {
}1
2
2
java
public class ExampleModAttributes implements ModInitializer {
@Override
public void onInitialize() {
ModAttributes.initialize();
}
}1
2
3
4
5
6
2
3
4
5
6
Calling a method on a class statically initializes it if it hasn't been previously loaded - this means that all static fields are evaluated. This is what this dummy initialize method is for.
Applying Attributes
Attributes need to be attached to an entity to take effect. This is typically done in the method where an entity's attributes are built or modified.
Vanilla provides attributes as well, including max health, movement speed, and attack damage as seen below. For a full list, see the vanilla Attributes class and the Minecraft Wiki.
As a demo, we'll include maximum health, movement speed, attack damage and the aggro range attribute as created earlier.
java
public static AttributeSupplier.Builder createEntityAttributes() {
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, 25.0)
.add(Attributes.MOVEMENT_SPEED, 0.22)
.add(Attributes.ATTACK_DAMAGE, 3.0)
.add(ModAttributes.AGGRO_RANGE, 8.0);
}1
2
3
4
5
6
7
2
3
4
5
6
7
Reading and Modifying Attributes
An attribute by itself is just data attached to an entity. For it to be useful, we need to be able to read from and write to it. There are two main ways to do this: getting the AttributeInstance on the entity, or getting the value directly.
java
entity.getAttribute(ModAttributes.AGGRO_RANGE) // returns an `AttributeInstance`
entity.getAttributeValue(ModAttributes.AGGRO_RANGE) // returns a double with the current value
entity.getAttributeBaseValue(ModAttributes.AGGRO_RANGE) // returns a double with the base value1
2
3
2
3
An AttributeInstance allows more flexibility, such as setting an AttributeModifier on the attribute, using one of the three vanilla attribute modifier operations. Modifiers can be permanent (saved to NBT) or transitive (not saved to NBT) and are added using addPermanentModifier or addTransitiveModifier, respectively.
java
attribute.addPermanentModifier(
new AttributeModifier(
ResourceLocation.fromNamespaceAndPath(ExampleMod.MOD_ID, "increased_range"), // the ID of your modifier, should be static so it can be removed
8, // how much to modify it
AttributeModifier.Operation.ADD_VALUE // what operator to use, see the wiki page linked above
));1
2
3
4
5
6
2
3
4
5
6
Once you have access to the attribute value, you can use it in your entity's AI.


