Views
Actions
Difference between revisions of "Events"
(Add sections for cancellable and result-having events) |
(Add mod bus list) |
||
(21 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
− | + | {{Under construction}} | |
− | = Cancellable Events = | + | 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. For a class to be considered an event, it must be a subclass of <code>Event</code>. | ||
+ | |||
+ | == Generic Events == | ||
+ | '''Generic events''' are events which supply additional generic type information, allowing event listeners to filter based on that secondary type. Generic events must implement <code>IGenericEvent<T></code>, and return their generic type from the <code>IGenericEvent#getType()</code> method. As a convenience, events that wish to be generic events may extend the <code>GenericEvent<T></code> instead of manually implementing the interface. | ||
+ | |||
+ | For generic events, the generic type must be an exact match with the listener's generic type filter to pass; if an <code>AttachCapabilitiesEvent<ItemStack></code> is fired and a listener is listening for <code>AttachCapabilitiesEvent<Object></code>, the listener does not receive the event. If an event listener is registered using <code>EventBus#register(Object)</code>, it may listen to events with any generic type by supplying a wildcard generic (<code><?></code>). Nested generic types are ignored. | ||
+ | |||
+ | == Cancellable Events == | ||
An event may be marked as '''cancellable''', which allows event listeners to cancel the event. | An event may be marked as '''cancellable''', which allows event listeners to cancel the event. | ||
− | A cancellable event may be cancelled by using <code>Event#setCanceled(true)</code>. Attempting to call this method on a non-cancellable event will result in a <code>UnsupportedOperationException</code>. A cancelled event behaves similarly to a regular noncancelled event, with one main difference: an event listener will not | + | A cancellable event may be cancelled by using <code>Event#setCanceled(true)</code>. Attempting to call this method on a non-cancellable event will result in a <code>UnsupportedOperationException</code>. 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 <code>@Cancelable</code>. This will automatically make <code>Event#isCancelable()</code> return <code>true</code>. Modders may check if an event has a result through the presence of the annotation or by calling the given method. | To mark an event as cancellable, the event class should be annotated with <code>@Cancelable</code>. This will automatically make <code>Event#isCancelable()</code> return <code>true</code>. Modders may check if an event has a result through the presence of the annotation or by calling the given method. | ||
− | = Events with Results = | + | == Events with Results == |
− | An event may ''' | + | An event may have a '''result''', which is an enum of <code>Event.Result</code>. |
The <code>Event.Result</code> enum has three values: <code>ALLOW</code>, <code>DEFAULT</code>, and <code>DENY</code>. The meaning of these result values is entirely dependent on the event itself. | The <code>Event.Result</code> enum has three values: <code>ALLOW</code>, <code>DEFAULT</code>, and <code>DENY</code>. The meaning of these result values is entirely dependent on the event itself. | ||
Line 17: | Line 26: | ||
To mark an event as having a result, the event class should be annotated with <code>@Event.HasResult</code>. This will automatically make <code>Event#hasResult</code> return <code>true</code>. Modders may check if an event has a result through the presence of the annotation or by calling the given method. | To mark an event as having a result, the event class should be annotated with <code>@Event.HasResult</code>. This will automatically make <code>Event#hasResult</code> return <code>true</code>. 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. The main class for event buses is <code>IEventBus</code>, and a bus is created using <code>BusBuilder</code>. | ||
+ | |||
+ | You can find a more detailed explanation on the Event Bus pattern [https://dzone.com/articles/design-patterns-event-bus here.] | ||
+ | ===Existing Buses=== | ||
+ | Forge exposes three main families of event buses: the main Forge event bus, the mod-specific event buses, and the network channel event buses. | ||
+ | ====Main Forge Event Bus==== | ||
+ | The '''main Forge event bus''' is located at <code>MinecraftForge#EVENT_BUS</code>, and is where most events relating to ingame actions or events are fired on, such as events for ticking, block interactions, and entity interactions. | ||
+ | |||
+ | |||
+ | List of events fired on the main Forge event bus{{:Events/Forge bus}} | ||
+ | |||
+ | |||
+ | ====Mod-Specific Event Buses==== | ||
+ | The '''mod-specific event buses''' are the family of event buses where mod-related initialization and registration events are fired, such as the events for [[Registration|registering objects]] or setup on different physical sides. Only events which implement <code>IModBusEvent</code> may be fired or listened for on these event buses. | ||
+ | |||
+ | Each loaded mod has their own instance of a mod-specific event bus. The mod-specific event bus for the currently loading mod can be retrieved from <code>FMLModContainer#getEventBus()</code>, which is also accessible from <code>FMLJavaModLoadingContext#getModEventBus()</code>. | ||
+ | |||
+ | {{Tip|title=Tip|The mod-specific event buses are provided by the <code>javafml</code> language provider which is builtin to Forge Mod Loader. Custom language providers may provide other ways for mods to receive the different mod-related initialization and registration events; see the documentation of your custom language provider for details.}} | ||
+ | |||
+ | List of events fired on the Mod-Specific event bus{{:Events/Mod bus}} | ||
+ | |||
+ | ====Network Channel Event Buses==== | ||
+ | The '''network channel event buses''' are the family of event buses where different network-related events are fired. Each registered [[Networking|networking channel]] has their own instance of an event-bus in <code>NetworkInstance</code>, where only events pertinent to that channel are fired on. | ||
+ | |||
+ | The network channel event buses cannot be accessed directly; <code>EventNetworkChannel</code> provides methods to register events listeners to the event bus. | ||
+ | |||
+ | == Event Listeners == | ||
+ | An '''event listener''' (also known as an '''event handler''') is a class, object, or method registered to an event bus to capture for specific events (and their subclasses). | ||
+ | |||
+ | [[File:Guide to Event Handlers.png|thumb|upright 0.9|A visual guide on how event listeners are registered.]] | ||
+ | |||
+ | An event listener may be registered in three ways: | ||
+ | * The <code>IEventBus#register(Object)</code> method on a class or instance; | ||
+ | * The <code>@EventBusSubscriber</code> annotation on a class; or | ||
+ | * The <code>IEventBus#addListener</code> and <code>IEventBus#addGenericListener</code> on a method reference or lambda. | ||
+ | |||
+ | === Priority and Receiving Cancelled Events === | ||
+ | An event listener may be registered to a specific '''event priority''' and whether to '''receive cancelled events'''. | ||
+ | |||
+ | The event priority levels allows a listener to react to an event before other event listeners of a lower level, such as to change the values within an event or cancel it outright. | ||
+ | |||
+ | There are five levels of event listeners priority; in descending order from first to receive an event to last: <code>HIGHEST</code>, <code>HIGH</code>, <code>NORMAL</code>, <code>LOW</code>, and <code>LOWEST</code>. Event listeners are registered by default on a priority of <code>NORMAL</code>. | ||
+ | |||
+ | An event listener normally never receives a cancelled event, however they may change this by being registered to receive these cancelled events. Non-cancellable events are unaffected by this, and will always be sent to all event listeners (in the order specified by their priority). | ||
+ | |||
+ | === <tt>IEventBus.register</tt> === | ||
+ | The <code>IEventBus#register(Object)</code> method allows for registering an object instance or a <code>Class<?></code> to the event bus. The method exhibits two different behaviors, depending on what is passed into it: | ||
+ | |||
+ | * '''an object instance''' - registers all ''instance or non-<code>static</code>'' methods annotated with <code>@SubscribeEvent</code> from the object | ||
+ | * '''a <code>Class<?></code> instance''' - registers all ''class or <code>static</code>'' methods annotated with <code>@SubscribeEvent</code> from the class which is represented by the passed in <code>Class<?></code> | ||
+ | |||
+ | <tab collapsed name="Example of how event listeners are registered with the IEventBus.register method"> | ||
+ | <syntaxhighlight lang="java"> | ||
+ | class EventHandler { | ||
+ | public static void nonAnnotatedStatic(Event event) {} | ||
+ | |||
+ | @SubscribeEvent | ||
+ | public static void annotatedStatic(Event event) {} | ||
+ | |||
+ | public void nonAnnotatedInstance(Event event) {} | ||
+ | |||
+ | @SubscribeEvent | ||
+ | public void annotatedInstance(Event event) {} | ||
+ | } | ||
+ | |||
+ | // Within the execution of the program | ||
+ | IEventBus bus = ...; | ||
+ | |||
+ | // This will register the "annotatedStatic" method from the class | ||
+ | bus.register(EventHandler.class); | ||
+ | // This would register "annotatedStatic", but it is already registered | ||
+ | bus.register(EventHandler.class); | ||
+ | |||
+ | EventHandler instanceA = new EventHandler(); | ||
+ | EventHandler instanceB = new EventHandler(); | ||
+ | |||
+ | // This will register the "annotatedInstance" method from the instanceA object, and will not touch the instanceB object | ||
+ | bus.register(instanceA); | ||
+ | </syntaxhighlight> | ||
+ | If an <code>Event</code> were to be fired on the event bus in the example above, the <code>EventHandler#annotatedStatic</code> would receive the event, and the <code>annotatedInstance</code> method from the <code>instanceA</code> object instance would receive the event. | ||
+ | |||
+ | Neither the unnannotated methods will receive the event, nor will the <code>annotatedInstance</code> method from the <code>instanceB</code> object instance. | ||
+ | |||
+ | </tab> | ||
+ | |||
+ | ==== <tt>@SubscribeEvent</tt> ==== | ||
+ | The <code>@SubscribeEvent</code> annotation is used to mark a method as an event listener when its containing class or object is registered using <code>IEventBus#register</code>. | ||
+ | |||
+ | They have two fields: <code>EventPriority priority</code> and <code>boolean receiveCancelled</code>, which sets the event priority for the listener and whether the listener receives cancelled events, respectively. | ||
− | + | = WIP = | |
+ | TODO: @EventBusSubscriber, addListener, Generic Events? (probably higher up) | ||
− | |||
− | + | <tab name="Partial previous content of page, to be removed" collapsed> | |
+ | == 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 <code>MinecraftForge.EVENT_BUS</code> or <code>EventBusSubscriber.Bus.FORGE</code> (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 <code>FMLJavaModLoadingContext.get().getModEventBus()</code> or <code>EventBusSubscriber.Bus.MOD</code>, 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 [[Stages of Modloading|mod loading events]]. Note that some of these are fired in parallel. | ||
== Sub Events == | == Sub Events == | ||
Many events have different variations of themselves, these can be different but all based around one common factor (e.g. <code>PlayerEvent</code>) or can be an event that has multiple phases (e.g. <code>PotionBrewEvent</code>). Take note that if you listen to the parent event class, you will receive calls to your method for ''all'' subclasses. | Many events have different variations of themselves, these can be different but all based around one common factor (e.g. <code>PlayerEvent</code>) or can be an event that has multiple phases (e.g. <code>PotionBrewEvent</code>). 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 == | == Registering Event Handlers == | ||
+ | Event handlers are registered typically one of four ways: | ||
+ | * <code>EventBusSubscriber</code> (which requires a static, annotated handler method) | ||
+ | * <code>EventBus#register(T.class)</code> (which requires a static, annotated handler method) | ||
+ | * <code>EventBus#register(new X())</code> (which requires an instance, annotated handler method) | ||
+ | * <code>EventBus#addListener(Class::function)</code> (which requires an instance, non-annotated handler method) | ||
+ | * as an extension of the above: <code>EventBus#<LivingHurtEvent>addListener(event -> { code })</code> | ||
− | + | Each of these will be explained in detail as follows. | |
=== Annotated Event Handlers === | === Annotated Event Handlers === | ||
Line 48: | Line 178: | ||
This event handler listens for the <code>EntityItemPickupEvent</code>, which is, as the name states, posted to the event bus whenever an <code>Entity</code> picks up an item. | This event handler listens for the <code>EntityItemPickupEvent</code>, which is, as the name states, posted to the event bus whenever an <code>Entity</code> picks up an item. | ||
− | + | This function would be registered with <code>EventBus#register(new X())</code> in the above examples. | |
=== Static Event Handlers === | === Static Event Handlers === | ||
Line 63: | Line 193: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | which must be registered <code> | + | which must be registered <code>EventBus#register(MyStaticForgeEventHandler.class)</code>. |
<h3 id="eventbussubscriber">Using <tt style="font-size: 100%">@Mod.EventBusSubscriber</tt></h3> | <h3 id="eventbussubscriber">Using <tt style="font-size: 100%">@Mod.EventBusSubscriber</tt></h3> | ||
− | A class may be annotated with the <code>@Mod.EventBusSubscriber</code> annotation. Such a class is automatically registered to | + | A class may be annotated with the <code>@Mod.EventBusSubscriber</code> annotation. Such a class is automatically registered to the configured bus when the <code>@Mod</code> class itself is constructed. This is essentially equivalent to adding <code>EventBus#register(AnnotatedClass.class);</code> at the end of the <code>@Mod</code> class's constructor. |
+ | |||
+ | The mod ID must be specified unless your class is already annotated with an <code>@Mod</code> annotation. You can pass the bus you want to listen to inside the <code>@Mod.EventBusSubscriber</code> annotation. | ||
+ | |||
+ | The bus registered with <code>EventBusSubscriber</code> defaults to the Forge event bus. | ||
+ | |||
+ | You can also specify the <code>Dist</code>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 <code> | + | An example for a static event listener listening to <code>RenderLevelLastEvent</code> which will only be called on the physical client: |
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
Line 77: | Line 212: | ||
public class MyStaticClientOnlyEventHandler { | public class MyStaticClientOnlyEventHandler { | ||
@SubscribeEvent | @SubscribeEvent | ||
− | public static void drawLast( | + | public static void drawLast(RenderLevelLastEvent event) { |
System.out.println("Drawing!"); | System.out.println("Drawing!"); | ||
} | } | ||
Line 84: | Line 219: | ||
{{Tip/Important|This does not register an instance of the class; it registers the class itself (i.e. the event handling methods must be static).}} | {{Tip/Important|This does not register an instance of the class; it registers the class itself (i.e. the event handling methods must be static).}} | ||
+ | |||
=== Non-Annotated Event Handlers === | === Non-Annotated Event Handlers === | ||
− | Event handlers do not need to be annotated if they are directly referred to using <code> | + | Event handlers do not need to be annotated if they are directly referred to using <code>EventBus#addListener</code> (or <code>EventBus#addGenericListener</code> for generic events). |
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
Line 104: | Line 240: | ||
{{Tip/Important|The generic passed into the event must be referenced directly within the code itself. Otherwise, the event will not be called whatsoever. For example, if you use <code>AttachCapabilitiesEvent<LivingEntity></code>, the event will never be called as no call of this event uses <code>LivingEntity</code>, only <code>Entity</code>.}} | {{Tip/Important|The generic passed into the event must be referenced directly within the code itself. Otherwise, the event will not be called whatsoever. For example, if you use <code>AttachCapabilitiesEvent<LivingEntity></code>, the event will never be called as no call of this event uses <code>LivingEntity</code>, only <code>Entity</code>.}} | ||
− | == | + | == Cancelling == |
− | If an event can be | + | If an event can be cancelled, it will be marked with the <code>@Cancelable</code> annotation, and the method <code>Event#isCancelable()</code> will return <code>true</code>. The cancel state of a cancellable event may be modified by calling <code>Event#setCanceled(boolean canceled)</code>, wherein passing the boolean value <code>true</code> is interpreted as cancelling the event, and passing the boolean value <code>false</code> is interpreted as “un-cancelling” the event. |
− | {{Tip/Important|Not all events can be | + | {{Tip/Important|Not all events can be cancelled! Attempting to cancel an event that is not cancellable will result in an unchecked <code>UnsupportedOperationException</code> being thrown, which is expected to result in the game crashing. Always check that an event can be cancelled using <code>Event#isCancelable()</code> before attempting to cancel it.}} |
== Results == | == Results == | ||
Line 122: | Line 258: | ||
== Mod Event Bus == | == 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 <code>InterModComms</code> system for that. | 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 <code>InterModComms</code> 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: | These are the four most commonly used lifecycle events that are called during mod initialization on the mod event bus: | ||
Line 131: | Line 270: | ||
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 <code>enqueueWork</code> methods within the events to do so. | 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 <code>enqueueWork</code> methods within the events to do so. | ||
− | Next to the lifecycle events there are a few miscellaneous events that are fired on the mod | + | 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: |
* <code>ColorHandlerEvent</code> | * <code>ColorHandlerEvent</code> | ||
* <code>ModelBakeEvent</code> | * <code>ModelBakeEvent</code> | ||
* <code>TextureStitchEvent</code> | * <code>TextureStitchEvent</code> | ||
* <code>RegistryEvent</code> | * <code>RegistryEvent</code> | ||
+ | * <code>GatherDataEvent</code> | ||
+ | * <code>SoundLoadEvent</code> | ||
+ | * <code>ParticleFactoryRegisterEvent</code> | ||
+ | * <code>ModConfigEvent</code> | ||
+ | |||
+ | 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: | ||
+ | |||
+ | {{Tree list}} | ||
+ | * <code>Event</code> - ''The root event class'' | ||
+ | ** '''Rendering events''' ('''client-only''') | ||
+ | *** <code>RenderLevelLastEvent</code> - Fired after level rendering to allow mods to add custom renders | ||
+ | *** <code>RenderHandEvent</code> - Fired before and after the hand of the player is rendered in the first person POV | ||
+ | *** <code>RenderLivingEvent</code> - Fired before and after a <code>LivingRenderer</code> is executed | ||
+ | *** <code>RenderItemInFrameEvent</code> - Fired before the item in an <code>ItemFrameEntity</code> is rendered | ||
+ | *** <code>RenderBlockOverlayEvent</code> - Fired before the block overlay for the player's screen is rendered | ||
+ | *** <code>DrawHighlightEvent</code> - Fired before the block highlight outline is rendered | ||
+ | *** <code>RenderTooltipEvent</code> - Fired before and during rendering of a text tooltip on a screen | ||
+ | *** <code>EntityViewRenderEvent</code> - Superclass for events relating to the player's viewpoint | ||
+ | *** <code>RenderGameOverlayEvent</code> - Superclass, fired for each element on the player's HUD or game overlay | ||
+ | *** <code>FOVModifierEvent</code> - Fired when the FOV of the player is requested (?) | ||
+ | ** '''Screen events''' ('''client-only''') | ||
+ | *** <code>ScreenEvent</code> - Superclass for events relating to <code>Screen</code>s | ||
+ | *** <code>ScreenContainerEvent</code> - Superclsas for events relating to <code>ContainerScreen</code>s | ||
+ | *** <code>ScreenOpenEvent</code> - Fired before a new screen is opened on the game window | ||
+ | ** '''Superclass events''' - ''These events exist to be superclasses of other events'' | ||
+ | *** <code>GenericEvent</code> - ''from EventBus'', superclass of events which have a generic type | ||
+ | *** <code>BlockEvent</code> - Superclass for events relating to a block within the level | ||
+ | *** <code>LevelEvent</code> - Superclass for events relating to the level | ||
+ | *** <code>InputEvent</code> - ('''client-only''') Superclass for events relating to the player's keyboard and mouse inputs | ||
+ | *** <code>NetworkEvent</code> - Superclass for events relating to networking | ||
+ | *** <code>ExplosionEvent</code> - Fired before an explosion explodes in the level | ||
+ | *** <code>SoundEvent</code> - ('''client-only''') Superclass for events related to sounds | ||
+ | *** <code>EntityEvent</code> - Superclass for events relating to entities | ||
+ | *** <code>TickEvent</code> - Superclass for events fired before and after ticking | ||
+ | ** '''Chat events''' | ||
+ | *** <code>ServerChatEvent</code> ('''server-only''') - Fired when the server receives a chat message and before it relays the message | ||
+ | *** <code>ClientChatEvent</code> ('''client-only''') - Fired before the client is about to send a chat message | ||
+ | *** <code>ClientChatReceivedEvent</code> ('''client-only''') - Fired when the client receives a chat message from the server | ||
+ | ** '''Data loading events''' | ||
+ | *** <code>RecipesUpdatedEvent</code> | ||
+ | *** <code>BiomeLoadingEvent</code> | ||
+ | *** <code>LootTableLoadEvent</code> | ||
+ | *** <code>StructureSpawnListGatherEvent</code> | ||
+ | ** '''Startup events''' | ||
+ | *** <code>AddReloadListenerEvent</code> | ||
+ | *** <code>RegisterCommandsEvent</code> | ||
+ | *** <code>ServerLifecycleEvent</code> | ||
+ | ** '''Gamemode events''' | ||
+ | *** <code>DifficultyChangeEvent</code> | ||
+ | *** <code>ClientPlayerChangeGameTypeEvent</code> | ||
+ | **'''Trade events''' | ||
+ | *** <code>WandererTradesEvent</code> | ||
+ | *** <code>VillagerTradesEvent</code> | ||
+ | ** '''Other events''' | ||
+ | *** <code>FurnaceFuelBurnTimeEvent</code> | ||
+ | *** <code>BabyEntitySpawnEvent</code> | ||
+ | *** <code>VillageSiegeEvent</code> | ||
+ | *** <code>TagsUpdatedEvent</code> | ||
+ | *** <code>PotionBrewEvent</code> | ||
+ | *** <code>ScreenshotEvent</code> | ||
+ | *** <code>EnchantmentLevelSetEvent</code> | ||
+ | *** <code>CommandEvent</code> | ||
+ | *** <code>AnvilUpdateEvent</code> | ||
+ | *** <code>ItemAttributeModifierEvent</code> | ||
+ | *** <code>ClientPlayerNetworkEvent</code> | ||
+ | *** <code>ChunkWatchEvent</code> | ||
+ | {{Tree list/end}} | ||
+ | |||
+ | 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. | ||
+ | </tab> | ||
+ | |||
+ | |||
+ | [[Category:Events]] | ||
+ | |||
− | + | [[Category:Common Concepts]] |
Latest revision as of 13:09, 3 April 2022
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. For a class to be considered an event, it must be a subclass of Event
.
Generic Events
Generic events are events which supply additional generic type information, allowing event listeners to filter based on that secondary type. Generic events must implement IGenericEvent<T>
, and return their generic type from the IGenericEvent#getType()
method. As a convenience, events that wish to be generic events may extend the GenericEvent<T>
instead of manually implementing the interface.
For generic events, the generic type must be an exact match with the listener's generic type filter to pass; if an AttachCapabilitiesEvent<ItemStack>
is fired and a listener is listening for AttachCapabilitiesEvent<Object>
, the listener does not receive the event. If an event listener is registered using EventBus#register(Object)
, it may listen to events with any generic type by supplying a wildcard generic (<?>
). Nested generic types are ignored.
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. The main class for event buses is IEventBus
, and a bus is created using BusBuilder
.
You can find a more detailed explanation on the Event Bus pattern here.
Existing Buses
Forge exposes three main families of event buses: the main Forge event bus, the mod-specific event buses, and the network channel event buses.
Main Forge Event Bus
The main Forge event bus is located at MinecraftForge#EVENT_BUS
, and is where most events relating to ingame actions or events are fired on, such as events for ticking, block interactions, and entity interactions.
List of events fired on the main Forge event bus
Event
- The root superclass for all eventsMissingMappingsEvent
RecipesUpdatedEvent
FurnaceFuelBurnTimeEvent
DrawSelectionEvent
HighlightBlock
inDrawSelectionEvent
HighlightEntity
inDrawSelectionEvent
VillagerTradesEvent
AddReloadListenerEvent
GameShuttingDownEvent
ClientPlayerChangeGameTypeEvent
PlayerNegotiationEvent
RenderHandEvent
RenderLivingEvent
Pre
inRenderLivingEvent
Post
inRenderLivingEvent
RegisterCommandsEvent
RenderItemInFrameEvent
RenderBlockOverlayEvent
BlockEvent
BlockToolModificationEvent
inBlockEvent
NeighborNotifyEvent
inBlockEvent
NoteBlockEvent
Change
inNoteBlockEvent
Play
inNoteBlockEvent
BreakEvent
inBlockEvent
EntityPlaceEvent
inBlockEvent
EntityMultiPlaceEvent
inBlockEvent
PistonEvent
Pre
inPistonEvent
Post
inPistonEvent
PortalSpawnEvent
inBlockEvent
FarmlandTrampleEvent
inBlockEvent
FluidPlaceBlockEvent
inBlockEvent
CropGrowEvent
inBlockEvent
Pre
inCropGrowEvent
inBlockEvent
Post
inCropGrowEvent
inBlockEvent
WorldEvent
Load
inWorldEvent
CreateSpawnPosition
inWorldEvent
Unload
inWorldEvent
ChunkEvent
Load
inChunkEvent
Unload
inChunkEvent
ChunkDataEvent
Save
inChunkDataEvent
Load
inChunkDataEvent
SleepFinishedTimeEvent
Save
inWorldEvent
SaplingGrowTreeEvent
PlayLevelSoundEvent
AtEntity
inPlayLevelSoundEvent
AtPosition
inPlayLevelSoundEvent
RegisterStructureConversionsEvent
ContainerScreenEvent
DrawBackground
inContainerScreenEvent
DrawForeground
inContainerScreenEvent
BabyEntitySpawnEvent
ServerChatEvent
ScreenEvent
KeyboardKeyEvent
inScreenEvent
KeyboardKeyReleasedEvent
inScreenEvent
Pre
inKeyboardKeyReleasedEvent
inScreenEvent
Post
inKeyboardKeyReleasedEvent
inScreenEvent
KeyboardKeyPressedEvent
inScreenEvent
Post
inKeyboardKeyPressedEvent
inScreenEvent
Pre
inKeyboardKeyPressedEvent
inScreenEvent
InitScreenEvent
inScreenEvent
Pre
inInitScreenEvent
inScreenEvent
Post
inInitScreenEvent
inScreenEvent
MouseInputEvent
inScreenEvent
MouseReleasedEvent
inScreenEvent
Pre
inMouseReleasedEvent
inScreenEvent
Post
inMouseReleasedEvent
inScreenEvent
MouseScrollEvent
inScreenEvent
Pre
inMouseScrollEvent
inScreenEvent
Post
inMouseScrollEvent
inScreenEvent
MouseClickedEvent
inScreenEvent
Post
inMouseClickedEvent
inScreenEvent
Pre
inMouseClickedEvent
inScreenEvent
MouseDragEvent
inScreenEvent
Post
inMouseDragEvent
inScreenEvent
Pre
inMouseDragEvent
inScreenEvent
KeyboardCharTypedEvent
inScreenEvent
Pre
inKeyboardCharTypedEvent
inScreenEvent
Post
inKeyboardCharTypedEvent
inScreenEvent
PotionSizeEvent
inScreenEvent
DrawScreenEvent
inScreenEvent
Post
inDrawScreenEvent
inScreenEvent
Pre
inDrawScreenEvent
inScreenEvent
BackgroundDrawnEvent
inScreenEvent
VillageSiegeEvent
LootTableLoadEvent
TagsUpdatedEvent
PotionBrewEvent
Pre
inPotionBrewEvent
Post
inPotionBrewEvent
ClientChatReceivedEvent
InputEvent
ClickInputEvent
inInputEvent
KeyInputEvent
inInputEvent
MouseInputEvent
inInputEvent
RawMouseEvent
inInputEvent
MouseScrollEvent
inInputEvent
RegisterClientCommandsEvent
GatherComponents
inRenderTooltipEvent
DifficultyChangeEvent
ScreenshotEvent
ServerLifecycleEvent
ServerStoppingEvent
ServerStoppedEvent
ServerAboutToStartEvent
ServerStartedEvent
ServerStartingEvent
EnchantmentLevelSetEvent
RenderTooltipEvent
Pre
inRenderTooltipEvent
Color
inRenderTooltipEvent
IdMappingEvent
CreateFluidSourceEvent
inBlockEvent
VanillaGameEvent
RenderGameOverlayEvent
Pre
inRenderGameOverlayEvent
Text
inRenderGameOverlayEvent
BossInfo
inRenderGameOverlayEvent
PreLayer
inRenderGameOverlayEvent
Chat
inRenderGameOverlayEvent
Post
inRenderGameOverlayEvent
PostLayer
inRenderGameOverlayEvent
ClientChatEvent
CommandEvent
PermissionGatherEvent
Handler
inPermissionGatherEvent
Nodes
inPermissionGatherEvent
OnDatapackSyncEvent
StructureSpawnListGatherEvent
GenericEvent
AttachCapabilitiesEvent
ExplosionEvent
Detonate
inExplosionEvent
Start
inExplosionEvent
SoundEvent
SoundSourceEvent
inSoundEvent
PlaySoundSourceEvent
PlayStreamingSourceEvent
PlaySoundEvent
AnvilUpdateEvent
ScreenOpenEvent
RenderArmEvent
RenderLevelLastEvent
TickEvent
PlayerTickEvent
inTickEvent
ServerTickEvent
inTickEvent
WorldTickEvent
inTickEvent
ClientTickEvent
inTickEvent
RenderTickEvent
inTickEvent
WandererTradesEvent
ItemAttributeModifierEvent
EntityViewRenderEvent
FieldOfView
inEntityViewRenderEvent
RenderFogEvent
inEntityViewRenderEvent
FogColors
inEntityViewRenderEvent
CameraSetup
inEntityViewRenderEvent
ClientPlayerNetworkEvent
LoggedOutEvent
inClientPlayerNetworkEvent
LoggedInEvent
inClientPlayerNetworkEvent
RespawnEvent
inClientPlayerNetworkEvent
FOVModifierEvent
EntityEvent
EntityTeleportEvent
SpreadPlayersCommand
inEntityTeleportEvent
EnderEntity
inEntityTeleportEvent
EnderPearl
inEntityTeleportEvent
TeleportCommand
inEntityTeleportEvent
ChorusFruit
inEntityTeleportEvent
ProjectileImpactEvent
EntityTravelToDimensionEvent
EntityMobGriefingEvent
RenderNameplateEvent
EntityConstructing
inEntityEvent
EntityMountEvent
EntityStruckByLightningEvent
Size
inEntityEvent
EntityJoinWorldEvent
EnteringSection
inEntityEvent
LivingEvent
LivingEquipmentChangeEvent
SleepingLocationCheckEvent
LivingUpdateEvent
inLivingEvent
PotionColorCalculationEvent
LivingExperienceDropEvent
LivingDamageEvent
LivingAttackEvent
LivingEntityUseItemEvent
Start
inLivingEntityUseItemEvent
Tick
inLivingEntityUseItemEvent
Stop
inLivingEntityUseItemEvent
Finish
inLivingEntityUseItemEvent
PotionEvent
PotionExpiryEvent
inPotionEvent
PotionApplicableEvent
inPotionEvent
PotionRemoveEvent
inPotionEvent
PotionAddedEvent
inPotionEvent
EnderManAngerEvent
LivingPackSizeEvent
PlayerEvent
PlayerChangeGameModeEvent
inPlayerEvent
PlayerContainerEvent
Close
inPlayerContainerEvent
Open
inPlayerContainerEvent
PlayerWakeUpEvent
BreakSpeed
inPlayerEvent
ItemSmeltedEvent
inPlayerEvent
ArrowLooseEvent
Clone
inPlayerEvent
MovementInputUpdateEvent
AdvancementEvent
AnvilRepairEvent
PlayerSleepInBedEvent
PlayerLoggedOutEvent
inPlayerEvent
PlayerXpEvent
XpChange
inPlayerXpEvent
LevelChange
inPlayerXpEvent
PickupXp
inPlayerXpEvent
StopTracking
inPlayerEvent
FillBucketEvent
PlayerDestroyItemEvent
BonemealEvent
SleepingTimeCheckEvent
PlayerInteractEvent
EntityInteractSpecific
inPlayerInteractEvent
RightClickBlock
inPlayerInteractEvent
EntityInteract
inPlayerInteractEvent
RightClickEmpty
inPlayerInteractEvent
RightClickItem
inPlayerInteractEvent
LeftClickEmpty
inPlayerInteractEvent
LeftClickBlock
inPlayerInteractEvent
EntityItemPickupEvent
HarvestCheck
inPlayerEvent
ItemPickupEvent
inPlayerEvent
TabListNameFormat
inPlayerEvent
PlayerChangedDimensionEvent
inPlayerEvent
PlayerSetSpawnEvent
PlayerFlyableFallEvent
LoadFromFile
inPlayerEvent
PermissionsChangedEvent
CriticalHitEvent
StartTracking
inPlayerEvent
ItemFishedEvent
ArrowNockEvent
PlayerRespawnEvent
inPlayerEvent
ItemTooltipEvent
SaveToFile
inPlayerEvent
PlayerLoggedInEvent
inPlayerEvent
ItemCraftedEvent
inPlayerEvent
NameFormat
inPlayerEvent
RenderPlayerEvent
Post
inRenderPlayerEvent
Pre
inRenderPlayerEvent
AttackEntityEvent
PlayerBrewedPotionEvent
ShieldBlockEvent
LivingHealEvent
LootingLevelEvent
LivingDestroyBlockEvent
LivingConversionEvent
Pre
inLivingConversionEvent
Post
inLivingConversionEvent
LivingKnockBackEvent
LivingHurtEvent
LivingVisibilityEvent
inLivingEvent
LivingDeathEvent
AnimalTameEvent
LivingFallEvent
LivingGetProjectileEvent
LivingSetAttackTargetEvent
LivingSpawnEvent
AllowDespawn
inLivingSpawnEvent
CheckSpawn
inLivingSpawnEvent
SpecialSpawn
inLivingSpawnEvent
LivingJumpEvent
inLivingEvent
LivingDropsEvent
ZombieEvent
SummonAidEvent
inZombieEvent
EntityLeaveWorldEvent
ItemEvent
ItemTossEvent
ItemExpireEvent
NetworkEvent
ServerCustomPayloadEvent
inNetworkEvent
ServerCustomPayloadLoginEvent
inNetworkEvent
LoginPayloadEvent
inNetworkEvent
ChannelRegistrationChangeEvent
inNetworkEvent
ClientCustomPayloadEvent
inNetworkEvent
ClientCustomPayloadLoginEvent
inNetworkEvent
GatherLoginPayloadsEvent
inNetworkEvent
ChunkWatchEvent
UnWatch
inChunkWatchEvent
Watch
inChunkWatchEvent
Mod-Specific Event Buses
The mod-specific event buses are the family of event buses where mod-related initialization and registration events are fired, such as the events for registering objects or setup on different physical sides. Only events which implement IModBusEvent
may be fired or listened for on these event buses.
Each loaded mod has their own instance of a mod-specific event bus. The mod-specific event bus for the currently loading mod can be retrieved from FMLModContainer#getEventBus()
, which is also accessible from FMLJavaModLoadingContext#getModEventBus()
.
Tip
javafml
language provider which is builtin to Forge Mod Loader. Custom language providers may provide other ways for mods to receive the different mod-related initialization and registration events; see the documentation of your custom language provider for details.List of events fired on the Mod-Specific event bus
IModBusEvent
- The interface for all mod bus eventsModelBakeEvent
EntityRenderersEvent
AddLayers
inEntityRenderersEvent
CreateSkullModels
inEntityRenderersEvent
RegisterRenderers
inEntityRenderersEvent
RegisterLayerDefinitions
inEntityRenderersEvent
ModelRegistryEvent
GatherDataEvent
RegisterShadersEvent
AddPackFindersEvent
ModLifecycleEvent
ParallelDispatchEvent
FMLCommonSetupEvent
InterModProcessEvent
FMLDedicatedServerSetupEvent
FMLConstructModEvent
InterModEnqueueEvent
FMLClientSetupEvent
FMLLoadCompleteEvent
EntityAttributeCreationEvent
NewRegistryEvent
RegisterGameTestsEvent
ParticleFactoryRegisterEvent
RegisterCapabilitiesEvent
TextureStitchEvent
Pre
inTextureStitchEvent
Post
inTextureStitchEvent
EntityAttributeModificationEvent
SoundEngineLoadEvent
RegisterClientReloadListenersEvent
RegisterEvent
ColorHandlerEvent
Block
inColorHandlerEvent
Item
inColorHandlerEvent
ModConfigEvent
Reloading
inModConfigEvent
Loading
inModConfigEvent
Network Channel Event Buses
The network channel event buses are the family of event buses where different network-related events are fired. Each registered networking channel has their own instance of an event-bus in NetworkInstance
, where only events pertinent to that channel are fired on.
The network channel event buses cannot be accessed directly; EventNetworkChannel
provides methods to register events listeners to the event bus.
Event Listeners
An event listener (also known as an event handler) is a class, object, or method registered to an event bus to capture for specific events (and their subclasses).
An event listener may be registered in three ways:
- The
IEventBus#register(Object)
method on a class or instance; - The
@EventBusSubscriber
annotation on a class; or - The
IEventBus#addListener
andIEventBus#addGenericListener
on a method reference or lambda.
Priority and Receiving Cancelled Events
An event listener may be registered to a specific event priority and whether to receive cancelled events.
The event priority levels allows a listener to react to an event before other event listeners of a lower level, such as to change the values within an event or cancel it outright.
There are five levels of event listeners priority; in descending order from first to receive an event to last: HIGHEST
, HIGH
, NORMAL
, LOW
, and LOWEST
. Event listeners are registered by default on a priority of NORMAL
.
An event listener normally never receives a cancelled event, however they may change this by being registered to receive these cancelled events. Non-cancellable events are unaffected by this, and will always be sent to all event listeners (in the order specified by their priority).
IEventBus.register
The IEventBus#register(Object)
method allows for registering an object instance or a Class<?>
to the event bus. The method exhibits two different behaviors, depending on what is passed into it:
- an object instance - registers all instance or non-
static
methods annotated with@SubscribeEvent
from the object - a
Class<?>
instance - registers all class orstatic
methods annotated with@SubscribeEvent
from the class which is represented by the passed inClass<?>
class EventHandler { public static void nonAnnotatedStatic(Event event) {} @SubscribeEvent public static void annotatedStatic(Event event) {} public void nonAnnotatedInstance(Event event) {} @SubscribeEvent public void annotatedInstance(Event event) {} } // Within the execution of the program IEventBus bus = ...; // This will register the "annotatedStatic" method from the class bus.register(EventHandler.class); // This would register "annotatedStatic", but it is already registered bus.register(EventHandler.class); EventHandler instanceA = new EventHandler(); EventHandler instanceB = new EventHandler(); // This will register the "annotatedInstance" method from the instanceA object, and will not touch the instanceB object bus.register(instanceA);
If an Event
were to be fired on the event bus in the example above, the EventHandler#annotatedStatic
would receive the event, and the annotatedInstance
method from the instanceA
object instance would receive the event.
Neither the unnannotated methods will receive the event, nor will the annotatedInstance
method from the instanceB
object instance.
@SubscribeEvent
The @SubscribeEvent
annotation is used to mark a method as an event listener when its containing class or object is registered using IEventBus#register
.
They have two fields: EventPriority priority
and boolean receiveCancelled
, which sets the event priority for the listener and whether the listener receives cancelled events, respectively.
WIP
TODO: @EventBusSubscriber, addListener, Generic Events? (probably higher up)
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 RenderLevelLastEvent
which will only be called on the physical client:
@Mod.EventBusSubscriber(modid = "examplemod", dist = Dist.CLIENT) public class MyStaticClientOnlyEventHandler { @SubscribeEvent public static void drawLast(RenderLevelLastEvent 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:
Event
- The root event class- Rendering events (client-only)
RenderLevelLastEvent
- Fired after level rendering to allow mods to add custom rendersRenderHandEvent
- Fired before and after the hand of the player is rendered in the first person POVRenderLivingEvent
- Fired before and after aLivingRenderer
is executedRenderItemInFrameEvent
- Fired before the item in anItemFrameEntity
is renderedRenderBlockOverlayEvent
- Fired before the block overlay for the player's screen is renderedDrawHighlightEvent
- Fired before the block highlight outline is renderedRenderTooltipEvent
- Fired before and during rendering of a text tooltip on a screenEntityViewRenderEvent
- Superclass for events relating to the player's viewpointRenderGameOverlayEvent
- Superclass, fired for each element on the player's HUD or game overlayFOVModifierEvent
- Fired when the FOV of the player is requested (?)
- Screen events (client-only)
ScreenEvent
- Superclass for events relating toScreen
sScreenContainerEvent
- Superclsas for events relating toContainerScreen
sScreenOpenEvent
- Fired before a new screen is opened on the game window
- Superclass events - These events exist to be superclasses of other events
GenericEvent
- from EventBus, superclass of events which have a generic typeBlockEvent
- Superclass for events relating to a block within the levelLevelEvent
- Superclass for events relating to the levelInputEvent
- (client-only) Superclass for events relating to the player's keyboard and mouse inputsNetworkEvent
- Superclass for events relating to networkingExplosionEvent
- Fired before an explosion explodes in the levelSoundEvent
- (client-only) Superclass for events related to soundsEntityEvent
- Superclass for events relating to entitiesTickEvent
- Superclass for events fired before and after ticking
- Chat events
ServerChatEvent
(server-only) - Fired when the server receives a chat message and before it relays the messageClientChatEvent
(client-only) - Fired before the client is about to send a chat messageClientChatReceivedEvent
(client-only) - Fired when the client receives a chat message from the server
- Data loading events
RecipesUpdatedEvent
BiomeLoadingEvent
LootTableLoadEvent
StructureSpawnListGatherEvent
- Startup events
AddReloadListenerEvent
RegisterCommandsEvent
ServerLifecycleEvent
- Gamemode events
DifficultyChangeEvent
ClientPlayerChangeGameTypeEvent
- Trade events
WandererTradesEvent
VillagerTradesEvent
- Other events
FurnaceFuelBurnTimeEvent
BabyEntitySpawnEvent
VillageSiegeEvent
TagsUpdatedEvent
PotionBrewEvent
ScreenshotEvent
EnchantmentLevelSetEvent
CommandEvent
AnvilUpdateEvent
ItemAttributeModifierEvent
ClientPlayerNetworkEvent
ChunkWatchEvent
- Rendering events (client-only)
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.