Custom Attributes in Forge
In Minecraft Forge, registering custom attributes is one of the simplest things you can do! Let’s create a custom attribute attack_range that we can apply to any entity and reference from other parts of the code.
First, we need a ModAttributes class. Since there won’t be any additional files to go along with it, I like to put it in my util folder. If you already have ModItems or ModBlocks, you will find the pattern to be very familiar.
public class ModAttributes {
public static final DeferredRegister<Attribute> ATTRIBUTES = DeferredRegister.create(ForgeRegistries.ATTRIBUTES, TestMod.MODID);
public static void register(IEventBus eventBus) {
ATTRIBUTES.register(eventBus);
}
}We create a deferred register called ATTRIBUTES that will hold and register our attributes. It uses the ForgeRegistries.ATTRIBUTES registry.
Get Colebot’s stories in your inbox
Join Medium for free to get updates from this writer.
Then, we define a function register that takes in an IEventBus. This is what will ultimately tell Forge that our attributes exist. To do that, let’s look at our main mod file. In my case, it’s called TestMod.java. At the beginning of the constructor, call your register function like so:
public TestMod(FMLJavaModLoadingContext context) {
IEventBus modEventBus = context.getModEventBus();
modEventBus.addListener(this::commonSetup);
ModAttributes.register(modEventBus);
...
}Again, if you’ve already registered custom blocks or items, you should be able to see what’s going on here. As you add more and more types of modded things, the list of register functions you’re calling will grow and grow.
Now that we’ve finished registering our attributes list, we can finally define our attribute! Back in ModAttributes, add the following line right in the middle:
public static final RegistryObject<Attribute> ATTACK_REACH = ATTRIBUTES.register("attack_reach", () -> new RangedAttribute("attribute.testmod.attack_reach", 1.5, 0, 1024));For each attribute you want to add, you’ll need one of these lines. It simply defines a public static final field to hold our attribute’s registry object. The register method of DeferredRegister<Attribute> (ATTRIBUTES) takes two arguments: the name of the attribute (attack_reach), and the attribute supplier (a lamda function that returns the new attribute). For the attribute itself, we create a new RangedAttribute, which means the attribute is represented by a numerical decimal point value. We define a description id (for translation), as well as the default value, the minimum value, and the maximum value.
Once you’ve done this, your attribute is good to go! Just use it as you would use any vanilla attribute in code: ModAttributes.ATTACK_REACH.get() (the .get() is important to get the actual attribute from the registry object), or in a datapack: testmod:attack_reach. Happy Modding!






