Line 1: |
Line 1: |
| {{Under construction}} | | {{Under construction}} |
| | | |
− | An '''event''' is a special object 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. | + | 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 = | | = 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 receieve cancelled events unless they are explicitly registered to listen for cancelled events. | + | 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 '''have a result''', which is an enum of <code>Event.Result</code>. | + | 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 20: |
Line 22: |
| | | |
| = Event Bus = | | = Event Bus = |
− | An '''event bus''' is an object which holds a list of event listeners. Events may be fired on these event buses, which is then given to each event listener in turn. | + | 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 == | | == 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'''. | | 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 is the primary event bus where most mods relating to the game are fired on, including ticking events, entity events, server events, and more. This event bus is located at <code>MinecraftForge#EVENT_BUS</code>. | + | 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-specific event bus is an event bus created for each mod loaded by the FMLJavaMod language provider (which is the default language provider for Java mods). This can be retrieved from <code>FMLJavaModLoadingContext#getEventBus()</code> when in the mod's constructor. This is where [[Stages of Modloading|mod loading events]] are fired on for mods (which may be fired in parallel for multiple mods). | + | The Mod bus, referenced through <code>FMLJavaModLoadingContext.get().getModEventBus()</code> or <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 == |
| | | |
| + | 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. |
| | | |
− | Forge uses an event bus that allows mods to intercept events from various vanilla and mod behaviors.
| + | Event handlers' properties are as such: |
− | | + | - Registered to an event bus |
− | Example: An event can be used to perform an action when a Vanilla stick is right clicked.
| + | - May be static or instance |
− | | + | - Have a single argument, which is used to determine the event that is being listened for |
− | The main event bus used for most events is located at <code>MinecraftForge.EVENT_BUS</code>. There is another event bus for mod specific events located at <code>FMLJavaModLoadingContext.get().getModEventBus()</code> that you should only use in specific cases, more information about this bus can be found below.
| + | - The argument given is the instance of the Event being posted. |
− | | |
− | Every event is fired on one of these busses, most events are fired on the main event bus but some are fired on the mod specific events bus.
| |
− | | |
− | == 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.
| + | 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> |
| | | |
− | [[File:Guide_to_Event_Handlers.png|768px|All available ways to register an event handler. Credits to Will BL of the MMD discord.]]
| + | Each of these will be explained in detail as follows. |
| | | |
| === Annotated Event Handlers === | | === Annotated Event Handlers === |
Line 61: |
Line 80: |
| 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. |
| | | |
− | To register this event handler, use <code>MinecraftForge.EVENT_BUS.register(<instance>)</code> and pass it an instance of your event handler class. If you want to register this handler to the mod specific event bus you should use <code>FMLJavaModLoadingContext.get().getModEventBus().register(<instance>)</code> instead.
| + | This function would be registered with <code>EventBus#register(new X())</code> in the above examples. |
| | | |
| === Static Event Handlers === | | === Static Event Handlers === |
Line 76: |
Line 95: |
| </syntaxhighlight> | | </syntaxhighlight> |
| | | |
− | which must be registered <code>MinecraftForge.EVENT_BUS.register(MyStaticForgeEventHandler.class)</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 <code>MinecraftForge.EVENT_BUS</code> when the <code>@Mod</code> class itself is constructed. This is essentially equivalent to adding <code>MinecraftForge.EVENT_BUS.register(AnnotatedClass.class);</code> at the end of the <code>@Mod</code> class's constructor. | + | 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. |
| | | |
− | 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 to the <code>@Mod.EventBusSubscriber</code> annotation. 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>RenderWorldLastEvent</code> which will only be called on the physical client: | | An example for a static event listener listening to <code>RenderWorldLastEvent</code> which will only be called on the physical client: |
Line 97: |
Line 121: |
| | | |
| {{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>IEventBus::addListener</code> or <code>IEventBus::addGenericListener</code> for generic events. | + | 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 117: |
Line 142: |
| {{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>.}} |
| | | |
− | == Canceling == | + | == Cancelling == |
| | | |
− | If an event can be canceled, 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 cancelable event may be modified by calling <code>Event#setCanceled(boolean canceled)</code>, wherein passing the boolean value <code>true</code> is interpreted as canceling the event, and passing the boolean value <code>false</code> is interpreted as “un-canceling” the event. | + | 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 canceled! Attempting to cancel an event that is not cancelable 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 canceled using <code>Event#isCancelable()</code> before attempting to cancel it.}} | + | {{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 135: |
Line 160: |
| == 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 144: |
Line 172: |
| 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 eventbus 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: | + | 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: |
| + | |
| + | === Render Events === |
| + | * <code>RenderWorldLastEvent</code> |
| + | * <code>RenderHandEvent</code> |
| + | * <code>RenderLivingEvent</code> |
| + | * <code>RenderItemInFrameEvent</code> |
| + | * <code>RenderBlockOverlayEvent</code> |
| + | * <code>DrawHighlightEvent</code> |
| + | * <code>RenderTooltipEvent</code> |
| + | * <code>EntityViewRenderEvent</code> |
| + | * <code>RenderGameOverlayEvent</code> |
| + | * <code>FOVUpdateEvent</code> |
| + | |
| + | === GUI Events === |
| + | * <code>GuiScreenEvent</code> |
| + | * <code>GuiContainerEvent</code> |
| + | * <code>GuiOpenEvent</code> |
| + | |
| + | === Super Events === |
| + | (Events that exist to contain other events) |
| + | * <code>BlockEvent</code> |
| + | * <code>WorldEvent</code> |
| + | * <code>InputEvent</code> |
| + | * <code>NetworkEvent</code> |
| + | * <code>GenericEvent</code> |
| + | * <code>ExplosionEvent</code> |
| + | * <code>SoundEvent</code> |
| + | * <code>EntityEvent</code> |
| + | * <code>TickEvent</code> |
| + | |
| + | === Chat Events === |
| + | * <code>ServerChatEvent</code> |
| + | * <code>ClientChatEvent</code> |
| + | * <code>ClientChatReceivedEvent</code> |
| + | |
| + | === 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>ClientPlayerChangeGamemodeEvent</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> |
| | | |
− | A good rule of thumb: events are fired on the mod eventbus when they should be handled during initialization of a mod.
| + | 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. |