Skip to content

Events in Forge

Forge uses events to allow mods to communicate with Minecraft and each other. Most of the events you will need to use come from Forge, but you can also create your own events if you need more.

Subscribing to events

If you are interested in an event you need to create an event handler. For this first create a method that has the @SubscribeEvent annotation, is public, return void and takes an event as an argument. The type of the event argument is what decides which events your method receives. You can also only have one argument on an event handler.

public class MyEventHandlerClass {
    int chatCount = 0;
    @SubscribeEvent //(1)!
    public void onChat(ClientChatReceivedEvent event) { //(2)!
        chatCount++;
        System.out.println("Chats received total: " + chatCount);
    }
}
  1. This annotation informs Forge that your method is an event handler
  2. The method parameter tells Forge which events this event handler listens to

This on it's own will not do anything yet. You must also register the event handler. To do that you register it on the corresponding event bus. For almost everything you will do, you need the MinecraftForge.EVENT_BUS (yes, even your own custom events should use this event bus). The best place to do this is in one of your FML*InitializationEvents.

@Mod(modid = "examplemod", useMetadata = true)
public class ExampleMod {
    @Mod.EventHandler
    public void init(FMLInitializationEvent event) {
        MinecraftForge.EVENT_BUS.register(new MyEventHandlerClass());
        MinecraftForge.EVENT_BUS.register(this);
    }
}

Cancelling Events

Forge Events can be cancelled. What exactly that means depends on the event, but it usually stops the action the event indicates from happening.

@SubscribeEvent
public void onChat(ClientChatReceivedEvent event) {
    // No more talking about cheese
    if (event.message.getFormattedText().contains("cheese"))
        event.setCanceled(true); // (1)!
}
  1. Cancel the event

Not all events can be cancelled. Check the event class in the decompilation for the @Cancellable annotation.

If an event is cancelled, it not only changes what Minecraft's code does with the event, but also prevents all other event handlers that come afterwards from handling the event. If you want your event handler to even receive cancelled events, use receiveCanceled = true:

@SubscribeEvent(receiveCanceled = true) // (1)!
public void onChat(ClientChatReceivedEvent event) {
    event.setCanceled(false); // (2)!
}
  1. Make sure our event handler receives cancelled events
  2. Uncancel the event. This means the event will be handled by Minecrafts code normally again and you will see the chat.

Custom Events

Note

This is an advanced topic that most mod developers don't need to worry about.

Forge also allows you to create custom events. Each event needs to have it's own class extending Event (transitively or not). (Make sure you extend net.minecraftforge.fml.common.eventhandler.Event, not any other event class).

@Cancelable // (1)!
public class CheeseEvent extends Event { // (2)!
    public final int totalCheeseCount;

    public CheeseEvent(int totalCheeseCount) {
        this.totalCheeseCount = totalCheeseCount;
    }
}
  1. If you want your event to be cancellable, you need this annotation. Remove it for an uncancellable event.
  2. Extend the Forge Event class. The rest of your class is just normal Java.

That's it, you are done. You have a custom event!

I'm kidding of course. The next step is actually using your event. For now, let's put our own custom event inside the forge chat event (you will later learn how to use mixins to create even more events):

int cheeseCount = 0;

@SubscribeEvent
public void onChat(ClientChatReceivedEvent event) {
    if (event.message.getFormattedText().contains("cheese")) {
        CheeseEvent cheeseEvent = new CheeseEvent(++cheeseCount); // (1)!
        MinecraftForge.EVENT_BUS.post(cheeseEvent); // (2)!
    }
}
  1. Creates a new CheeseEvent instance. This is just a normal java object construction, which does not interact with Forge at all.
  2. Send our CheeseEvent to be sent to all event handlers by Forge.

And now we are done, unless you want your event to be cancellable. For cancellable events we also need to add code to handle cancelled events. What that cancelling does is up to you, but in our example let's just cancel the original chat message event (hiding that chat message):

@SubscribeEvent
public void onChat(ClientChatReceivedEvent event) {
    if (event.message.getFormattedText().contains("cheese")) {
        CheeseEvent cheeseEvent = new CheeseEvent(++cheeseCount);
        MinecraftForge.EVENT_BUS.post(cheeseEvent);
        if (cheeseEvent.isCanceled()) {
            event.setCanceled(true);
        }
    }
}

You can now subscribe to your custom event like you would to any other event:

@SubscribeEvent
public void onCheese(CheeseEvent event) {
    if (event.totalCheeseCount > 10) {
        // Only 10 cheese messages are allowed per restart
        event.setCanceled(true);
    }
}