Subscribing to Events
The PackedPacksApi instance injected on the entrypoint provides the EventBus instance which allows
the posting and subscribing of events.
Registration of listeners is only permitted during the initialization inside PackedPacksInitializer#onInitialize.
Events
The following are the out-of-the-box events that you can subscribe to:
TIP
For more information, you can view the events package which includes javadocs for each event and event methods
| Event Class | Timing | Typical Use Case |
|---|---|---|
InitializeEvent.Pre | Within Screen#init before everything else runs | Set up widgets |
InitializeEvent.Post | Within Screen#init after everything else runs | Adding widgets |
InitializeLayoutEvent | When the header and footer is being created | Adding widgets to specific positions |
InitializePackEntryEvent | When a pack entry is created | Attaching widgets to pack entries |
ContextMenuEvent.Screen | When the context menu is created for the screen | Adding context menu items |
ContextMenuEvent.Preferences | When the context menu is created for the preferences sub-menu | Adding preference items in the preferences sub-menu |
ContextMenuEvent.PackEntry | When the context menu is created for the pack entry | Adding context menu items for specific packs |
ClosingEvent | When the screen is closing | Saving data or calling commit() to apply changes |
WatchEvent | When a file change is detected in a pack folder | Calling cancel() to prevent unecessary refreshes |
Basic Registration
Create an Identifier which uniquely identifies your listeners and is used for ordering.
Register your listener with the ID using EventBus#register(Class<Event>, Identifier, Consumer<Event>).
NOTE
You cannot register multiple listeners of the same event under the same ID.
@Override
public void onInitialize(PackedPacksApi api) {
Identifier id = Identifier.fromNamespaceAndPath("modid", "my_listener");
api.eventBus().register(InitializeLayoutEvent.class, id, event -> {
// handle event
});
}Ordered Registration
To ensure your listener runs after another, use the loadAfter overloads:
Identifier id = Identifier.fromNamespaceAndPath("modid", "my_listener");
Identifier otherId = Identifier.fromNamespaceAndPath("other_modid", "other_listener");
Identifier anotherId = Identifier.fromNamespaceAndPath("another_modid", "another_listener");
// after a single listener
api.eventBus().register(InitializeEvent.Pre.class, id, otherId, event -> {
// handle event
});
// after multiple listeners
api.eventBus().register(InitializeEvent.Post.class, id, List.of(otherId, anotherId), event -> {
// handle event
});Posting Events
You can create and dispatch custom events to registered listeners. This can only be done after the initialization phase, usually inside another event handler.
For example to collect child context menu items for a parent context menu item.
public class PackedPacksIntegrationFoo implements PackedPacksInitializer {
@Override
public void onInitialize(PackedPacksApi api) {
Identifier id = Identifier.fromNamespaceAndPath("foo", "context_menu_foo");
api.eventBus().register(ContextMenuEvent.Screen.class, id, event ->
event.addItem(item -> api.eventBus().post(new FooEvent(
event.screenContext(),
item.label(Component.literal("Foo")).separators())
))
);
}
// We implement the Event marker interface to allow it to be posted and be subscribed to
public static final class FooEvent extends ContextMenuEvent implements Event {
private final ContextMenuItemSpec parent;
public TestEvent(ScreenContext context, ContextMenuItemSpec parent) {
super(context);
this.parent = parent;
}
@Override
public void addItem(Consumer<ContextMenuItemSpec> configurator) {
this.parent.child(configurator);
}
}
}public class PackedPacksIntegrationBar implements PackedPacksInitializer {
@Override
public void onInitialize(PackedPacksApi api) {
Identifier id = Identifier.fromNamespaceAndPath("bar", "context_menu_foo");
api.eventBus().register(PackedPacksIntegrationFoo.FooEvent.class, id, event ->
event.addItem(Component.literal("Bar"))
);
}
}