Changes

9,421 bytes added ,  13:09, 3 April 2022
Add mod bus list
Line 3: Line 3:  
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.   
 
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.
+
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>.
   −
= Cancellable Events =
+
== 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.
   Line 12: Line 17:  
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 21: 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 =
+
==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.
+
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 ==
 
== 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'''.
Line 108: Line 206:       −
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>RenderLevelLastEvent</code> which will only be called on the physical client:  
    
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
Line 114: Line 212:  
public class MyStaticClientOnlyEventHandler {
 
public class MyStaticClientOnlyEventHandler {
 
     @SubscribeEvent
 
     @SubscribeEvent
     public static void drawLast(RenderWorldLastEvent event) {
+
     public static void drawLast(RenderLevelLastEvent event) {
 
         System.out.println("Drawing!");
 
         System.out.println("Drawing!");
 
     }
 
     }
Line 191: Line 289:  
A full list of the events fired here is as follows, split into discrete categories:
 
A full list of the events fired here is as follows, split into discrete categories:
   −
=== Render Events ===
+
{{Tree list}}
* <code>RenderWorldLastEvent</code>
+
* <code>Event</code> - ''The root event class''
* <code>RenderHandEvent</code>
+
** '''Rendering events''' ('''client-only''')
* <code>RenderLivingEvent</code>
+
*** <code>RenderLevelLastEvent</code> - Fired after level rendering to allow mods to add custom renders
* <code>RenderItemInFrameEvent</code>
+
*** <code>RenderHandEvent</code> - Fired before and after the hand of the player is rendered in the first person POV
* <code>RenderBlockOverlayEvent</code>
+
*** <code>RenderLivingEvent</code> - Fired before and after a <code>LivingRenderer</code> is executed
* <code>DrawHighlightEvent</code>
+
*** <code>RenderItemInFrameEvent</code> - Fired before the item in an <code>ItemFrameEntity</code> is rendered
* <code>RenderTooltipEvent</code>
+
*** <code>RenderBlockOverlayEvent</code> - Fired before the block overlay for the player's screen is rendered
* <code>EntityViewRenderEvent</code>
+
*** <code>DrawHighlightEvent</code> - Fired before the block highlight outline is rendered
* <code>RenderGameOverlayEvent</code>
+
*** <code>RenderTooltipEvent</code> - Fired before and during rendering of a text tooltip on a screen
* <code>FOVUpdateEvent</code>
+
*** <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}}
   −
=== GUI Events ===
+
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.
* <code>GuiScreenEvent</code>
+
</tab>
* <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 ===
+
[[Category: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 ===
+
[[Category:Common Concepts]]
* <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>
  −
 
  −
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.