This page is under construction.
This page is incomplete, and needs more work. Feel free to edit and improve this page!
An event is a signal that is fired on an event bus to inform registered listeners about some type of action or state. This is the primary way by which Forge allows mods to hook into vanilla and game behavior; Forge has an array of different events which are fired when different actions happen within the game, and mods may act upon receiving these events.
Additionally, mods may create their own events and fire them for other mods to listen for, allowing for higher compatibility.
Cancellable Events
An event may be marked as cancellable, which allows event listeners to cancel the event.
A cancellable event may be cancelled by using Event#setCanceled(true)
. Attempting to call this method on a non-cancellable event will result in a UnsupportedOperationException
. A cancelled event behaves similarly to a regular noncancelled event, with one main difference: an event listener will not receive cancelled events unless they are explicitly registered to listen for cancelled events.
To mark an event as cancellable, the event class should be annotated with @Cancelable
. This will automatically make Event#isCancelable()
return true
. Modders may check if an event has a result through the presence of the annotation or by calling the given method.
Events with Results
An event may have a ```result, which is an enum of Event.Result
.
The Event.Result
enum has three values: ALLOW
, DEFAULT
, and DENY
. The meaning of these result values is entirely dependent on the event itself.
An event's current result can be retrieved through Event#getResult()
. The result on an event can be set through Event#setResult(Event.Result)
. You can set the result for an event which is not marked as having a result, however this will cause nothing to happen if the event does not use the result value.
To mark an event as having a result, the event class should be annotated with @Event.HasResult
. This will automatically make Event#hasResult
return true
. Modders may check if an event has a result through the presence of the annotation or by calling the given method.
Event Bus
An event bus is an object which holds a list of event listeners, and the logic for firing the events. Events may be posted on these event buses, which then invokes the handlers.
Forge and Mod Buses
There are two event buses of note to a mod: the main Forge event bus, and the mod-specific event bus.
The Forge event bus, which can be referenced through MinecraftForge.EVENT_BUS
or EventBusSubscriber.Bus.FORGE
(the latter being an enum that provides handy references to both busses), fires events that depend solely on the game state. This means that:
- Entity Events
- Ticking Events
- Server Events
and more, are fired on the Forge bus.
The Mod bus, referenced through FMLJavaModLoadingContext.get().getModEventBus()
or EventBusSubscriber.Bus.MOD
, fires events that depend solely on mod state, or which are used to initialise such.
This means that:
- Registration Events
- Mod Lifecycle Events
- Model Events (bake and register)
- Config Events
- Data Provider Events
and more, are fired on the Mod bus. See mod loading events. Note that some of these are fired in parallel.
Sub Events
Many events have different variations of themselves, these can be different but all based around one common factor (e.g. PlayerEvent
) or can be an event that has multiple phases (e.g. PotionBrewEvent
). Take note that if you listen to the parent event class, you will receive calls to your method for all subclasses.
Event Handlers
Event handlers are methods, which have four main properties. They are communicated to the event bus you want them to listen on, and when the event is posted on that bus, the hander is invoked.
Event handlers' properties are as such: - Registered to an event bus - May be static or instance - Have a single argument, which is used to determine the event that is being listened for - The argument given is the instance of the Event being posted.
Note that handlers may take the form of anonymous functions - lambdas.
Registering Event Handlers
Event handlers are registered typically one of four ways:
EventBusSubscriber
(which requires a static, annotated handler method)EventBus#register(T.class)
(which requires a static, annotated handler method)EventBus#register(new X())
(which requires an instance, annotated handler method)EventBus#addListener(Class::function)
(which requires an instance, non-annotated handler method)- as an extension of the above:
EventBus#<LivingHurtEvent>addListener(event -> { code })
Each of these will be explained in detail as follows.
Annotated Event Handlers
public class MyForgeEventHandler { @SubscribeEvent public void pickupItem(EntityItemPickupEvent event) { System.out.println("Item picked up!"); } }
This event handler listens for the EntityItemPickupEvent
, which is, as the name states, posted to the event bus whenever an Entity
picks up an item.
This function would be registered with EventBus#register(new X())
in the above examples.
Static Event Handlers
An event handler may also be static. The handling method is still annotated with @SubscribeEvent
with the only difference from an instance handler is that it is also marked static. In order to register a static event handler, an instance of the class won’t do, the Class itself has to be passed in. An example:
public class MyStaticForgeEventHandler { @SubscribeEvent public static void arrowNocked(ArrowNockEvent event) { System.out.println("Arrow nocked!"); } }
which must be registered EventBus#register(MyStaticForgeEventHandler.class)
.
Using @Mod.EventBusSubscriber
A class may be annotated with the @Mod.EventBusSubscriber
annotation. Such a class is automatically registered to the configured bus when the @Mod
class itself is constructed. This is essentially equivalent to adding EventBus#register(AnnotatedClass.class);
at the end of the @Mod
class's constructor.
The mod ID must be specified unless your class is already annotated with an @Mod
annotation. You can pass the bus you want to listen to inside the @Mod.EventBusSubscriber
annotation.
The bus registered with EventBusSubscriber
defaults to the Forge event bus.
You can also specify the Dist
s to load this event subscriber on. This can be used to not load client specific event subscribers on the dedicated server.
An example for a static event listener listening to RenderWorldLastEvent
which will only be called on the physical client:
@Mod.EventBusSubscriber(modid = "examplemod", dist = Dist.CLIENT) public class MyStaticClientOnlyEventHandler { @SubscribeEvent public static void drawLast(RenderWorldLastEvent event) { System.out.println("Drawing!"); } }
Important
Non-Annotated Event Handlers
Event handlers do not need to be annotated if they are directly referred to using EventBus#addListener
(or EventBus#addGenericListener
for generic events).
@Mod("examplemod") public class MyMainModClass { public MyMainModClass() { FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(Entity.class, this::entityCap); } private void entityCap(AttachCapabilitiesEvent<Entity> event) { System.out.println("Capability attached!"); } }
Important
AttachCapabilitiesEvent<LivingEntity>
, the event will never be called as no call of this event uses LivingEntity
, only Entity
.Cancelling
If an event can be cancelled, it will be marked with the @Cancelable
annotation, and the method Event#isCancelable()
will return true
. The cancel state of a cancellable event may be modified by calling Event#setCanceled(boolean canceled)
, wherein passing the boolean value true
is interpreted as cancelling the event, and passing the boolean value false
is interpreted as “un-cancelling” the event.
Important
UnsupportedOperationException
being thrown, which is expected to result in the game crashing. Always check that an event can be cancelled using Event#isCancelable()
before attempting to cancel it.Results
Some events have an Event.Result
as denoted by @HasResult
. A result can be one of three things: DENY
which stops the event, DEFAULT
which uses the Vanilla behavior, and ALLOW
which forces the action to take place, regardless of if it would have originally. The result of an event can be set by calling setResult
with an Event.Result on the event.
Information
Priority
Event handler methods have a priority. You can set the priority
of an event handler method by setting the priority value of the annotation or the listener. The priority can be any value of the EventPriority
enum (HIGHEST
, HIGH
, NORMAL
, LOW
, and LOWEST
). Event handlers with priority HIGHEST
are executed first and from there in descending order until LOWEST
events which are executed last.
Mod Event Bus
The mod event bus is primarily used for listening to lifecycle events in which mods should initialize. Many of these events are also ran in parallel so mods can be initialized at the same time. This does mean you cannot directly execute code from other mods in these events. Use the InterModComms
system for that.
It is impossible for an event to be posted on the Mod bus that does not inherit the IModBusEvent interface. Thus, this provides a good, easy way to tell which events are fired on this bus.
These are the four most commonly used lifecycle events that are called during mod initialization on the mod event bus:
FMLCommonSetupEvent
FMLClientSetupEvent
&FMLDedicatedServerSetupEvent
(These events are only called on their respective physical side.)InterModEnqueueEvent
InterModProcessEvent
These four lifecycle events are all ran in parallel. If you want to run code on the main thread during these events you can use the enqueueWork
methods within the events to do so.
Next to the lifecycle events there are a few miscellaneous events that are fired on the mod event bus where you can register, set up, or initialize various things. Most of these events are not ran in parallel in contrast to the lifecycle events:
ColorHandlerEvent
ModelBakeEvent
TextureStitchEvent
RegistryEvent
GatherDataEvent
SoundLoadEvent
ParticleFactoryRegisterEvent
ModConfigEvent
A good rule of thumb: events are fired on the mod event bus when they should be handled during initialization of a mod. or where they are used to set state (eg. the config event.)
Detailed information about these events will be found in their respective pages, once they are ready.
Forge Event Bus
The Forge event bus is where game state events are fired. If anything changes to do with the game, or anything happens that you would need to know about, there's a good chance it's sent here.
A full list of the events fired here is as follows, split into discrete categories:
Render Events
RenderWorldLastEvent
RenderHandEvent
RenderLivingEvent
RenderItemInFrameEvent
RenderBlockOverlayEvent
DrawHighlightEvent
RenderTooltipEvent
EntityViewRenderEvent
RenderGameOverlayEvent
FOVUpdateEvent
GUI Events
GuiScreenEvent
GuiContainerEvent
GuiOpenEvent
Super Events
(Events that exist to contain other events)
BlockEvent
WorldEvent
InputEvent
NetworkEvent
GenericEvent
ExplosionEvent
SoundEvent
EntityEvent
TickEvent
Chat Events
ServerChatEvent
ClientChatEvent
ClientChatReceivedEvent
Data Loading Events
RecipesUpdatedEvent
BiomeLoadingEvent
LootTableLoadEvent
StructureSpawnListGatherEvent
Startup Events
AddReloadListenerEvent
RegisterCommandsEvent
ServerLifecycleEvent
Gamemode Events
DifficultyChangeEvent
ClientPlayerChangeGamemodeEvent
Trade Events
WandererTradesEvent
VillagerTradesEvent
Other Events
FurnaceFuelBurnTimeEvent
BabyEntitySpawnEvent
VillageSiegeEvent
TagsUpdatedEvent
PotionBrewEvent
ScreenshotEvent
EnchantmentLevelSetEvent
CommandEvent
AnvilUpdateEvent
ItemAttributeModifierEvent
ClientPlayerNetworkEvent
ChunkWatchEvent
Like before, each of these events (especially the Super Events, which contain most of the useful events in the game) will have their own article explaining their purpose and usefulness.