diff --git a/common/src/main/java/dev/architectury/event/Event.java b/common/src/main/java/dev/architectury/event/Event.java index 6449e309..73fe5db7 100644 --- a/common/src/main/java/dev/architectury/event/Event.java +++ b/common/src/main/java/dev/architectury/event/Event.java @@ -22,8 +22,12 @@ package dev.architectury.event; public interface Event { T invoker(); + T invoker(EventPriority priority); + void register(T listener); + void register(EventPriority priority, T listener); + void unregister(T listener); boolean isRegistered(T listener); diff --git a/common/src/main/java/dev/architectury/event/EventFactory.java b/common/src/main/java/dev/architectury/event/EventFactory.java index 37270fa5..ace31cb1 100644 --- a/common/src/main/java/dev/architectury/event/EventFactory.java +++ b/common/src/main/java/dev/architectury/event/EventFactory.java @@ -28,9 +28,7 @@ import org.jetbrains.annotations.ApiStatus; import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.function.Consumer; import java.util.function.Function; @@ -196,15 +194,106 @@ public final class EventFactory { private static class EventImpl implements Event { private final Function, T> function; - private T invoker = null; - private ArrayList listeners; + private final Map> invokers; + private List listeners; + private final Invoker overallInvoker; + private final T emptyInvoker; public EventImpl(Function, T> function) { + this.function = function; + this.invokers = new EnumMap<>(EventPriority.class); + this.invokers.put(EventPriority.NORMAL, new IndividualInvoker<>(this.function)); + this.overallInvoker = new Invoker<>(this.function, this.listeners); + this.buildListeners(); + this.emptyInvoker = this.function.apply(Collections.emptyList()); + } + + private void buildListeners() { + if (this.invokers.size() == 1) { + this.listeners = this.invokers.values().iterator().next().listeners; + } else { + this.listeners = new ArrayList<>(); + for (var invoker : this.invokers.values()) { + this.listeners.addAll(invoker.listeners); + } + } + this.overallInvoker.listeners = this.listeners; + this.overallInvoker.invoker = null; + } + + @Override + public T invoker() { + return this.overallInvoker.invoker(); + } + + @Override + public T invoker(EventPriority priority) { + IndividualInvoker invoker = this.invokers.get(priority); + + if (invoker != null) { + return invoker.invoker(); + } else { + return emptyInvoker; + } + } + + @Override + public void register(T listener) { + this.register(EventPriority.NORMAL, listener); + } + + @Override + public void register(EventPriority priority, T listener) { + this.getOrCreatePriority(priority).register(listener); + this.buildListeners(); + } + + @Override + public void unregister(T listener) { + for (var invoker : this.invokers.values()) { + invoker.unregister(listener); + } + this.buildListeners(); + } + + @Override + public boolean isRegistered(T listener) { + return overallInvoker.listeners.contains(listener); + } + + private IndividualInvoker getOrCreatePriority(EventPriority priority) { + IndividualInvoker invoker = this.invokers.get(priority); + + if (invoker == null) { + invoker = new IndividualInvoker<>(this.function); + this.invokers.put(priority, invoker); + } + + return invoker; + } + + @Override + public void clearListeners() { + this.invokers.put(EventPriority.NORMAL, new IndividualInvoker<>(this.function)); + this.buildListeners(); + } + } + + private static class Invoker { + protected final Function, T> function; + protected T invoker = null; + protected List listeners; + + public Invoker(Function, T> function) { this.function = function; this.listeners = new ArrayList<>(); } - @Override + public Invoker(Function, T> function, List listeners) { + this.function = function; + this.listeners = listeners; + } + public T invoker() { if (invoker == null) { update(); @@ -212,31 +301,6 @@ public final class EventFactory { return invoker; } - @Override - public void register(T listener) { - listeners.add(listener); - invoker = null; - } - - @Override - public void unregister(T listener) { - listeners.remove(listener); - listeners.trimToSize(); - invoker = null; - } - - @Override - public boolean isRegistered(T listener) { - return listeners.contains(listener); - } - - @Override - public void clearListeners() { - listeners.clear(); - listeners.trimToSize(); - invoker = null; - } - public void update() { if (listeners.size() == 1) { invoker = listeners.get(0); @@ -245,4 +309,35 @@ public final class EventFactory { } } } + + private static class IndividualInvoker extends Invoker { + public IndividualInvoker(Function, T> function) { + super(function); + } + + public IndividualInvoker(Function, T> function, ArrayList listeners) { + super(function, listeners); + } + + public void register(T listener) { + listeners.add(listener); + invoker = null; + } + + public void unregister(T listener) { + listeners.remove(listener); + if (listeners instanceof ArrayList arrayList) { + arrayList.trimToSize(); + } + invoker = null; + } + + public void clearListeners() { + listeners.clear(); + if (listeners instanceof ArrayList arrayList) { + arrayList.trimToSize(); + } + invoker = null; + } + } } diff --git a/common/src/main/java/dev/architectury/event/EventPriority.java b/common/src/main/java/dev/architectury/event/EventPriority.java new file mode 100644 index 00000000..612349d3 --- /dev/null +++ b/common/src/main/java/dev/architectury/event/EventPriority.java @@ -0,0 +1,30 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.event; + +public enum EventPriority { + HIGHEST, + HIGH, + NORMAL, + LOW, + LOWEST; + + public static final EventPriority[] VALUES = values(); +} \ No newline at end of file diff --git a/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java b/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java index bddfe3e3..bd1b35a6 100644 --- a/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java +++ b/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java @@ -19,6 +19,7 @@ package dev.architectury.event.fabric; +import dev.architectury.event.EventPriority; import dev.architectury.event.events.client.ClientGuiEvent; import dev.architectury.event.events.client.ClientLifecycleEvent; import dev.architectury.event.events.client.ClientTickEvent; @@ -42,57 +43,74 @@ import net.fabricmc.fabric.api.event.player.UseItemCallback; import net.fabricmc.fabric.api.loot.v2.LootTableEvents; import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent; import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; +import net.minecraft.resources.ResourceLocation; -import java.util.concurrent.CompletableFuture; +import java.util.function.Function; public class EventHandlerImpl { + public static final ResourceLocation HIGHEST = new ResourceLocation("architectury", "highest"); + public static final ResourceLocation HIGH = new ResourceLocation("architectury", "high"); + public static final ResourceLocation LOW = new ResourceLocation("architectury", "low"); + public static final ResourceLocation LOWEST = new ResourceLocation("architectury", "lowest"); + public static final ResourceLocation[] PHASES = new ResourceLocation[]{HIGHEST, HIGH, net.fabricmc.fabric.api.event.Event.DEFAULT_PHASE, LOW, LOWEST}; + @Environment(EnvType.CLIENT) public static void registerClient() { - ClientLifecycleEvents.CLIENT_STARTED.register(instance -> ClientLifecycleEvent.CLIENT_STARTED.invoker().stateChanged(instance)); - ClientLifecycleEvents.CLIENT_STOPPING.register(instance -> ClientLifecycleEvent.CLIENT_STOPPING.invoker().stateChanged(instance)); + registerWithPriority(ClientLifecycleEvents.CLIENT_STARTED, priority -> instance -> ClientLifecycleEvent.CLIENT_STARTED.invoker(priority).stateChanged(instance)); + registerWithPriority(ClientLifecycleEvents.CLIENT_STOPPING, priority -> instance -> ClientLifecycleEvent.CLIENT_STOPPING.invoker(priority).stateChanged(instance)); - ClientTickEvents.START_CLIENT_TICK.register(instance -> ClientTickEvent.CLIENT_PRE.invoker().tick(instance)); - ClientTickEvents.END_CLIENT_TICK.register(instance -> ClientTickEvent.CLIENT_POST.invoker().tick(instance)); - ClientTickEvents.START_WORLD_TICK.register(instance -> ClientTickEvent.CLIENT_LEVEL_PRE.invoker().tick(instance)); - ClientTickEvents.END_WORLD_TICK.register(instance -> ClientTickEvent.CLIENT_LEVEL_POST.invoker().tick(instance)); + registerWithPriority(ClientTickEvents.START_CLIENT_TICK, priority -> instance -> ClientTickEvent.CLIENT_PRE.invoker(priority).tick(instance)); + registerWithPriority(ClientTickEvents.END_CLIENT_TICK, priority -> instance -> ClientTickEvent.CLIENT_POST.invoker(priority).tick(instance)); + registerWithPriority(ClientTickEvents.START_WORLD_TICK, priority -> instance -> ClientTickEvent.CLIENT_LEVEL_PRE.invoker(priority).tick(instance)); + registerWithPriority(ClientTickEvents.END_WORLD_TICK, priority -> instance -> ClientTickEvent.CLIENT_LEVEL_POST.invoker(priority).tick(instance)); - ItemTooltipCallback.EVENT.register((itemStack, tooltipFlag, list) -> ClientTooltipEvent.ITEM.invoker().append(itemStack, list, tooltipFlag)); - HudRenderCallback.EVENT.register((graphics, tickDelta) -> ClientGuiEvent.RENDER_HUD.invoker().renderHud(graphics, tickDelta)); + registerWithPriority(ItemTooltipCallback.EVENT, priority -> (itemStack, tooltipFlag, list) -> ClientTooltipEvent.ITEM.invoker(priority).append(itemStack, list, tooltipFlag)); + registerWithPriority(HudRenderCallback.EVENT, priority -> (graphics, tickDelta) -> ClientGuiEvent.RENDER_HUD.invoker(priority).renderHud(graphics, tickDelta)); } public static void registerCommon() { - ServerLifecycleEvents.SERVER_STARTING.register(instance -> LifecycleEvent.SERVER_BEFORE_START.invoker().stateChanged(instance)); - ServerLifecycleEvents.SERVER_STARTED.register(instance -> LifecycleEvent.SERVER_STARTED.invoker().stateChanged(instance)); - ServerLifecycleEvents.SERVER_STOPPING.register(instance -> LifecycleEvent.SERVER_STOPPING.invoker().stateChanged(instance)); - ServerLifecycleEvents.SERVER_STOPPED.register(instance -> LifecycleEvent.SERVER_STOPPED.invoker().stateChanged(instance)); + registerWithPriority(ServerLifecycleEvents.SERVER_STARTING, priority -> instance -> LifecycleEvent.SERVER_BEFORE_START.invoker(priority).stateChanged(instance)); + registerWithPriority(ServerLifecycleEvents.SERVER_STARTED, priority -> instance -> LifecycleEvent.SERVER_STARTED.invoker(priority).stateChanged(instance)); + registerWithPriority(ServerLifecycleEvents.SERVER_STOPPING, priority -> instance -> LifecycleEvent.SERVER_STOPPING.invoker(priority).stateChanged(instance)); + registerWithPriority(ServerLifecycleEvents.SERVER_STOPPED, priority -> instance -> LifecycleEvent.SERVER_STOPPED.invoker(priority).stateChanged(instance)); - ServerTickEvents.START_SERVER_TICK.register(instance -> TickEvent.SERVER_PRE.invoker().tick(instance)); - ServerTickEvents.END_SERVER_TICK.register(instance -> TickEvent.SERVER_POST.invoker().tick(instance)); - ServerTickEvents.START_WORLD_TICK.register(instance -> TickEvent.SERVER_LEVEL_PRE.invoker().tick(instance)); - ServerTickEvents.END_WORLD_TICK.register(instance -> TickEvent.SERVER_LEVEL_POST.invoker().tick(instance)); + registerWithPriority(ServerTickEvents.START_SERVER_TICK, priority -> instance -> TickEvent.SERVER_PRE.invoker(priority).tick(instance)); + registerWithPriority(ServerTickEvents.END_SERVER_TICK, priority -> instance -> TickEvent.SERVER_POST.invoker(priority).tick(instance)); + registerWithPriority(ServerTickEvents.START_WORLD_TICK, priority -> instance -> TickEvent.SERVER_LEVEL_PRE.invoker(priority).tick(instance)); + registerWithPriority(ServerTickEvents.END_WORLD_TICK, priority -> instance -> TickEvent.SERVER_LEVEL_POST.invoker(priority).tick(instance)); - ServerWorldEvents.LOAD.register((server, world) -> LifecycleEvent.SERVER_LEVEL_LOAD.invoker().act(world)); - ServerWorldEvents.UNLOAD.register((server, world) -> LifecycleEvent.SERVER_LEVEL_UNLOAD.invoker().act(world)); + registerWithPriority(ServerWorldEvents.LOAD, priority -> (server, world) -> LifecycleEvent.SERVER_LEVEL_LOAD.invoker(priority).act(world)); + registerWithPriority(ServerWorldEvents.UNLOAD, priority -> (server, world) -> LifecycleEvent.SERVER_LEVEL_UNLOAD.invoker(priority).act(world)); - CommandRegistrationCallback.EVENT.register((dispatcher, registry, selection) -> CommandRegistrationEvent.EVENT.invoker().register(dispatcher, registry, selection)); + registerWithPriority(CommandRegistrationCallback.EVENT, priority -> (dispatcher, registry, selection) -> CommandRegistrationEvent.EVENT.invoker(priority).register(dispatcher, registry, selection)); - UseItemCallback.EVENT.register((player, world, hand) -> InteractionEvent.RIGHT_CLICK_ITEM.invoker().click(player, hand).asMinecraft()); - UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> InteractionEvent.RIGHT_CLICK_BLOCK.invoker().click(player, hand, hitResult.getBlockPos(), hitResult.getDirection()).asMinecraft()); - AttackBlockCallback.EVENT.register((player, world, hand, pos, face) -> InteractionEvent.LEFT_CLICK_BLOCK.invoker().click(player, hand, pos, face).asMinecraft()); - AttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> PlayerEvent.ATTACK_ENTITY.invoker().attack(player, world, entity, hand, hitResult).asMinecraft()); + registerWithPriority(UseItemCallback.EVENT, priority -> (player, world, hand) -> InteractionEvent.RIGHT_CLICK_ITEM.invoker(priority).click(player, hand).asMinecraft()); + registerWithPriority(UseBlockCallback.EVENT, priority -> (player, world, hand, hitResult) -> InteractionEvent.RIGHT_CLICK_BLOCK.invoker(priority).click(player, hand, hitResult.getBlockPos(), hitResult.getDirection()).asMinecraft()); + registerWithPriority(AttackBlockCallback.EVENT, priority -> (player, world, hand, pos, face) -> InteractionEvent.LEFT_CLICK_BLOCK.invoker(priority).click(player, hand, pos, face).asMinecraft()); + registerWithPriority(AttackEntityCallback.EVENT, priority -> (player, world, hand, entity, hitResult) -> PlayerEvent.ATTACK_ENTITY.invoker(priority).attack(player, world, entity, hand, hitResult).asMinecraft()); - LootTableEvents.MODIFY.register((resourceManager, lootManager, id, tableBuilder, source) -> LootEvent.MODIFY_LOOT_TABLE.invoker().modifyLootTable(lootManager, id, new LootTableModificationContextImpl(tableBuilder), source.isBuiltin())); + registerWithPriority(LootTableEvents.MODIFY, priority -> (resourceManager, lootManager, id, tableBuilder, source) -> LootEvent.MODIFY_LOOT_TABLE.invoker(priority).modifyLootTable(lootManager, id, new LootTableModificationContextImpl(tableBuilder), source.isBuiltin())); ServerMessageDecoratorEvent.EVENT.register(ServerMessageDecoratorEvent.CONTENT_PHASE, (player, component) -> { ChatEvent.ChatComponent chatComponent = new ChatComponentImpl(component); ChatEvent.DECORATE.invoker().decorate(player, chatComponent); return chatComponent.get(); }); - ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((message, sender, params) -> { - return !ChatEvent.RECEIVED.invoker().received(sender, message.decoratedContent()).isFalse(); + registerWithPriority(ServerMessageEvents.ALLOW_CHAT_MESSAGE, priority -> (message, sender, params) -> { + return !ChatEvent.RECEIVED.invoker(priority).received(sender, message.decoratedContent()).isFalse(); }); } + private static void registerWithPriority(net.fabricmc.fabric.api.event.Event fabricEvent, Function listener) { + fabricEvent.addPhaseOrdering(HIGH, net.fabricmc.fabric.api.event.Event.DEFAULT_PHASE); + fabricEvent.addPhaseOrdering(HIGHEST, HIGH); + fabricEvent.addPhaseOrdering(net.fabricmc.fabric.api.event.Event.DEFAULT_PHASE, LOW); + fabricEvent.addPhaseOrdering(LOW, LOWEST); + for (EventPriority priority : EventPriority.VALUES) { + fabricEvent.register(PHASES[priority.ordinal()], listener.apply(priority)); + } + } + @Environment(EnvType.SERVER) public static void registerServer() { diff --git a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImpl.java b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImpl.java index 86137582..2de029e1 100644 --- a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImpl.java +++ b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImpl.java @@ -28,17 +28,13 @@ import net.minecraftforge.common.MinecraftForge; public class EventHandlerImpl { @OnlyIn(Dist.CLIENT) public static void registerClient() { - MinecraftForge.EVENT_BUS.register(EventHandlerImplClient.class); - EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> { - bus.register(EventHandlerImplClient.ModBasedEventHandler.class); - }); + EventHandlerImplClient.init(); + EventBuses.onRegistered(ArchitecturyForge.MOD_ID, EventHandlerImplClient.ModBasedEventHandler::init); } public static void registerCommon() { - MinecraftForge.EVENT_BUS.register(EventHandlerImplCommon.class); - EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> { - bus.register(EventHandlerImplCommon.ModBasedEventHandler.class); - }); + EventHandlerImplCommon.init(); + EventBuses.onRegistered(ArchitecturyForge.MOD_ID, EventHandlerImplCommon.ModBasedEventHandler::init); } @OnlyIn(Dist.DEDICATED_SERVER) diff --git a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java index 97edb06a..d17d1e07 100644 --- a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java +++ b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java @@ -20,6 +20,7 @@ package dev.architectury.event.forge; import dev.architectury.event.CompoundEventResult; +import dev.architectury.event.EventPriority; import dev.architectury.event.EventResult; import dev.architectury.event.events.client.ClientChatEvent; import dev.architectury.event.events.client.*; @@ -35,79 +36,116 @@ import net.minecraft.network.chat.Component; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.*; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.level.LevelEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import java.util.function.BiConsumer; + @OnlyIn(Dist.CLIENT) public class EventHandlerImplClient { - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ItemTooltipEvent event) { - ClientTooltipEvent.ITEM.invoker().append(event.getItemStack(), event.getToolTip(), event.getFlags()); + public static void init() { + for (EventPriority priority : EventPriority.VALUES) { + registerWithPriority(priority, ItemTooltipEvent.class, EventHandlerImplClient::event); + registerWithPriority(priority, net.minecraftforge.event.TickEvent.ClientTickEvent.class, EventHandlerImplClient::event); + registerWithPriority(priority, RenderGuiEvent.Post.class, EventHandlerImplClient::eventRenderGameOverlayEvent); + registerWithPriority(priority, ClientPlayerNetworkEvent.LoggingIn.class, EventHandlerImplClient::event); + registerWithPriority(priority, ClientPlayerNetworkEvent.LoggingOut.class, EventHandlerImplClient::event); + registerWithPriority(priority, ClientPlayerNetworkEvent.Clone.class, EventHandlerImplClient::event); + registerWithPriority(priority, ScreenEvent.Init.Pre.class, EventHandlerImplClient::eventInitScreenEvent); + registerWithPriority(priority, ScreenEvent.Init.Post.class, EventHandlerImplClient::eventInitScreenEvent); + registerWithPriority(priority, CustomizeGuiOverlayEvent.DebugText.class, EventHandlerImplClient::eventRenderGameOverlayEvent); + registerWithPriority(priority, net.minecraftforge.client.event.ClientChatEvent.class, EventHandlerImplClient::event); + registerWithPriority(priority, ClientChatReceivedEvent.class, EventHandlerImplClient::event); + registerWithPriority(priority, LevelEvent.Load.class, EventHandlerImplClient::eventWorldEvent); + registerWithPriority(priority, ScreenEvent.Opening.class, EventHandlerImplClient::event); + registerWithPriority(priority, ScreenEvent.Render.Pre.class, EventHandlerImplClient::eventDrawScreenEvent); + registerWithPriority(priority, ScreenEvent.Render.Post.class, EventHandlerImplClient::eventDrawScreenEvent); + registerWithPriority(priority, ContainerScreenEvent.Render.Background.class, EventHandlerImplClient::eventContainerScreenEvent); + registerWithPriority(priority, ContainerScreenEvent.Render.Foreground.class, EventHandlerImplClient::eventContainerScreenEvent); + registerWithPriority(priority, PlayerInteractEvent.RightClickEmpty.class, EventHandlerImplClient::eventPlayerInteractEvent); + registerWithPriority(priority, PlayerInteractEvent.LeftClickEmpty.class, EventHandlerImplClient::eventPlayerInteractEvent); + registerWithPriority(priority, RecipesUpdatedEvent.class, EventHandlerImplClient::event); + registerWithPriority(priority, RenderTooltipEvent.Pre.class, EventHandlerImplClient::eventRenderTooltipEvent); + registerWithPriority(priority, RenderTooltipEvent.Color.class, EventHandlerImplClient::eventRenderTooltipEvent); + registerWithPriority(priority, ScreenEvent.MouseScrolled.Pre.class, EventHandlerImplClient::eventMouseScrollEvent); + registerWithPriority(priority, ScreenEvent.MouseScrolled.Post.class, EventHandlerImplClient::eventMouseScrollEvent); + registerWithPriority(priority, ScreenEvent.MouseButtonPressed.Pre.class, EventHandlerImplClient::eventMouseClickedEvent); + registerWithPriority(priority, ScreenEvent.MouseButtonPressed.Post.class, EventHandlerImplClient::eventMouseClickedEvent); + registerWithPriority(priority, ScreenEvent.MouseDragged.Pre.class, EventHandlerImplClient::eventMouseDragEvent); + registerWithPriority(priority, ScreenEvent.MouseDragged.Post.class, EventHandlerImplClient::eventMouseDragEvent); + registerWithPriority(priority, ScreenEvent.MouseButtonReleased.Pre.class, EventHandlerImplClient::eventMouseReleasedEvent); + registerWithPriority(priority, ScreenEvent.MouseButtonReleased.Post.class, EventHandlerImplClient::eventMouseReleasedEvent); + registerWithPriority(priority, ScreenEvent.CharacterTyped.Pre.class, EventHandlerImplClient::eventKeyboardCharTypedEvent); + registerWithPriority(priority, ScreenEvent.CharacterTyped.Post.class, EventHandlerImplClient::eventKeyboardCharTypedEvent); + registerWithPriority(priority, ScreenEvent.KeyPressed.Pre.class, EventHandlerImplClient::eventKeyboardKeyPressedEvent); + registerWithPriority(priority, ScreenEvent.KeyPressed.Post.class, EventHandlerImplClient::eventKeyboardKeyPressedEvent); + registerWithPriority(priority, ScreenEvent.KeyReleased.Pre.class, EventHandlerImplClient::eventKeyboardKeyReleasedEvent); + registerWithPriority(priority, ScreenEvent.KeyReleased.Post.class, EventHandlerImplClient::eventKeyboardKeyReleasedEvent); + registerWithPriority(priority, InputEvent.MouseScrollingEvent.class, EventHandlerImplClient::eventInputEvent); + registerWithPriority(priority, InputEvent.MouseButton.Pre.class, EventHandlerImplClient::eventInputEvent); + registerWithPriority(priority, InputEvent.MouseButton.Post.class, EventHandlerImplClient::eventInputEvent); + registerWithPriority(priority, InputEvent.Key.class, EventHandlerImplClient::eventInputEvent); + } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(net.minecraftforge.event.TickEvent.ClientTickEvent event) { + public static void event(ItemTooltipEvent event, EventPriority priority) { + ClientTooltipEvent.ITEM.invoker(priority).append(event.getItemStack(), event.getToolTip(), event.getFlags()); + } + + public static void event(net.minecraftforge.event.TickEvent.ClientTickEvent event, EventPriority priority) { if (event.phase == net.minecraftforge.event.TickEvent.Phase.START) - ClientTickEvent.CLIENT_PRE.invoker().tick(Minecraft.getInstance()); + ClientTickEvent.CLIENT_PRE.invoker(priority).tick(Minecraft.getInstance()); else if (event.phase == net.minecraftforge.event.TickEvent.Phase.END) - ClientTickEvent.CLIENT_POST.invoker().tick(Minecraft.getInstance()); + ClientTickEvent.CLIENT_POST.invoker(priority).tick(Minecraft.getInstance()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventRenderGameOverlayEvent(RenderGuiEvent.Post event) { - ClientGuiEvent.RENDER_HUD.invoker().renderHud(event.getGuiGraphics(), event.getPartialTick()); + public static void eventRenderGameOverlayEvent(RenderGuiEvent.Post event, EventPriority priority) { + ClientGuiEvent.RENDER_HUD.invoker(priority).renderHud(event.getGuiGraphics(), event.getPartialTick()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ClientPlayerNetworkEvent.LoggingIn event) { - ClientPlayerEvent.CLIENT_PLAYER_JOIN.invoker().join(event.getPlayer()); + public static void event(ClientPlayerNetworkEvent.LoggingIn event, EventPriority priority) { + ClientPlayerEvent.CLIENT_PLAYER_JOIN.invoker(priority).join(event.getPlayer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ClientPlayerNetworkEvent.LoggingOut event) { - ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(event.getPlayer()); + public static void event(ClientPlayerNetworkEvent.LoggingOut event, EventPriority priority) { + ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker(priority).quit(event.getPlayer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ClientPlayerNetworkEvent.Clone event) { - ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.invoker().respawn(event.getOldPlayer(), event.getNewPlayer()); + public static void event(ClientPlayerNetworkEvent.Clone event, EventPriority priority) { + ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.invoker(priority).respawn(event.getOldPlayer(), event.getNewPlayer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventInitScreenEvent(ScreenEvent.Init.Pre event) { - if (ClientGuiEvent.INIT_PRE.invoker().init(event.getScreen(), new ScreenAccessImpl(event.getScreen())).isFalse()) { + public static void eventInitScreenEvent(ScreenEvent.Init.Pre event, EventPriority priority) { + if (ClientGuiEvent.INIT_PRE.invoker(priority).init(event.getScreen(), new ScreenAccessImpl(event.getScreen())).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventInitScreenEvent(ScreenEvent.Init.Post event) { - ClientGuiEvent.INIT_POST.invoker().init(event.getScreen(), new ScreenAccessImpl(event.getScreen())); + public static void eventInitScreenEvent(ScreenEvent.Init.Post event, EventPriority priority) { + ClientGuiEvent.INIT_POST.invoker(priority).init(event.getScreen(), new ScreenAccessImpl(event.getScreen())); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventRenderGameOverlayEvent(CustomizeGuiOverlayEvent.DebugText event) { + public static void eventRenderGameOverlayEvent(CustomizeGuiOverlayEvent.DebugText event, EventPriority priority) { if (Minecraft.getInstance().options.renderDebug) { - ClientGuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(event.getLeft()); - ClientGuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(event.getRight()); + ClientGuiEvent.DEBUG_TEXT_LEFT.invoker(priority).gatherText(event.getLeft()); + ClientGuiEvent.DEBUG_TEXT_RIGHT.invoker(priority).gatherText(event.getRight()); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(net.minecraftforge.client.event.ClientChatEvent event) { - EventResult process = ClientChatEvent.SEND.invoker().send(event.getMessage(), null); + public static void event(net.minecraftforge.client.event.ClientChatEvent event, EventPriority priority) { + EventResult process = ClientChatEvent.SEND.invoker(priority).send(event.getMessage(), null); if (process.isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ClientChatReceivedEvent event) { - CompoundEventResult process = ClientChatEvent.RECEIVED.invoker().process(event.getBoundChatType(), event.getMessage()); + public static void event(ClientChatReceivedEvent event, EventPriority priority) { + CompoundEventResult process = ClientChatEvent.RECEIVED.invoker(priority).process(event.getBoundChatType(), event.getMessage()); if (process.isPresent()) { if (process.isFalse()) event.setCanceled(true); @@ -116,17 +154,15 @@ public class EventHandlerImplClient { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventWorldEvent(LevelEvent.Load event) { + public static void eventWorldEvent(LevelEvent.Load event, EventPriority priority) { if (event.getLevel().isClientSide()) { ClientLevel world = (ClientLevel) event.getLevel(); - ClientLifecycleEvent.CLIENT_LEVEL_LOAD.invoker().act(world); + ClientLifecycleEvent.CLIENT_LEVEL_LOAD.invoker(priority).act(world); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ScreenEvent.Opening event) { - CompoundEventResult result = ClientGuiEvent.SET_SCREEN.invoker().modifyScreen(event.getScreen()); + public static void event(ScreenEvent.Opening event, EventPriority priority) { + CompoundEventResult result = ClientGuiEvent.SET_SCREEN.invoker(priority).modifyScreen(event.getScreen()); if (result.isPresent()) { if (result.isFalse()) event.setCanceled(true); @@ -135,59 +171,51 @@ public class EventHandlerImplClient { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventDrawScreenEvent(ScreenEvent.Render.Pre event) { - if (ClientGuiEvent.RENDER_PRE.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), event.getPartialTick()).isFalse()) { + public static void eventDrawScreenEvent(ScreenEvent.Render.Pre event, EventPriority priority) { + if (ClientGuiEvent.RENDER_PRE.invoker(priority).render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), event.getPartialTick()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventDrawScreenEvent(ScreenEvent.Render.Post event) { - ClientGuiEvent.RENDER_POST.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), event.getPartialTick()); + public static void eventDrawScreenEvent(ScreenEvent.Render.Post event, EventPriority priority) { + ClientGuiEvent.RENDER_POST.invoker(priority).render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), event.getPartialTick()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventContainerScreenEvent(ContainerScreenEvent.Render.Background event) { - ClientGuiEvent.RENDER_CONTAINER_BACKGROUND.invoker().render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaFrameTime()); + public static void eventContainerScreenEvent(ContainerScreenEvent.Render.Background event, EventPriority priority) { + ClientGuiEvent.RENDER_CONTAINER_BACKGROUND.invoker(priority).render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaFrameTime()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventContainerScreenEvent(ContainerScreenEvent.Render.Foreground event) { - ClientGuiEvent.RENDER_CONTAINER_FOREGROUND.invoker().render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaFrameTime()); + public static void eventContainerScreenEvent(ContainerScreenEvent.Render.Foreground event, EventPriority priority) { + ClientGuiEvent.RENDER_CONTAINER_FOREGROUND.invoker(priority).render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaFrameTime()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickEmpty event) { - InteractionEvent.CLIENT_RIGHT_CLICK_AIR.invoker().click(event.getEntity(), event.getHand()); + public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickEmpty event, EventPriority priority) { + InteractionEvent.CLIENT_RIGHT_CLICK_AIR.invoker(priority).click(event.getEntity(), event.getHand()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerInteractEvent(PlayerInteractEvent.LeftClickEmpty event) { - InteractionEvent.CLIENT_LEFT_CLICK_AIR.invoker().click(event.getEntity(), event.getHand()); + public static void eventPlayerInteractEvent(PlayerInteractEvent.LeftClickEmpty event, EventPriority priority) { + InteractionEvent.CLIENT_LEFT_CLICK_AIR.invoker(priority).click(event.getEntity(), event.getHand()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(RecipesUpdatedEvent event) { - ClientRecipeUpdateEvent.EVENT.invoker().update(event.getRecipeManager()); + public static void event(RecipesUpdatedEvent event, EventPriority priority) { + ClientRecipeUpdateEvent.EVENT.invoker(priority).update(event.getRecipeManager()); } private static final ThreadLocal tooltipPositionContext = ThreadLocal.withInitial(TooltipEventPositionContextImpl::new); - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventRenderTooltipEvent(RenderTooltipEvent.Pre event) { + public static void eventRenderTooltipEvent(RenderTooltipEvent.Pre event, EventPriority priority) { GuiGraphics graphics = event.getGraphics(); ClientTooltipEvent.additionalContexts().setItem(event.getItemStack()); try { - if (ClientTooltipEvent.RENDER_PRE.invoker().renderTooltip(graphics, event.getComponents(), event.getX(), event.getY()).isFalse()) { + if (ClientTooltipEvent.RENDER_PRE.invoker(priority).renderTooltip(graphics, event.getComponents(), event.getX(), event.getY()).isFalse()) { event.setCanceled(true); return; } TooltipEventPositionContextImpl positionContext = tooltipPositionContext.get(); positionContext.reset(event.getX(), event.getY()); - ClientTooltipEvent.RENDER_MODIFY_POSITION.invoker().renderTooltip(graphics, positionContext); + ClientTooltipEvent.RENDER_MODIFY_POSITION.invoker(priority).renderTooltip(graphics, positionContext); event.setX(positionContext.getTooltipX()); event.setY(positionContext.getTooltipY()); } finally { @@ -195,8 +223,7 @@ public class EventHandlerImplClient { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventRenderTooltipEvent(RenderTooltipEvent.Color event) { + public static void eventRenderTooltipEvent(RenderTooltipEvent.Color event, EventPriority priority) { GuiGraphics graphics = event.getGraphics(); ClientTooltipEvent.additionalContexts().setItem(event.getItemStack()); @@ -206,7 +233,7 @@ public class EventHandlerImplClient { colorContext.setBackgroundColor(event.getBackgroundStart()); colorContext.setOutlineGradientTopColor(event.getBorderStart()); colorContext.setOutlineGradientBottomColor(event.getBorderEnd()); - ClientTooltipEvent.RENDER_MODIFY_COLOR.invoker().renderTooltip(graphics, event.getX(), event.getY(), colorContext); + ClientTooltipEvent.RENDER_MODIFY_COLOR.invoker(priority).renderTooltip(graphics, event.getX(), event.getY(), colorContext); event.setBackground(colorContext.getBackgroundColor()); event.setBorderEnd(colorContext.getOutlineGradientBottomColor()); event.setBorderStart(colorContext.getOutlineGradientTopColor()); @@ -215,129 +242,126 @@ public class EventHandlerImplClient { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseScrollEvent(ScreenEvent.MouseScrolled.Pre event) { - if (ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getScrollDelta()).isFalse()) { + public static void eventMouseScrollEvent(ScreenEvent.MouseScrolled.Pre event, EventPriority priority) { + if (ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker(priority).mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getScrollDelta()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseScrollEvent(ScreenEvent.MouseScrolled.Post event) { - ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getScrollDelta()); + public static void eventMouseScrollEvent(ScreenEvent.MouseScrolled.Post event, EventPriority priority) { + ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker(priority).mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getScrollDelta()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseClickedEvent(ScreenEvent.MouseButtonPressed.Pre event) { - if (ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()).isFalse()) { + public static void eventMouseClickedEvent(ScreenEvent.MouseButtonPressed.Pre event, EventPriority priority) { + if (ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker(priority).mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseClickedEvent(ScreenEvent.MouseButtonPressed.Post event) { - ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()); + public static void eventMouseClickedEvent(ScreenEvent.MouseButtonPressed.Post event, EventPriority priority) { + ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker(priority).mouseClicked(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseDragEvent(ScreenEvent.MouseDragged.Pre event) { - if (ClientScreenInputEvent.MOUSE_DRAGGED_PRE.invoker().mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getMouseButton(), event.getDragX(), event.getDragY()).isFalse()) { + public static void eventMouseDragEvent(ScreenEvent.MouseDragged.Pre event, EventPriority priority) { + if (ClientScreenInputEvent.MOUSE_DRAGGED_PRE.invoker(priority).mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getMouseButton(), event.getDragX(), event.getDragY()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseDragEvent(ScreenEvent.MouseDragged.Post event) { - ClientScreenInputEvent.MOUSE_DRAGGED_POST.invoker().mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getMouseButton(), event.getDragX(), event.getDragY()); + public static void eventMouseDragEvent(ScreenEvent.MouseDragged.Post event, EventPriority priority) { + ClientScreenInputEvent.MOUSE_DRAGGED_POST.invoker(priority).mouseDragged(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getMouseButton(), event.getDragX(), event.getDragY()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseReleasedEvent(ScreenEvent.MouseButtonReleased.Pre event) { - if (ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()).isFalse()) { + public static void eventMouseReleasedEvent(ScreenEvent.MouseButtonReleased.Pre event, EventPriority priority) { + if (ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker(priority).mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventMouseReleasedEvent(ScreenEvent.MouseButtonReleased.Post event) { - ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()); + public static void eventMouseReleasedEvent(ScreenEvent.MouseButtonReleased.Post event, EventPriority priority) { + ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker(priority).mouseReleased(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getButton()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventKeyboardCharTypedEvent(ScreenEvent.CharacterTyped.Pre event) { - if (ClientScreenInputEvent.CHAR_TYPED_PRE.invoker().charTyped(Minecraft.getInstance(), event.getScreen(), event.getCodePoint(), event.getModifiers()).isFalse()) { + public static void eventKeyboardCharTypedEvent(ScreenEvent.CharacterTyped.Pre event, EventPriority priority) { + if (ClientScreenInputEvent.CHAR_TYPED_PRE.invoker(priority).charTyped(Minecraft.getInstance(), event.getScreen(), event.getCodePoint(), event.getModifiers()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventKeyboardCharTypedEvent(ScreenEvent.CharacterTyped.Post event) { - ClientScreenInputEvent.CHAR_TYPED_POST.invoker().charTyped(Minecraft.getInstance(), event.getScreen(), event.getCodePoint(), event.getModifiers()); + public static void eventKeyboardCharTypedEvent(ScreenEvent.CharacterTyped.Post event, EventPriority priority) { + ClientScreenInputEvent.CHAR_TYPED_POST.invoker(priority).charTyped(Minecraft.getInstance(), event.getScreen(), event.getCodePoint(), event.getModifiers()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventKeyboardKeyPressedEvent(ScreenEvent.KeyPressed.Pre event) { - if (ClientScreenInputEvent.KEY_PRESSED_PRE.invoker().keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()).isFalse()) { + public static void eventKeyboardKeyPressedEvent(ScreenEvent.KeyPressed.Pre event, EventPriority priority) { + if (ClientScreenInputEvent.KEY_PRESSED_PRE.invoker(priority).keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventKeyboardKeyPressedEvent(ScreenEvent.KeyPressed.Post event) { - ClientScreenInputEvent.KEY_PRESSED_POST.invoker().keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()); + public static void eventKeyboardKeyPressedEvent(ScreenEvent.KeyPressed.Post event, EventPriority priority) { + ClientScreenInputEvent.KEY_PRESSED_POST.invoker(priority).keyPressed(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventKeyboardKeyReleasedEvent(ScreenEvent.KeyReleased.Pre event) { - if (ClientScreenInputEvent.KEY_RELEASED_PRE.invoker().keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()).isFalse()) { + public static void eventKeyboardKeyReleasedEvent(ScreenEvent.KeyReleased.Pre event, EventPriority priority) { + if (ClientScreenInputEvent.KEY_RELEASED_PRE.invoker(priority).keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventKeyboardKeyReleasedEvent(ScreenEvent.KeyReleased.Post event) { - ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()); + public static void eventKeyboardKeyReleasedEvent(ScreenEvent.KeyReleased.Post event, EventPriority priority) { + ClientScreenInputEvent.KEY_RELEASED_POST.invoker(priority).keyReleased(Minecraft.getInstance(), event.getScreen(), event.getKeyCode(), event.getScanCode(), event.getModifiers()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventInputEvent(InputEvent.MouseScrollingEvent event) { - if (ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(Minecraft.getInstance(), event.getScrollDelta()).isFalse()) { + public static void eventInputEvent(InputEvent.MouseScrollingEvent event, EventPriority priority) { + if (ClientRawInputEvent.MOUSE_SCROLLED.invoker(priority).mouseScrolled(Minecraft.getInstance(), event.getScrollDelta()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventInputEvent(InputEvent.MouseButton.Pre event) { - if (ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getModifiers()).isFalse()) { + public static void eventInputEvent(InputEvent.MouseButton.Pre event, EventPriority priority) { + if (ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker(priority).mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getModifiers()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventInputEvent(InputEvent.MouseButton.Post event) { - ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getModifiers()); + public static void eventInputEvent(InputEvent.MouseButton.Post event, EventPriority priority) { + ClientRawInputEvent.MOUSE_CLICKED_POST.invoker(priority).mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getModifiers()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventInputEvent(InputEvent.Key event) { - ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(Minecraft.getInstance(), event.getKey(), event.getScanCode(), event.getAction(), event.getModifiers()); + public static void eventInputEvent(InputEvent.Key event, EventPriority priority) { + ClientRawInputEvent.KEY_PRESSED.invoker(priority).keyPressed(Minecraft.getInstance(), event.getKey(), event.getScanCode(), event.getAction(), event.getModifiers()); + } + + private static void registerWithPriority(EventPriority priority, Class type, BiConsumer callback) { + net.minecraftforge.eventbus.api.EventPriority forgePriority = net.minecraftforge.eventbus.api.EventPriority.valueOf(priority.name()); + MinecraftForge.EVENT_BUS.addListener(forgePriority, false, type, event -> callback.accept(event, priority)); } @OnlyIn(Dist.CLIENT) public static class ModBasedEventHandler { - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventTextureStitchEvent(TextureStitchEvent.Post event) { - // ClientTextureStitchEvent.POST.invoker().stitch(event.getAtlas()); + public static void init(IEventBus bus) { + for (EventPriority priority : EventPriority.VALUES) { + registerWithPriority(bus, priority, TextureStitchEvent.Post.class, ModBasedEventHandler::eventTextureStitchEvent); + registerWithPriority(bus, priority, FMLClientSetupEvent.class, ModBasedEventHandler::event); + registerWithPriority(bus, priority, RegisterShadersEvent.class, ModBasedEventHandler::event); + } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(FMLClientSetupEvent event) { - ClientLifecycleEvent.CLIENT_SETUP.invoker().stateChanged(Minecraft.getInstance()); + public static void eventTextureStitchEvent(TextureStitchEvent.Post event, EventPriority priority) { + // ClientTextureStitchEvent.POST.invoker(priority).stitch(event.getAtlas()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(RegisterShadersEvent event) { - ClientReloadShadersEvent.EVENT.invoker().reload(event.getResourceProvider(), event::registerShader); + public static void event(FMLClientSetupEvent event, EventPriority priority) { + ClientLifecycleEvent.CLIENT_SETUP.invoker(priority).stateChanged(Minecraft.getInstance()); + } + + public static void event(RegisterShadersEvent event, EventPriority priority) { + ClientReloadShadersEvent.EVENT.invoker(priority).reload(event.getResourceProvider(), event::registerShader); + } + + private static void registerWithPriority(IEventBus bus, EventPriority priority, Class type, BiConsumer callback) { + net.minecraftforge.eventbus.api.EventPriority forgePriority = net.minecraftforge.eventbus.api.EventPriority.valueOf(priority.name()); + bus.addListener(forgePriority, false, type, event -> callback.accept(event, priority)); } } } diff --git a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java index 617a0bcb..987bf115 100644 --- a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java +++ b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java @@ -20,6 +20,7 @@ package dev.architectury.event.forge; import dev.architectury.event.CompoundEventResult; +import dev.architectury.event.EventPriority; import dev.architectury.event.EventResult; import dev.architectury.event.events.common.PlayerEvent; import dev.architectury.event.events.common.*; @@ -31,6 +32,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.storage.loot.LootDataManager; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.CommandEvent; import net.minecraftforge.event.LootTableLoadEvent; import net.minecraftforge.event.RegisterCommandsEvent; @@ -56,95 +58,134 @@ import net.minecraftforge.event.level.ExplosionEvent.Start; import net.minecraftforge.event.level.LevelEvent; import net.minecraftforge.event.server.*; import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.server.ServerLifecycleHooks; import java.lang.ref.WeakReference; +import java.util.function.BiConsumer; public class EventHandlerImplCommon { public static WeakReference lootDataManagerRef = null; - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ServerTickEvent event) { - if (event.phase == Phase.START) - TickEvent.SERVER_PRE.invoker().tick(ServerLifecycleHooks.getCurrentServer()); - else if (event.phase == Phase.END) - TickEvent.SERVER_POST.invoker().tick(ServerLifecycleHooks.getCurrentServer()); + public static void init() { + for (EventPriority priority : EventPriority.VALUES) { + registerWithPriority(priority, ServerTickEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, LevelTickEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ServerStartingEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ServerStartedEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ServerStoppingEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ServerStoppedEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, RegisterCommandsEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, PlayerLoggedInEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, PlayerLoggedOutEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, PlayerRespawnEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, CommandEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, PlayerTickEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, LevelEvent.Load.class, EventHandlerImplCommon::eventWorldEvent); + registerWithPriority(priority, LevelEvent.Unload.class, EventHandlerImplCommon::eventWorldEvent); + registerWithPriority(priority, LevelEvent.Save.class, EventHandlerImplCommon::eventWorldEvent); + registerWithPriority(priority, LivingDeathEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, AdvancementEvent.AdvancementEarnEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, Clone.class, EventHandlerImplCommon::eventPlayerEvent); + registerWithPriority(priority, Start.class, EventHandlerImplCommon::eventExplosionEvent); + registerWithPriority(priority, Detonate.class, EventHandlerImplCommon::eventExplosionEvent); + registerWithPriority(priority, LivingAttackEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, EntityJoinLevelEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, FarmlandTrampleEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, FillBucketEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, MobSpawnEvent.FinalizeSpawn.class, EventHandlerImplCommon::eventLivingSpawnEvent); + registerWithPriority(priority, AnimalTameEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ItemCraftedEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ItemSmeltedEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, EntityItemPickupEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ItemPickupEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ItemTossEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, PlayerContainerEvent.Open.class, EventHandlerImplCommon::eventPlayerContainerEvent); + registerWithPriority(priority, PlayerContainerEvent.Close.class, EventHandlerImplCommon::eventPlayerContainerEvent); + registerWithPriority(priority, PlayerInteractEvent.RightClickItem.class, EventHandlerImplCommon::eventPlayerInteractEvent); + registerWithPriority(priority, PlayerInteractEvent.RightClickBlock.class, EventHandlerImplCommon::eventPlayerInteractEvent); + registerWithPriority(priority, PlayerInteractEvent.EntityInteract.class, EventHandlerImplCommon::eventPlayerInteractEvent); + registerWithPriority(priority, PlayerInteractEvent.LeftClickBlock.class, EventHandlerImplCommon::eventPlayerInteractEvent); + registerWithPriority(priority, BreakEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, EntityPlaceEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ServerAboutToStartEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, PlayerChangedDimensionEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, ChunkDataEvent.Save.class, EventHandlerImplCommon::eventChunkDataEvent); + registerWithPriority(priority, ChunkDataEvent.Load.class, EventHandlerImplCommon::eventChunkDataEvent); + registerWithPriority(priority, LootTableLoadEvent.class, EventHandlerImplCommon::event); + registerWithPriority(priority, AttackEntityEvent.class, EventHandlerImplCommon::event); + } + registerWithPriority(EventPriority.HIGHEST, ServerChatEvent.class, (serverChatEvent, priority) -> event(serverChatEvent)); + registerWithPriority(EventPriority.LOWEST, ServerChatEvent.class, (serverChatEvent, priority) -> eventAfter(serverChatEvent)); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(LevelTickEvent event) { + public static void event(ServerTickEvent event, EventPriority priority) { + if (event.phase == Phase.START) + TickEvent.SERVER_PRE.invoker(priority).tick(ServerLifecycleHooks.getCurrentServer()); + else if (event.phase == Phase.END) + TickEvent.SERVER_POST.invoker(priority).tick(ServerLifecycleHooks.getCurrentServer()); + } + + public static void event(LevelTickEvent event, EventPriority priority) { if (event.side == LogicalSide.SERVER) { if (event.phase == Phase.START) - TickEvent.SERVER_LEVEL_PRE.invoker().tick((ServerLevel) event.level); + TickEvent.SERVER_LEVEL_PRE.invoker(priority).tick((ServerLevel) event.level); else if (event.phase == Phase.END) - TickEvent.SERVER_LEVEL_POST.invoker().tick((ServerLevel) event.level); + TickEvent.SERVER_LEVEL_POST.invoker(priority).tick((ServerLevel) event.level); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ServerStartingEvent event) { - LifecycleEvent.SERVER_STARTING.invoker().stateChanged(event.getServer()); + public static void event(ServerStartingEvent event, EventPriority priority) { + LifecycleEvent.SERVER_STARTING.invoker(priority).stateChanged(event.getServer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ServerStartedEvent event) { - LifecycleEvent.SERVER_STARTED.invoker().stateChanged(event.getServer()); + public static void event(ServerStartedEvent event, EventPriority priority) { + LifecycleEvent.SERVER_STARTED.invoker(priority).stateChanged(event.getServer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ServerStoppingEvent event) { - LifecycleEvent.SERVER_STOPPING.invoker().stateChanged(event.getServer()); + public static void event(ServerStoppingEvent event, EventPriority priority) { + LifecycleEvent.SERVER_STOPPING.invoker(priority).stateChanged(event.getServer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ServerStoppedEvent event) { - LifecycleEvent.SERVER_STOPPED.invoker().stateChanged(event.getServer()); + public static void event(ServerStoppedEvent event, EventPriority priority) { + LifecycleEvent.SERVER_STOPPED.invoker(priority).stateChanged(event.getServer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(RegisterCommandsEvent event) { - CommandRegistrationEvent.EVENT.invoker().register(event.getDispatcher(), event.getBuildContext(), event.getCommandSelection()); + public static void event(RegisterCommandsEvent event, EventPriority priority) { + CommandRegistrationEvent.EVENT.invoker(priority).register(event.getDispatcher(), event.getBuildContext(), event.getCommandSelection()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(PlayerLoggedInEvent event) { - PlayerEvent.PLAYER_JOIN.invoker().join((ServerPlayer) event.getEntity()); + public static void event(PlayerLoggedInEvent event, EventPriority priority) { + PlayerEvent.PLAYER_JOIN.invoker(priority).join((ServerPlayer) event.getEntity()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(PlayerLoggedOutEvent event) { - PlayerEvent.PLAYER_QUIT.invoker().quit((ServerPlayer) event.getEntity()); + public static void event(PlayerLoggedOutEvent event, EventPriority priority) { + PlayerEvent.PLAYER_QUIT.invoker(priority).quit((ServerPlayer) event.getEntity()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(PlayerRespawnEvent event) { - PlayerEvent.PLAYER_RESPAWN.invoker().respawn((ServerPlayer) event.getEntity(), event.isEndConquered()); + public static void event(PlayerRespawnEvent event, EventPriority priority) { + PlayerEvent.PLAYER_RESPAWN.invoker(priority).respawn((ServerPlayer) event.getEntity(), event.isEndConquered()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(CommandEvent event) { + public static void event(CommandEvent event, EventPriority priority) { CommandPerformEvent performEvent = new CommandPerformEvent(event.getParseResults(), event.getException()); - if (CommandPerformEvent.EVENT.invoker().act(performEvent).isFalse()) { + if (CommandPerformEvent.EVENT.invoker(priority).act(performEvent).isFalse()) { event.setCanceled(true); } event.setParseResults(performEvent.getResults()); event.setException(performEvent.getThrowable()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(PlayerTickEvent event) { + public static void event(PlayerTickEvent event, EventPriority priority) { if (event.phase == Phase.START) { - TickEvent.PLAYER_PRE.invoker().tick(event.player); + TickEvent.PLAYER_PRE.invoker(priority).tick(event.player); } else if (event.phase == Phase.END) { - TickEvent.PLAYER_POST.invoker().tick(event.player); + TickEvent.PLAYER_POST.invoker(priority).tick(event.player); } } - @SubscribeEvent(priority = EventPriority.HIGH) public static void event(ServerChatEvent event) { class ChatComponentImpl implements ChatEvent.ChatComponent { @Override @@ -160,95 +201,82 @@ public class EventHandlerImplCommon { ChatEvent.DECORATE.invoker().decorate(event.getPlayer(), new ChatComponentImpl()); } - @SubscribeEvent(priority = EventPriority.LOWEST) public static void eventAfter(ServerChatEvent event) { EventResult process = ChatEvent.RECEIVED.invoker().received(event.getPlayer(), event.getMessage()); if (process.isFalse()) event.setCanceled(true); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventWorldEvent(LevelEvent.Load event) { + public static void eventWorldEvent(LevelEvent.Load event, EventPriority priority) { if (event.getLevel() instanceof ServerLevel) { ServerLevel world = (ServerLevel) event.getLevel(); - LifecycleEvent.SERVER_LEVEL_LOAD.invoker().act(world); + LifecycleEvent.SERVER_LEVEL_LOAD.invoker(priority).act(world); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventWorldEvent(LevelEvent.Unload event) { + public static void eventWorldEvent(LevelEvent.Unload event, EventPriority priority) { if (event.getLevel() instanceof ServerLevel) { ServerLevel world = (ServerLevel) event.getLevel(); - LifecycleEvent.SERVER_LEVEL_UNLOAD.invoker().act(world); + LifecycleEvent.SERVER_LEVEL_UNLOAD.invoker(priority).act(world); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventWorldEvent(LevelEvent.Save event) { + public static void eventWorldEvent(LevelEvent.Save event, EventPriority priority) { if (event.getLevel() instanceof ServerLevel) { ServerLevel world = (ServerLevel) event.getLevel(); - LifecycleEvent.SERVER_LEVEL_SAVE.invoker().act(world); + LifecycleEvent.SERVER_LEVEL_SAVE.invoker(priority).act(world); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(LivingDeathEvent event) { - if (EntityEvent.LIVING_DEATH.invoker().die(event.getEntity(), event.getSource()).isFalse()) { + public static void event(LivingDeathEvent event, EventPriority priority) { + if (EntityEvent.LIVING_DEATH.invoker(priority).die(event.getEntity(), event.getSource()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(AdvancementEvent.AdvancementEarnEvent event) { + public static void event(AdvancementEvent.AdvancementEarnEvent event, EventPriority priority) { if (event.getEntity() instanceof ServerPlayer) { - PlayerEvent.PLAYER_ADVANCEMENT.invoker().award((ServerPlayer) event.getEntity(), event.getAdvancement()); + PlayerEvent.PLAYER_ADVANCEMENT.invoker(priority).award((ServerPlayer) event.getEntity(), event.getAdvancement()); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerEvent(Clone event) { + public static void eventPlayerEvent(Clone event, EventPriority priority) { if (event.getOriginal() instanceof ServerPlayer && event.getEntity() instanceof ServerPlayer) { - PlayerEvent.PLAYER_CLONE.invoker().clone((ServerPlayer) event.getOriginal(), (ServerPlayer) event.getEntity(), !event.isWasDeath()); + PlayerEvent.PLAYER_CLONE.invoker(priority).clone((ServerPlayer) event.getOriginal(), (ServerPlayer) event.getEntity(), !event.isWasDeath()); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventExplosionEvent(Start event) { - if (ExplosionEvent.PRE.invoker().explode(event.getLevel(), event.getExplosion()).isFalse()) { + public static void eventExplosionEvent(Start event, EventPriority priority) { + if (ExplosionEvent.PRE.invoker(priority).explode(event.getLevel(), event.getExplosion()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventExplosionEvent(Detonate event) { - ExplosionEvent.DETONATE.invoker().explode(event.getLevel(), event.getExplosion(), event.getAffectedEntities()); + public static void eventExplosionEvent(Detonate event, EventPriority priority) { + ExplosionEvent.DETONATE.invoker(priority).explode(event.getLevel(), event.getExplosion(), event.getAffectedEntities()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(LivingAttackEvent event) { - if (EntityEvent.LIVING_HURT.invoker().hurt(event.getEntity(), event.getSource(), event.getAmount()).isFalse()) { + public static void event(LivingAttackEvent event, EventPriority priority) { + if (EntityEvent.LIVING_HURT.invoker(priority).hurt(event.getEntity(), event.getSource(), event.getAmount()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(EntityJoinLevelEvent event) { - if (EntityEvent.ADD.invoker().add(event.getEntity(), event.getLevel()).isFalse()) { + public static void event(EntityJoinLevelEvent event, EventPriority priority) { + if (EntityEvent.ADD.invoker(priority).add(event.getEntity(), event.getLevel()).isFalse()) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(FarmlandTrampleEvent event) { - if (event.getLevel() instanceof Level && InteractionEvent.FARMLAND_TRAMPLE.invoker().trample((Level) event.getLevel(), event.getPos(), event.getState(), event.getFallDistance(), event.getEntity()).value() != null) { + public static void event(FarmlandTrampleEvent event, EventPriority priority) { + if (event.getLevel() instanceof Level && InteractionEvent.FARMLAND_TRAMPLE.invoker(priority).trample((Level) event.getLevel(), event.getPos(), event.getState(), event.getFallDistance(), event.getEntity()).value() != null) { event.setCanceled(true); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(FillBucketEvent event) { + public static void event(FillBucketEvent event, EventPriority priority) { ItemStack oldItem = event.getEmptyBucket(); - CompoundEventResult result = PlayerEvent.FILL_BUCKET.invoker().fill(event.getEntity(), event.getLevel(), oldItem, event.getTarget()); + CompoundEventResult result = PlayerEvent.FILL_BUCKET.invoker(priority).fill(event.getEntity(), event.getLevel(), oldItem, event.getTarget()); if (result.interruptsFurtherEvaluation()) { event.setCanceled(true); event.setFilledBucket(result.object()); @@ -265,9 +293,8 @@ public class EventHandlerImplCommon { // EntityEvent.ENTER_SECTION.invoker().enterChunk(event.getEntity(), event.getNewChunkX(), event.getNewChunkZ(), event.getOldChunkX(), event.getOldChunkZ()); // } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventLivingSpawnEvent(MobSpawnEvent.FinalizeSpawn event) { - EventResult result = EntityEvent.LIVING_CHECK_SPAWN.invoker().canSpawn(event.getEntity(), event.getLevel(), event.getX(), event.getY(), event.getZ(), event.getSpawnType(), event.getSpawner()); + public static void eventLivingSpawnEvent(MobSpawnEvent.FinalizeSpawn event, EventPriority priority) { + EventResult result = EntityEvent.LIVING_CHECK_SPAWN.invoker(priority).canSpawn(event.getEntity(), event.getLevel(), event.getX(), event.getY(), event.getZ(), event.getSpawnType(), event.getSpawner()); if (result.interruptsFurtherEvaluation()) { if (!result.isEmpty()) { event.setSpawnCancelled(result.value()); @@ -275,27 +302,23 @@ public class EventHandlerImplCommon { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(AnimalTameEvent event) { - EventResult result = EntityEvent.ANIMAL_TAME.invoker().tame(event.getAnimal(), event.getTamer()); + public static void event(AnimalTameEvent event, EventPriority priority) { + EventResult result = EntityEvent.ANIMAL_TAME.invoker(priority).tame(event.getAnimal(), event.getTamer()); event.setCanceled(result.isFalse()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ItemCraftedEvent event) { - PlayerEvent.CRAFT_ITEM.invoker().craft(event.getEntity(), event.getCrafting(), event.getInventory()); + public static void event(ItemCraftedEvent event, EventPriority priority) { + PlayerEvent.CRAFT_ITEM.invoker(priority).craft(event.getEntity(), event.getCrafting(), event.getInventory()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ItemSmeltedEvent event) { - PlayerEvent.SMELT_ITEM.invoker().smelt(event.getEntity(), event.getSmelting()); + public static void event(ItemSmeltedEvent event, EventPriority priority) { + PlayerEvent.SMELT_ITEM.invoker(priority).smelt(event.getEntity(), event.getSmelting()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(EntityItemPickupEvent event) { + public static void event(EntityItemPickupEvent event, EventPriority priority) { // note: this event is weird, cancel is equivalent to denying the pickup, // and setting the result to ALLOW will pick it up without adding it to the player's inventory - var result = PlayerEvent.PICKUP_ITEM_PRE.invoker().canPickup(event.getEntity(), event.getItem(), event.getItem().getItem()); + var result = PlayerEvent.PICKUP_ITEM_PRE.invoker(priority).canPickup(event.getEntity(), event.getItem(), event.getItem().getItem()); if (result.isFalse()) { event.setCanceled(true); } else if (result.isTrue()) { @@ -303,38 +326,32 @@ public class EventHandlerImplCommon { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ItemPickupEvent event) { - PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(event.getEntity(), event.getOriginalEntity(), event.getStack()); + public static void event(ItemPickupEvent event, EventPriority priority) { + PlayerEvent.PICKUP_ITEM_POST.invoker(priority).pickup(event.getEntity(), event.getOriginalEntity(), event.getStack()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ItemTossEvent event) { - PlayerEvent.DROP_ITEM.invoker().drop(event.getPlayer(), event.getEntity()); + public static void event(ItemTossEvent event, EventPriority priority) { + PlayerEvent.DROP_ITEM.invoker(priority).drop(event.getPlayer(), event.getEntity()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerContainerEvent(PlayerContainerEvent.Open event) { - PlayerEvent.OPEN_MENU.invoker().open(event.getEntity(), event.getContainer()); + public static void eventPlayerContainerEvent(PlayerContainerEvent.Open event, EventPriority priority) { + PlayerEvent.OPEN_MENU.invoker(priority).open(event.getEntity(), event.getContainer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerContainerEvent(PlayerContainerEvent.Close event) { - PlayerEvent.CLOSE_MENU.invoker().close(event.getEntity(), event.getContainer()); + public static void eventPlayerContainerEvent(PlayerContainerEvent.Close event, EventPriority priority) { + PlayerEvent.CLOSE_MENU.invoker(priority).close(event.getEntity(), event.getContainer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickItem event) { - CompoundEventResult result = InteractionEvent.RIGHT_CLICK_ITEM.invoker().click(event.getEntity(), event.getHand()); + public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickItem event, EventPriority priority) { + CompoundEventResult result = InteractionEvent.RIGHT_CLICK_ITEM.invoker(priority).click(event.getEntity(), event.getHand()); if (result.isPresent()) { event.setCanceled(true); event.setCancellationResult(result.result().asMinecraft()); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickBlock event) { - EventResult result = InteractionEvent.RIGHT_CLICK_BLOCK.invoker().click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); + public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickBlock event, EventPriority priority) { + EventResult result = InteractionEvent.RIGHT_CLICK_BLOCK.invoker(priority).click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); if (result.isPresent()) { event.setCanceled(true); event.setCancellationResult(result.asMinecraft()); @@ -343,18 +360,16 @@ public class EventHandlerImplCommon { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerInteractEvent(PlayerInteractEvent.EntityInteract event) { - EventResult result = InteractionEvent.INTERACT_ENTITY.invoker().interact(event.getEntity(), event.getTarget(), event.getHand()); + public static void eventPlayerInteractEvent(PlayerInteractEvent.EntityInteract event, EventPriority priority) { + EventResult result = InteractionEvent.INTERACT_ENTITY.invoker(priority).interact(event.getEntity(), event.getTarget(), event.getHand()); if (result.isPresent()) { event.setCanceled(true); event.setCancellationResult(result.asMinecraft()); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventPlayerInteractEvent(PlayerInteractEvent.LeftClickBlock event) { - EventResult result = InteractionEvent.LEFT_CLICK_BLOCK.invoker().click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); + public static void eventPlayerInteractEvent(PlayerInteractEvent.LeftClickBlock event, EventPriority priority) { + EventResult result = InteractionEvent.LEFT_CLICK_BLOCK.invoker(priority).click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); if (result.isPresent()) { event.setCanceled(true); event.setCancellationResult(result.asMinecraft()); @@ -363,10 +378,9 @@ public class EventHandlerImplCommon { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(BreakEvent event) { + public static void event(BreakEvent event, EventPriority priority) { if (event.getPlayer() instanceof ServerPlayer && event.getLevel() instanceof Level) { - EventResult result = BlockEvent.BREAK.invoker().breakBlock((Level) event.getLevel(), event.getPos(), event.getState(), (ServerPlayer) event.getPlayer(), new IntValue() { + EventResult result = BlockEvent.BREAK.invoker(priority).breakBlock((Level) event.getLevel(), event.getPos(), event.getState(), (ServerPlayer) event.getPlayer(), new IntValue() { @Override public int getAsInt() { return event.getExpToDrop(); @@ -383,57 +397,55 @@ public class EventHandlerImplCommon { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(EntityPlaceEvent event) { + public static void event(EntityPlaceEvent event, EventPriority priority) { if (event.getLevel() instanceof Level) { - EventResult result = BlockEvent.PLACE.invoker().placeBlock((Level) event.getLevel(), event.getPos(), event.getState(), event.getEntity()); + EventResult result = BlockEvent.PLACE.invoker(priority).placeBlock((Level) event.getLevel(), event.getPos(), event.getState(), event.getEntity()); if (result.isFalse()) { event.setCanceled(true); } } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(ServerAboutToStartEvent event) { - LifecycleEvent.SERVER_BEFORE_START.invoker().stateChanged(event.getServer()); + public static void event(ServerAboutToStartEvent event, EventPriority priority) { + LifecycleEvent.SERVER_BEFORE_START.invoker(priority).stateChanged(event.getServer()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(PlayerChangedDimensionEvent event) { + public static void event(PlayerChangedDimensionEvent event, EventPriority priority) { if (event.getEntity() instanceof ServerPlayer) { - PlayerEvent.CHANGE_DIMENSION.invoker().change((ServerPlayer) event.getEntity(), event.getFrom(), event.getTo()); + PlayerEvent.CHANGE_DIMENSION.invoker(priority).change((ServerPlayer) event.getEntity(), event.getFrom(), event.getTo()); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventChunkDataEvent(ChunkDataEvent.Save event) { + public static void eventChunkDataEvent(ChunkDataEvent.Save event, EventPriority priority) { if (event.getLevel() instanceof ServerLevel) { - ChunkEvent.SAVE_DATA.invoker().save(event.getChunk(), (ServerLevel) event.getLevel(), event.getData()); + ChunkEvent.SAVE_DATA.invoker(priority).save(event.getChunk(), (ServerLevel) event.getLevel(), event.getData()); } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventChunkDataEvent(ChunkDataEvent.Load event) { + public static void eventChunkDataEvent(ChunkDataEvent.Load event, EventPriority priority) { LevelAccessor level = event.getChunk().getWorldForge(); if (!(level instanceof ServerLevel) && event instanceof LevelEventAttachment) { level = ((LevelEventAttachment) event).architectury$getAttachedLevel(); } - ChunkEvent.LOAD_DATA.invoker().load(event.getChunk(), level instanceof ServerLevel ? (ServerLevel) level : null, event.getData()); + ChunkEvent.LOAD_DATA.invoker(priority).load(event.getChunk(), level instanceof ServerLevel ? (ServerLevel) level : null, event.getData()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(LootTableLoadEvent event) { - LootEvent.MODIFY_LOOT_TABLE.invoker().modifyLootTable(lootDataManagerRef == null ? null : lootDataManagerRef.get(), event.getName(), new LootTableModificationContextImpl(event.getTable()), true); + public static void event(LootTableLoadEvent event, EventPriority priority) { + LootEvent.MODIFY_LOOT_TABLE.invoker(priority).modifyLootTable(lootDataManagerRef == null ? null : lootDataManagerRef.get(), event.getName(), new LootTableModificationContextImpl(event.getTable()), true); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(AttackEntityEvent event) { - EventResult result = PlayerEvent.ATTACK_ENTITY.invoker().attack(event.getEntity(), event.getEntity().level(), event.getTarget(), event.getEntity().getUsedItemHand(), null); + public static void event(AttackEntityEvent event, EventPriority priority) { + EventResult result = PlayerEvent.ATTACK_ENTITY.invoker(priority).attack(event.getEntity(), event.getEntity().level(), event.getTarget(), event.getEntity().getUsedItemHand(), null); if (result.isFalse()) { event.setCanceled(true); } } + private static void registerWithPriority(EventPriority priority, Class type, BiConsumer callback) { + net.minecraftforge.eventbus.api.EventPriority forgePriority = net.minecraftforge.eventbus.api.EventPriority.valueOf(priority.name()); + MinecraftForge.EVENT_BUS.addListener(forgePriority, false, type, event -> callback.accept(event, priority)); + } + public interface LevelEventAttachment { LevelAccessor architectury$getAttachedLevel(); @@ -441,9 +453,19 @@ public class EventHandlerImplCommon { } public static class ModBasedEventHandler { - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(FMLCommonSetupEvent event) { - LifecycleEvent.SETUP.invoker().run(); + public static void init(IEventBus bus) { + for (EventPriority priority : EventPriority.VALUES) { + registerWithPriority(bus, priority, FMLCommonSetupEvent.class, ModBasedEventHandler::event); + } + } + + public static void event(FMLCommonSetupEvent event, EventPriority priority) { + LifecycleEvent.SETUP.invoker(priority).run(); + } + + private static void registerWithPriority(IEventBus bus, EventPriority priority, Class type, BiConsumer callback) { + net.minecraftforge.eventbus.api.EventPriority forgePriority = net.minecraftforge.eventbus.api.EventPriority.valueOf(priority.name()); + bus.addListener(forgePriority, false, type, event -> callback.accept(event, priority)); } } } diff --git a/testmod-common/src/main/java/dev/architectury/test/TestMod.java b/testmod-common/src/main/java/dev/architectury/test/TestMod.java index 009bcf22..8e2eb893 100644 --- a/testmod-common/src/main/java/dev/architectury/test/TestMod.java +++ b/testmod-common/src/main/java/dev/architectury/test/TestMod.java @@ -26,6 +26,7 @@ import dev.architectury.test.debug.MessageSink; import dev.architectury.test.debug.client.ClientOverlayMessageSink; import dev.architectury.test.entity.TestEntity; import dev.architectury.test.events.DebugEvents; +import dev.architectury.test.events.TestEvents; import dev.architectury.test.gamerule.TestGameRules; import dev.architectury.test.item.TestBlockInteractions; import dev.architectury.test.loot.TestLoot; @@ -49,6 +50,7 @@ public class TestMod { public static final String MOD_ID = "architectury_test"; public static void initialize() { + TestEvents.test(); DebugEvents.initialize(); TestRegistries.initialize(); TestGameRules.init(); diff --git a/testmod-common/src/main/java/dev/architectury/test/events/TestEvents.java b/testmod-common/src/main/java/dev/architectury/test/events/TestEvents.java new file mode 100644 index 00000000..4a421a38 --- /dev/null +++ b/testmod-common/src/main/java/dev/architectury/test/events/TestEvents.java @@ -0,0 +1,94 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.test.events; + +import com.google.common.base.Preconditions; +import dev.architectury.event.Event; +import dev.architectury.event.EventFactory; +import dev.architectury.event.EventPriority; +import dev.architectury.event.EventResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +public class TestEvents { + public static void test() { + testPriority(); + testOrder(); + } + + public static void testPriority() { + Event> event = EventFactory.createEventResult(); + event.register(EventPriority.HIGH, () -> { + throw new RuntimeException("This should not be ran!"); + }); + event.register(EventPriority.HIGHEST, () -> EventResult.interruptDefault()); + Preconditions.checkArgument(event.invoker().get() == EventResult.interruptDefault()); + } + + public static void testOrder() { + Event event = EventFactory.createLoop(); + Runnable runnable; + List list = new ArrayList<>(); + event.register(EventPriority.HIGH, () -> list.add(2)); + event.register(() -> list.add(4)); + event.register(EventPriority.LOW, () -> list.add(6)); + event.register(EventPriority.HIGH, () -> list.add(3)); + event.register(EventPriority.LOWEST, runnable = () -> list.add(8)); + event.register(EventPriority.HIGHEST, () -> list.add(0)); + event.register(() -> list.add(5)); + event.register(EventPriority.LOW, () -> list.add(7)); + event.register(EventPriority.LOWEST, () -> list.add(9)); + event.register(EventPriority.HIGHEST, () -> list.add(1)); + + // Test if the order is correct, when we invoke all priorities at once + event.invoker().run(); + Preconditions.checkArgument(list.equals(list.stream().sorted().toList())); + Preconditions.checkArgument(list.size() == 10); + + list.clear(); + // Test if the order is correct, when we invoke each priority individually + for (EventPriority value : EventPriority.VALUES) { + event.invoker(value).run(); + } + Preconditions.checkArgument(list.equals(list.stream().sorted().toList())); + Preconditions.checkArgument(list.size() == 10); + + // Test if unregistering works + Preconditions.checkArgument(event.isRegistered(runnable)); + event.unregister(runnable); + Preconditions.checkArgument(!event.isRegistered(runnable)); + + // Now test if the order is correct, when we invoke all priorities at once + list.clear(); + event.invoker().run(); + Preconditions.checkArgument(list.equals(list.stream().sorted().toList())); + Preconditions.checkArgument(list.size() == 9); + + // Test if the order is correct, when we invoke each priority individually + list.clear(); + for (EventPriority value : EventPriority.VALUES) { + event.invoker(value).run(); + } + Preconditions.checkArgument(list.equals(list.stream().sorted().toList())); + Preconditions.checkArgument(list.size() == 9); + } +}