Difference between revisions of "Events"

From Forge Community Wiki
m (Added a link to a page with a more detailed explanation of event busses.)
m (Fixed my own formatting.)
Line 28: Line 28:
 
== 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. The main class for event buses is <code>IEventBus</code>, and a bus is created using <code>BusBuilder</code>.
 
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>.
 +
 
A more detailed explanation at https://dzone.com/articles/design-patterns-event-bus.
 
A more detailed explanation at https://dzone.com/articles/design-patterns-event-bus.
  

Revision as of 18:00, 8 December 2021

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. A event listener 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.

A more detailed explanation at https://dzone.com/articles/design-patterns-event-bus.

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 events
    • MissingMappingsEvent
    • RecipesUpdatedEvent
    • FurnaceFuelBurnTimeEvent
    • DrawSelectionEvent
      • HighlightBlock in DrawSelectionEvent
      • HighlightEntity in DrawSelectionEvent
    • VillagerTradesEvent
    • AddReloadListenerEvent
    • GameShuttingDownEvent
    • ClientPlayerChangeGameTypeEvent
    • PlayerNegotiationEvent
    • RenderHandEvent
    • RenderLivingEvent
      • Pre in RenderLivingEvent
      • Post in RenderLivingEvent
    • RegisterCommandsEvent
    • RenderItemInFrameEvent
    • RenderBlockOverlayEvent
    • BlockEvent
      • BlockToolModificationEvent in BlockEvent
      • NeighborNotifyEvent in BlockEvent
      • NoteBlockEvent
        • Change in NoteBlockEvent
        • Play in NoteBlockEvent
      • BreakEvent in BlockEvent
      • EntityPlaceEvent in BlockEvent
        • EntityMultiPlaceEvent in BlockEvent
      • PistonEvent
        • Pre in PistonEvent
        • Post in PistonEvent
      • PortalSpawnEvent in BlockEvent
      • FarmlandTrampleEvent in BlockEvent
      • FluidPlaceBlockEvent in BlockEvent
      • CropGrowEvent in BlockEvent
        • Pre in CropGrowEvent in BlockEvent
        • Post in CropGrowEvent in BlockEvent
    • WorldEvent
      • Load in WorldEvent
      • CreateSpawnPosition in WorldEvent
      • Unload in WorldEvent
      • ChunkEvent
        • Load in ChunkEvent
        • Unload in ChunkEvent
        • ChunkDataEvent
          • Save in ChunkDataEvent
          • Load in ChunkDataEvent
      • SleepFinishedTimeEvent
      • Save in WorldEvent
      • SaplingGrowTreeEvent
    • PlayLevelSoundEvent
      • AtEntity in PlayLevelSoundEvent
      • AtPosition in PlayLevelSoundEvent
    • RegisterStructureConversionsEvent
    • ContainerScreenEvent
      • DrawBackground in ContainerScreenEvent
      • DrawForeground in ContainerScreenEvent
    • BabyEntitySpawnEvent
    • ServerChatEvent
    • ScreenEvent
      • KeyboardKeyEvent in ScreenEvent
        • KeyboardKeyReleasedEvent in ScreenEvent
          • Pre in KeyboardKeyReleasedEvent in ScreenEvent
          • Post in KeyboardKeyReleasedEvent in ScreenEvent
        • KeyboardKeyPressedEvent in ScreenEvent
          • Post in KeyboardKeyPressedEvent in ScreenEvent
          • Pre in KeyboardKeyPressedEvent in ScreenEvent
      • InitScreenEvent in ScreenEvent
        • Pre in InitScreenEvent in ScreenEvent
        • Post in InitScreenEvent in ScreenEvent
      • MouseInputEvent in ScreenEvent
        • MouseReleasedEvent in ScreenEvent
          • Pre in MouseReleasedEvent in ScreenEvent
          • Post in MouseReleasedEvent in ScreenEvent
        • MouseScrollEvent in ScreenEvent
          • Pre in MouseScrollEvent in ScreenEvent
          • Post in MouseScrollEvent in ScreenEvent
        • MouseClickedEvent in ScreenEvent
          • Post in MouseClickedEvent in ScreenEvent
          • Pre in MouseClickedEvent in ScreenEvent
        • MouseDragEvent in ScreenEvent
          • Post in MouseDragEvent in ScreenEvent
          • Pre in MouseDragEvent in ScreenEvent
      • KeyboardCharTypedEvent in ScreenEvent
        • Pre in KeyboardCharTypedEvent in ScreenEvent
        • Post in KeyboardCharTypedEvent in ScreenEvent
      • PotionSizeEvent in ScreenEvent
      • DrawScreenEvent in ScreenEvent
        • Post in DrawScreenEvent in ScreenEvent
        • Pre in DrawScreenEvent in ScreenEvent
      • BackgroundDrawnEvent in ScreenEvent
    • VillageSiegeEvent
    • LootTableLoadEvent
    • TagsUpdatedEvent
    • PotionBrewEvent
      • Pre in PotionBrewEvent
      • Post in PotionBrewEvent
    • ClientChatReceivedEvent
    • InputEvent
      • ClickInputEvent in InputEvent
      • KeyInputEvent in InputEvent
      • MouseInputEvent in InputEvent
      • RawMouseEvent in InputEvent
      • MouseScrollEvent in InputEvent
    • RegisterClientCommandsEvent
    • GatherComponents in RenderTooltipEvent
    • DifficultyChangeEvent
    • ScreenshotEvent
    • ServerLifecycleEvent
      • ServerStoppingEvent
      • ServerStoppedEvent
      • ServerAboutToStartEvent
      • ServerStartedEvent
      • ServerStartingEvent
    • EnchantmentLevelSetEvent
    • RenderTooltipEvent
      • Pre in RenderTooltipEvent
      • Color in RenderTooltipEvent
    • IdMappingEvent
    • CreateFluidSourceEvent in BlockEvent
    • VanillaGameEvent
    • RenderGameOverlayEvent
      • Pre in RenderGameOverlayEvent
        • Text in RenderGameOverlayEvent
        • BossInfo in RenderGameOverlayEvent
        • PreLayer in RenderGameOverlayEvent
        • Chat in RenderGameOverlayEvent
      • Post in RenderGameOverlayEvent
        • PostLayer in RenderGameOverlayEvent
    • ClientChatEvent
    • CommandEvent
    • PermissionGatherEvent
      • Handler in PermissionGatherEvent
      • Nodes in PermissionGatherEvent
    • OnDatapackSyncEvent
    • StructureSpawnListGatherEvent
    • GenericEvent
      • AttachCapabilitiesEvent
    • ExplosionEvent
      • Detonate in ExplosionEvent
      • Start in ExplosionEvent
    • SoundEvent
      • SoundSourceEvent in SoundEvent
        • PlaySoundSourceEvent
        • PlayStreamingSourceEvent
      • PlaySoundEvent
    • AnvilUpdateEvent
    • ScreenOpenEvent
    • RenderArmEvent
    • RenderLevelLastEvent
    • TickEvent
      • PlayerTickEvent in TickEvent
      • ServerTickEvent in TickEvent
      • WorldTickEvent in TickEvent
      • ClientTickEvent in TickEvent
      • RenderTickEvent in TickEvent
    • WandererTradesEvent
    • ItemAttributeModifierEvent
    • EntityViewRenderEvent
      • FieldOfView in EntityViewRenderEvent
      • RenderFogEvent in EntityViewRenderEvent
      • FogColors in EntityViewRenderEvent
      • CameraSetup in EntityViewRenderEvent
    • ClientPlayerNetworkEvent
      • LoggedOutEvent in ClientPlayerNetworkEvent
      • LoggedInEvent in ClientPlayerNetworkEvent
      • RespawnEvent in ClientPlayerNetworkEvent
    • FOVModifierEvent
    • EntityEvent
      • EntityTeleportEvent
        • SpreadPlayersCommand in EntityTeleportEvent
        • EnderEntity in EntityTeleportEvent
        • EnderPearl in EntityTeleportEvent
        • TeleportCommand in EntityTeleportEvent
        • ChorusFruit in EntityTeleportEvent
      • ProjectileImpactEvent
      • EntityTravelToDimensionEvent
      • EntityMobGriefingEvent
      • RenderNameplateEvent
      • EntityConstructing in EntityEvent
      • EntityMountEvent
      • EntityStruckByLightningEvent
      • Size in EntityEvent
      • EntityJoinWorldEvent
      • EnteringSection in EntityEvent
      • LivingEvent
        • LivingEquipmentChangeEvent
        • SleepingLocationCheckEvent
        • LivingUpdateEvent in LivingEvent
        • PotionColorCalculationEvent
        • LivingExperienceDropEvent
        • LivingDamageEvent
        • LivingAttackEvent
        • LivingEntityUseItemEvent
          • Start in LivingEntityUseItemEvent
          • Tick in LivingEntityUseItemEvent
          • Stop in LivingEntityUseItemEvent
          • Finish in LivingEntityUseItemEvent
        • PotionEvent
          • PotionExpiryEvent in PotionEvent
          • PotionApplicableEvent in PotionEvent
          • PotionRemoveEvent in PotionEvent
          • PotionAddedEvent in PotionEvent
        • EnderManAngerEvent
        • LivingPackSizeEvent
        • PlayerEvent
          • PlayerChangeGameModeEvent in PlayerEvent
          • PlayerContainerEvent
            • Close in PlayerContainerEvent
            • Open in PlayerContainerEvent
          • PlayerWakeUpEvent
          • BreakSpeed in PlayerEvent
          • ItemSmeltedEvent in PlayerEvent
          • ArrowLooseEvent
          • Clone in PlayerEvent
          • MovementInputUpdateEvent
          • AdvancementEvent
          • AnvilRepairEvent
          • PlayerSleepInBedEvent
          • PlayerLoggedOutEvent in PlayerEvent
          • PlayerXpEvent
            • XpChange in PlayerXpEvent
            • LevelChange in PlayerXpEvent
            • PickupXp in PlayerXpEvent
          • StopTracking in PlayerEvent
          • FillBucketEvent
          • PlayerDestroyItemEvent
          • BonemealEvent
          • SleepingTimeCheckEvent
          • PlayerInteractEvent
            • EntityInteractSpecific in PlayerInteractEvent
            • RightClickBlock in PlayerInteractEvent
            • EntityInteract in PlayerInteractEvent
            • RightClickEmpty in PlayerInteractEvent
            • RightClickItem in PlayerInteractEvent
            • LeftClickEmpty in PlayerInteractEvent
            • LeftClickBlock in PlayerInteractEvent
          • EntityItemPickupEvent
          • HarvestCheck in PlayerEvent
          • ItemPickupEvent in PlayerEvent
          • TabListNameFormat in PlayerEvent
          • PlayerChangedDimensionEvent in PlayerEvent
          • PlayerSetSpawnEvent
          • PlayerFlyableFallEvent
          • LoadFromFile in PlayerEvent
          • PermissionsChangedEvent
          • CriticalHitEvent
          • StartTracking in PlayerEvent
          • ItemFishedEvent
          • ArrowNockEvent
          • PlayerRespawnEvent in PlayerEvent
          • ItemTooltipEvent
          • SaveToFile in PlayerEvent
          • PlayerLoggedInEvent in PlayerEvent
          • ItemCraftedEvent in PlayerEvent
          • NameFormat in PlayerEvent
          • RenderPlayerEvent
            • Post in RenderPlayerEvent
            • Pre in RenderPlayerEvent
          • AttackEntityEvent
          • PlayerBrewedPotionEvent
        • ShieldBlockEvent
        • LivingHealEvent
        • LootingLevelEvent
        • LivingDestroyBlockEvent
        • LivingConversionEvent
          • Pre in LivingConversionEvent
          • Post in LivingConversionEvent
        • LivingKnockBackEvent
        • LivingHurtEvent
        • LivingVisibilityEvent in LivingEvent
        • LivingDeathEvent
        • AnimalTameEvent
        • LivingFallEvent
        • LivingGetProjectileEvent
        • LivingSetAttackTargetEvent
        • LivingSpawnEvent
          • AllowDespawn in LivingSpawnEvent
          • CheckSpawn in LivingSpawnEvent
          • SpecialSpawn in LivingSpawnEvent
        • LivingJumpEvent in LivingEvent
        • LivingDropsEvent
      • ZombieEvent
        • SummonAidEvent in ZombieEvent
      • EntityLeaveWorldEvent
      • ItemEvent
        • ItemTossEvent
        • ItemExpireEvent
    • NetworkEvent
      • ServerCustomPayloadEvent in NetworkEvent
        • ServerCustomPayloadLoginEvent in NetworkEvent
      • LoginPayloadEvent in NetworkEvent
      • ChannelRegistrationChangeEvent in NetworkEvent
      • ClientCustomPayloadEvent in NetworkEvent
        • ClientCustomPayloadLoginEvent in NetworkEvent
    • GatherLoginPayloadsEvent in NetworkEvent
    • ChunkWatchEvent
      • UnWatch in ChunkWatchEvent
      • Watch in ChunkWatchEvent

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

The mod-specific event buses are provided by the 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.

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).

Error creating thumbnail: Unable to save thumbnail to destination
A visual guide on how event listeners are registered.

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 and IEventBus#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 or static methods annotated with @SubscribeEvent from the class which is represented by the passed in Class<?>
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 Dists to load this event subscriber on. This can be used to not load client specific event subscribers on the dedicated server.


An example for a static event listener listening to RenderWorldLastEvent which will only be called on the physical client:

@Mod.EventBusSubscriber(modid = "examplemod", dist = Dist.CLIENT)
public class MyStaticClientOnlyEventHandler {
    @SubscribeEvent
    public static void drawLast(RenderWorldLastEvent event) {
        System.out.println("Drawing!");
    }
}

Important

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

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

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 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

Not all events can be cancelled! Attempting to cancel an event that is not cancellable will result in an unchecked 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

Different events may use results in different ways, refer to the event's JavaDoc before using the result.

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)
      • RenderWorldLastEvent - Fired after world rendering to allow mods to add custom renders
      • RenderHandEvent - Fired before and after the hand of the player is rendered in the first person POV
      • RenderLivingEvent - Fired before and after a LivingRenderer is executed
      • RenderItemInFrameEvent - Fired before the item in an ItemFrameEntity is rendered
      • RenderBlockOverlayEvent - Fired before the block overlay for the player's screen is rendered
      • DrawHighlightEvent - Fired before the block highlight outline is rendered
      • RenderTooltipEvent - Fired before and during rendering of a text tooltip on a screen
      • EntityViewRenderEvent - Superclass for events relating to the player's viewpoint
      • RenderGameOverlayEvent - Superclass, fired for each element on the player's HUD or game overlay
      • FOVUpdateEvent - Fired when the FOV of the player is requested (?)
    • GUI/Screen events (client-only)
      • GuiScreenEvent - Superclass for events relating to Screens
      • GuiContainerEvent - Superclsas for events relating to ContainerScreens
      • GuiOpenEvent - 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 type
      • BlockEvent - Superclass for events relating to a block within the world
      • WorldEvent - Superclass for events relating to the world
      • InputEvent - (client-only) Superclass for events relating to the player's keyboard and mouse inputs
      • NetworkEvent - Superclass for events relating to networking
      • ExplosionEvent - Fired before an explosion explodes in the world
      • SoundEvent - (client-only) Superclass for events related to sounds
      • EntityEvent - Superclass for events relating to entities
      • TickEvent - 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 message
      • ClientChatEvent (client-only) - Fired before the client is about to send a chat message
      • ClientChatReceivedEvent (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
      • ClientPlayerChangeGamemodeEvent
    • Trade events
      • WandererTradesEvent
      • VillagerTradesEvent
    • Other events
      • FurnaceFuelBurnTimeEvent
      • BabyEntitySpawnEvent
      • VillageSiegeEvent
      • TagsUpdatedEvent
      • PotionBrewEvent
      • ScreenshotEvent
      • EnchantmentLevelSetEvent
      • CommandEvent
      • AnvilUpdateEvent
      • ItemAttributeModifierEvent
      • ClientPlayerNetworkEvent
      • ChunkWatchEvent

Like before, each of these events (especially the Super Events, which contain most of the useful events in the game) will have their own article explaining their purpose and usefulness.