From 0e25e4e960f2d43ca1bff1196cc51b8b7c521d0d Mon Sep 17 00:00:00 2001 From: GrizzlT <13691001+GrizzlT@users.noreply.github.com> Date: Sat, 14 Aug 2021 13:26:23 +0200 Subject: [PATCH] Revision of the Event system - new direct Event system inspired by FabricMC - all current events adapted to the new system - removed EventManager, Listener, Cancellable and EventHandler in favor of the new thing - Changed the event invocations in ClientSession and Player --- .gitignore | 1 + src/main/java/com/loohp/limbo/Limbo.java | 12 +- .../com/loohp/limbo/events/Cancellable.java | 9 -- .../java/com/loohp/limbo/events/Event.java | 5 - .../com/loohp/limbo/events/EventHandler.java | 14 -- .../com/loohp/limbo/events/EventPriority.java | 37 ----- .../com/loohp/limbo/events/EventsManager.java | 58 -------- .../java/com/loohp/limbo/events/Listener.java | 5 - .../com/loohp/limbo/events/api/Event.java | 56 ++++++++ .../loohp/limbo/events/api/EventFactory.java | 107 +++++++++++++++ .../loohp/limbo/events/api/EventPriority.java | 10 ++ .../limbo/events/impl/ArrayBackedEvent.java | 85 ++++++++++++ .../limbo/events/impl/EventFactoryImpl.java | 43 ++++++ .../limbo/events/player/PlayerChatEvent.java | 52 ++++--- .../limbo/events/player/PlayerEvent.java | 5 +- .../limbo/events/player/PlayerJoinEvent.java | 28 ++-- .../limbo/events/player/PlayerLoginEvent.java | 56 +++++--- .../limbo/events/player/PlayerMoveEvent.java | 69 +++++----- .../limbo/events/player/PlayerQuitEvent.java | 17 ++- .../player/PlayerSelectedSlotChangeEvent.java | 48 +++++-- .../events/player/PlayerTeleportEvent.java | 33 +++++ .../limbo/events/status/StatusPingEvent.java | 32 ++++- .../java/com/loohp/limbo/player/Player.java | 31 ++--- .../loohp/limbo/server/ClientConnection.java | 127 ++++++------------ 24 files changed, 595 insertions(+), 345 deletions(-) delete mode 100644 src/main/java/com/loohp/limbo/events/Cancellable.java delete mode 100644 src/main/java/com/loohp/limbo/events/Event.java delete mode 100644 src/main/java/com/loohp/limbo/events/EventHandler.java delete mode 100644 src/main/java/com/loohp/limbo/events/EventPriority.java delete mode 100644 src/main/java/com/loohp/limbo/events/EventsManager.java delete mode 100644 src/main/java/com/loohp/limbo/events/Listener.java create mode 100644 src/main/java/com/loohp/limbo/events/api/Event.java create mode 100644 src/main/java/com/loohp/limbo/events/api/EventFactory.java create mode 100644 src/main/java/com/loohp/limbo/events/api/EventPriority.java create mode 100644 src/main/java/com/loohp/limbo/events/impl/ArrayBackedEvent.java create mode 100644 src/main/java/com/loohp/limbo/events/impl/EventFactoryImpl.java diff --git a/.gitignore b/.gitignore index d7459c2..cc90103 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea/ +target/ *.iml diff --git a/src/main/java/com/loohp/limbo/Limbo.java b/src/main/java/com/loohp/limbo/Limbo.java index c58ce88..2892744 100644 --- a/src/main/java/com/loohp/limbo/Limbo.java +++ b/src/main/java/com/loohp/limbo/Limbo.java @@ -39,7 +39,6 @@ import org.json.simple.parser.ParseException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.loohp.limbo.events.EventsManager; import com.loohp.limbo.server.ServerConnection; import com.loohp.limbo.server.packets.Packet; import com.loohp.limbo.server.packets.PacketIn; @@ -124,7 +123,6 @@ public class Limbo { private ServerProperties properties; private PluginManager pluginManager; - private EventsManager eventsManager; private PermissionsManager permissionManager; private File pluginFolder; @@ -287,9 +285,7 @@ public class Limbo { tick = new Tick(this); permissionManager = new PermissionsManager(); - permissionManager.loadDefaultPermissionFile(permissionFile); - - eventsManager = new EventsManager(); + permissionManager.loadDefaultPermissionFile(permissionFile); pluginFolder = new File("plugins"); pluginFolder.mkdirs(); @@ -352,10 +348,6 @@ public class Limbo { public File getInternalDataFolder() { return internalDataFolder; } - - public EventsManager getEventsManager() { - return eventsManager; - } public File getPluginFolder() { return pluginFolder; @@ -496,7 +488,7 @@ public class Limbo { } public String buildLegacyPingResponse(String version, BaseComponent[] motd, int maxPlayers, int playersOnline) { - String begin = "§1"; + String begin = "�1"; return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> each.toLegacyText()).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers)); } diff --git a/src/main/java/com/loohp/limbo/events/Cancellable.java b/src/main/java/com/loohp/limbo/events/Cancellable.java deleted file mode 100644 index 7f0c192..0000000 --- a/src/main/java/com/loohp/limbo/events/Cancellable.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.loohp.limbo.events; - -public interface Cancellable { - - public void setCancelled(boolean cancelled); - - public boolean isCancelled(); - -} diff --git a/src/main/java/com/loohp/limbo/events/Event.java b/src/main/java/com/loohp/limbo/events/Event.java deleted file mode 100644 index ca563c5..0000000 --- a/src/main/java/com/loohp/limbo/events/Event.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.loohp.limbo.events; - -public abstract class Event { - -} diff --git a/src/main/java/com/loohp/limbo/events/EventHandler.java b/src/main/java/com/loohp/limbo/events/EventHandler.java deleted file mode 100644 index 126f257..0000000 --- a/src/main/java/com/loohp/limbo/events/EventHandler.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.loohp.limbo.events; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Documented -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface EventHandler { - EventPriority priority() default EventPriority.NORMAL; -} \ No newline at end of file diff --git a/src/main/java/com/loohp/limbo/events/EventPriority.java b/src/main/java/com/loohp/limbo/events/EventPriority.java deleted file mode 100644 index 89fc3f6..0000000 --- a/src/main/java/com/loohp/limbo/events/EventPriority.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.loohp.limbo.events; - -public enum EventPriority { - LOWEST(0), - LOW(1), - NORMAL(2), - HIGH(3), - HIGHEST(4), - MONITOR(5); - - int order; - - EventPriority(int order) { - this.order = order; - } - - public int getOrder() { - return order; - } - - public static EventPriority getByOrder(int order) { - for (EventPriority each : EventPriority.values()) { - if (each.getOrder() == order) { - return each; - } - } - return null; - } - - public static EventPriority[] getPrioritiesInOrder() { - EventPriority[] array = new EventPriority[EventPriority.values().length]; - for (int i = 0; i < array.length; i++) { - array[i] = EventPriority.getByOrder(i); - } - return array; - } -} \ No newline at end of file diff --git a/src/main/java/com/loohp/limbo/events/EventsManager.java b/src/main/java/com/loohp/limbo/events/EventsManager.java deleted file mode 100644 index 1db524f..0000000 --- a/src/main/java/com/loohp/limbo/events/EventsManager.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.loohp.limbo.events; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import com.loohp.limbo.plugins.LimboPlugin; - -public class EventsManager { - - private List listeners; - - public EventsManager() { - listeners = new ArrayList<>(); - } - - public T callEvent(T event) { - for (EventPriority priority : EventPriority.getPrioritiesInOrder()) { - for (ListenerPair entry : listeners) { - Listener listener = entry.listener; - for (Method method : listener.getClass().getMethods()) { - if (method.isAnnotationPresent(EventHandler.class)) { - if (method.getAnnotation(EventHandler.class).priority().equals(priority)) { - if (method.getParameterCount() == 1 && method.getParameterTypes()[0].equals(event.getClass())) { - try { - method.invoke(listener, event); - } catch (Exception e) { - System.err.println("Error while passing " + event.getClass().getCanonicalName() + " to the plugin \"" + entry.plugin.getName() + "\""); - e.printStackTrace(); - } - } - } - } - } - } - } - return event; - } - - public void registerEvents(LimboPlugin plugin, Listener listener) { - listeners.add(new ListenerPair(plugin, listener)); - } - - public void unregisterAllListeners(LimboPlugin plugin) { - listeners.removeIf(each -> each.plugin.equals(plugin)); - } - - protected static class ListenerPair { - public LimboPlugin plugin; - public Listener listener; - - public ListenerPair(LimboPlugin plugin, Listener listener) { - this.plugin = plugin; - this.listener = listener; - } - } - -} diff --git a/src/main/java/com/loohp/limbo/events/Listener.java b/src/main/java/com/loohp/limbo/events/Listener.java deleted file mode 100644 index cbd3591..0000000 --- a/src/main/java/com/loohp/limbo/events/Listener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.loohp.limbo.events; - -public interface Listener { - -} diff --git a/src/main/java/com/loohp/limbo/events/api/Event.java b/src/main/java/com/loohp/limbo/events/api/Event.java new file mode 100644 index 0000000..e298e6d --- /dev/null +++ b/src/main/java/com/loohp/limbo/events/api/Event.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.loohp.limbo.events.api; + +/** + * Base class for Event implementations. + * + * @param The listener type. + * @see EventFactory + */ +public abstract class Event { + /** + * The invoker field. This should be updated by the implementation to + * always refer to an instance containing all code that should be + * executed upon event emission. + */ + protected volatile T invoker; + + /** + * Returns the invoker instance. + * + *

An "invoker" is an object which hides multiple registered + * listeners of type T under one instance of type T, executing + * them and leaving early as necessary. + * + * @return The invoker instance. + */ + public final T invoker() { + return invoker; + } + + /** + * Register a listener to the event. + * + * @param listener The desired listener. + */ + public abstract void register(EventPriority eventPriority, T listener); + + public void register(T listener) { + this.register(EventPriority.NORMAL, listener); + } +} \ No newline at end of file diff --git a/src/main/java/com/loohp/limbo/events/api/EventFactory.java b/src/main/java/com/loohp/limbo/events/api/EventFactory.java new file mode 100644 index 0000000..46c205b --- /dev/null +++ b/src/main/java/com/loohp/limbo/events/api/EventFactory.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.loohp.limbo.events.api; + +import com.loohp.limbo.events.impl.EventFactoryImpl; + +import java.util.function.Function; + +/** + * Helper for creating {@link Event} classes. + */ +public final class EventFactory { + + private static boolean profilingEnabled = true; + + private EventFactory() { } + + /** + * @return True if events are supposed to be profiled. + */ + public static boolean isProfilingEnabled() { + return profilingEnabled; + } + + /** + * Invalidate and re-create all existing "invoker" instances across + * events created by this EventFactory. Use this if, for instance, + * the profilingEnabled field changes. + */ + // TODO: Turn this into an event? + public static void invalidate() { + EventFactoryImpl.invalidate(); + } + + /** + * Create an "array-backed" Event instance. + * + *

If your factory simply delegates to the listeners without adding custom behavior, + * consider using {@linkplain #createArrayBacked(Class, Object, Function) the other overload} + * if performance of this event is critical. + * + * @param type The listener class type. + * @param invokerFactory The invoker factory, combining multiple listeners into one instance. + * @param The listener type. + * @return The Event instance. + */ + public static Event createArrayBacked(Class type, Function invokerFactory) { + return EventFactoryImpl.createArrayBacked(type, invokerFactory); + } + + /** + * Create an "array-backed" Event instance with a custom empty invoker, + * for an event whose {@code invokerFactory} only delegates to the listeners. + *

    + *
  • If there is no listener, the custom empty invoker will be used.
  • + *
  • If there is only one listener, that one will be used as the invoker + * and the factory will not be called.
  • + *
  • Only when there are at least two listeners will the factory be used.
  • + *
+ * + *

Having a custom empty invoker (of type (...) -> {}) increases performance + * relative to iterating over an empty array; however, it only really matters + * if the event is executed thousands of times a second. + * + * @param type The listener class type. + * @param emptyInvoker The custom empty invoker. + * @param invokerFactory The invoker factory, combining multiple listeners into one instance. + * @param The listener type. + * @return The Event instance. + */ + public static Event createArrayBacked(Class type, T emptyInvoker, Function invokerFactory) { + return createArrayBacked(type, listeners -> { + if (listeners.length == 0) { + return emptyInvoker; + } else if (listeners.length == 1) { + return listeners[0]; + } else { + return invokerFactory.apply(listeners); + } + }); + } + + /** + * Get the listener object name. This can be used in debugging/profiling + * scenarios. + * + * @param handler The listener object. + * @return The listener name. + */ + public static String getHandlerName(Object handler) { + return handler.getClass().getName(); + } +} \ No newline at end of file diff --git a/src/main/java/com/loohp/limbo/events/api/EventPriority.java b/src/main/java/com/loohp/limbo/events/api/EventPriority.java new file mode 100644 index 0000000..eff6dc8 --- /dev/null +++ b/src/main/java/com/loohp/limbo/events/api/EventPriority.java @@ -0,0 +1,10 @@ +package com.loohp.limbo.events.api; + +public enum EventPriority { + LOWEST, + LOW, + NORMAL, + HIGH, + HIGHEST, + MONITOR +} \ No newline at end of file diff --git a/src/main/java/com/loohp/limbo/events/impl/ArrayBackedEvent.java b/src/main/java/com/loohp/limbo/events/impl/ArrayBackedEvent.java new file mode 100644 index 0000000..ae533b5 --- /dev/null +++ b/src/main/java/com/loohp/limbo/events/impl/ArrayBackedEvent.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.loohp.limbo.events.impl; + +import com.loohp.limbo.events.api.EventPriority; +import com.loohp.limbo.events.api.Event; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Objects; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Function; + +class ArrayBackedEvent extends Event +{ + private final Function invokerFactory; + private final Lock lock = new ReentrantLock(); + private T[] handlers; + + private final Class invokerType; + private InvokerWrapper[] handlersWrapped; + + @SuppressWarnings("unchecked") + ArrayBackedEvent(Class type, Function invokerFactory) { + this.invokerType = type; + this.invokerFactory = invokerFactory; + this.handlers = (T[]) Array.newInstance(type, 0); + this.handlersWrapped = new InvokerWrapper[0]; + update(); + } + + void update() { + this.invoker = invokerFactory.apply(handlers); + } + + @SuppressWarnings("unchecked") + @Override + public void register(EventPriority eventPriority, T listener) { + Objects.requireNonNull(listener, "Tried to register a null listener!"); + + lock.lock(); + + try { + handlersWrapped = Arrays.copyOf(handlersWrapped, handlersWrapped.length + 1); + handlersWrapped[handlersWrapped.length - 1] = new InvokerWrapper<>(eventPriority, listener); + Arrays.sort(handlersWrapped, Comparator.comparing(wrapper -> wrapper.priority)); + + handlers = Arrays.stream(handlersWrapped).map(InvokerWrapper::getInvoker).toArray(size -> (T[]) Array.newInstance(this.invokerType, size)); + update(); + } finally { + lock.unlock(); + } + } + + static class InvokerWrapper { + + public EventPriority priority; + public T invoker; + + public InvokerWrapper(EventPriority priority, T invoker) { + this.priority = priority; + this.invoker = invoker; + } + + public T getInvoker() { + return this.invoker; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/loohp/limbo/events/impl/EventFactoryImpl.java b/src/main/java/com/loohp/limbo/events/impl/EventFactoryImpl.java new file mode 100644 index 0000000..01da482 --- /dev/null +++ b/src/main/java/com/loohp/limbo/events/impl/EventFactoryImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.loohp.limbo.events.impl; + +import com.loohp.limbo.events.api.Event; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + + +// As required by the Apache License, Version 2.0 we are required to +// mention that we decided to delete the second method in this class. +// It was considered unnecessary code by us and thus remove, (this also influences the imports) +public final class EventFactoryImpl { + private static final List> ARRAY_BACKED_EVENTS = new ArrayList<>(); + + private EventFactoryImpl() { } + + public static void invalidate() { + ARRAY_BACKED_EVENTS.forEach(ArrayBackedEvent::update); + } + + public static Event createArrayBacked(Class type, Function invokerFactory) { + ArrayBackedEvent event = new ArrayBackedEvent<>(type, invokerFactory); + ARRAY_BACKED_EVENTS.add(event); + return event; + } +} \ No newline at end of file diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerChatEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerChatEvent.java index bb71487..9523157 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerChatEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerChatEvent.java @@ -1,19 +1,51 @@ package com.loohp.limbo.events.player; -import com.loohp.limbo.events.Cancellable; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; import com.loohp.limbo.player.Player; -public class PlayerChatEvent extends PlayerEvent implements Cancellable { +public class PlayerChatEvent extends PlayerEvent { + + /** + * This callback will be invoked every time the server receives a chat message + * + * Cancelling this event will prevent the chat message from being sent to all connected clients + */ + public static final Event PLAYER_CHAT_EVENT = EventFactory.createArrayBacked(PlayerChatEventCallback.class, (_1, cancel) -> cancel, callbacks -> (event, _isCancelled) -> { + boolean isCancelled = _isCancelled; + for (PlayerChatEventCallback callback : callbacks) { + isCancelled = callback.onPlayerChat(event, isCancelled); + } + return isCancelled; + }); + + public interface PlayerChatEventCallback { + /** + * Callback for the {@link PlayerChatEvent} + * This will initiate the event as non-cancelled + * @param event the chat event + * @return true to cancel the event, otherwise return false + */ + default boolean onPlayerChat(PlayerChatEvent event) { + return this.onPlayerChat(event, false); + } + + /** + * Callback for the {@link PlayerChatEvent} + * @param event the chat event + * @param isCancelled whether the event was cancelled before reaching this callback + * @return true to cancel the event, otherwise return false + */ + boolean onPlayerChat(PlayerChatEvent event, boolean isCancelled); + } private String format; private String message; - private boolean cancelled; - public PlayerChatEvent(Player player, String format, String message, boolean cancelled) { + public PlayerChatEvent(Player player, String format, String message) { super(player); this.format = format; this.message = message; - this.cancelled = cancelled; } public String getFormat() { @@ -32,14 +64,4 @@ public class PlayerChatEvent extends PlayerEvent implements Cancellable { this.message = message; } - @Override - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - } diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerEvent.java index 47b2eb6..f48f84a 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerEvent.java @@ -1,11 +1,10 @@ package com.loohp.limbo.events.player; -import com.loohp.limbo.events.Event; import com.loohp.limbo.player.Player; -public class PlayerEvent extends Event { +public class PlayerEvent { - private Player player; + private final Player player; public PlayerEvent(Player player) { this.player = player; diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerJoinEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerJoinEvent.java index 0178f32..f9709b5 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerJoinEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerJoinEvent.java @@ -1,22 +1,24 @@ package com.loohp.limbo.events.player; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; import com.loohp.limbo.location.Location; import com.loohp.limbo.player.Player; -public class PlayerJoinEvent extends PlayerEvent { +public interface PlayerJoinEvent { - private Location spawnLocation; - - public PlayerJoinEvent(Player player, Location spawnLoc) { - super(player); - spawnLocation = spawnLoc; - } - - public Location getSpawnLocation() { + /** + * Called whenever a player joins the server + * + * This event can be used to change the spawn location of the player + */ + Event PLAYER_JOIN_EVENT = EventFactory.createArrayBacked(PlayerJoinEvent.class, (_1, location) -> location, callbacks -> (player, _spawnLocation) -> { + Location spawnLocation = _spawnLocation; + for (PlayerJoinEvent callback : callbacks) { + spawnLocation = callback.onPlayerJoin(player, spawnLocation); + } return spawnLocation; - } + }); - public void setSpawnLocation(Location spawnLocation) { - this.spawnLocation = spawnLocation; - } + Location onPlayerJoin(Player player, Location spawnLocation); } diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerLoginEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerLoginEvent.java index e4845ce..3639b0b 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerLoginEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerLoginEvent.java @@ -1,20 +1,50 @@ package com.loohp.limbo.events.player; -import com.loohp.limbo.events.Cancellable; -import com.loohp.limbo.events.Event; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; import com.loohp.limbo.server.ClientConnection; - import net.md_5.bungee.api.chat.BaseComponent; -public class PlayerLoginEvent extends Event implements Cancellable { +public class PlayerLoginEvent { + + /** + * Called when a player logs into the server (protocol-wise right before the Login Success Packet would be sent) + * + * Cancelling this event will prevent the player from joining the server + */ + public static Event PLAYER_LOGIN_EVENT = EventFactory.createArrayBacked(PlayerLoginEventCallback.class, (_1, cancel) -> cancel, callbacks -> (event, _isCancelled) -> { + boolean isCancelled = _isCancelled; + for (PlayerLoginEventCallback callback : callbacks) { + isCancelled = callback.onPlayerLoginEvent(event, isCancelled); + } + return isCancelled; + }); + + public interface PlayerLoginEventCallback { + /** + * Callback for the {@link PlayerLoginEvent} + * This will initiate the event as non-cancelled + * @param event the chat event + * @return true to cancel the event, otherwise return false + */ + default boolean onPlayerLoginEvent(PlayerLoginEvent event) { + return this.onPlayerLoginEvent(event, false); + } + + /** + * Callback for the {@link PlayerLoginEvent} + * @param event the login event + * @param isCancelled whether the event was cancelled before reaching this callback + * @return true to cancel the event, otherwise return false + */ + boolean onPlayerLoginEvent(PlayerLoginEvent event, boolean isCancelled); + } - private ClientConnection connection; - private boolean cancelled; + private final ClientConnection connection; private BaseComponent[] cancelReason; - public PlayerLoginEvent(ClientConnection connection, boolean cancelled, BaseComponent... cancelReason) { + public PlayerLoginEvent(ClientConnection connection, BaseComponent... cancelReason) { this.connection = connection; - this.cancelled = cancelled; this.cancelReason = cancelReason; } @@ -30,14 +60,4 @@ public class PlayerLoginEvent extends Event implements Cancellable { this.cancelReason = cancelReason; } - @Override - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - } diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerMoveEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerMoveEvent.java index ec2a8aa..ad25ae8 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerMoveEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerMoveEvent.java @@ -1,15 +1,48 @@ package com.loohp.limbo.events.player; -import com.loohp.limbo.events.Cancellable; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; import com.loohp.limbo.location.Location; import com.loohp.limbo.player.Player; /** * Holds information for player movement events */ -public class PlayerMoveEvent extends PlayerEvent implements Cancellable { +public class PlayerMoveEvent extends PlayerEvent { + + /** + * Called when the player sends a movement packet + * + * Cancelling this event will cause the player to stay in place + */ + public static final Event PLAYER_MOVE_EVENT = EventFactory.createArrayBacked(PlayerMoveEventCallback.class, (_1, cancel) -> cancel, callbacks -> (event, _isCancelled) -> { + boolean isCancelled = _isCancelled; + for (PlayerMoveEventCallback callback : callbacks) { + isCancelled = callback.onPlayerMove(event, isCancelled); + } + return isCancelled; + }); + + public interface PlayerMoveEventCallback { + /** + * Callback for the {@link PlayerMoveEvent} + * This will initiate the event as non-cancelled + * @param event the move event + * @return true to cancel the event, otherwise return false + */ + default boolean onPlayerMove(PlayerMoveEvent event) { + return this.onPlayerMove(event, false); + } + + /** + * Callback for the {@link PlayerMoveEvent} + * @param event the move event + * @param isCancelled whether the event was cancelled before reaching this callback + * @return true to cancel the event, otherwise return false + */ + boolean onPlayerMove(PlayerMoveEvent event, boolean isCancelled); + } - private boolean cancel = false; private Location from; private Location to; @@ -19,36 +52,6 @@ public class PlayerMoveEvent extends PlayerEvent implements Cancellable { this.to = to; } - /** - * Gets the cancellation state of this event. A cancelled event will not - * be executed in the server, but will still pass to other plugins - *

- * If a move or teleport event is cancelled, the player will be moved or - * teleported back to the Location as defined by getFrom(). This will not - * fire an event - * - * @return true if this event is cancelled - */ - @Override - public boolean isCancelled() { - return cancel; - } - - /** - * Sets the cancellation state of this event. A cancelled event will not - * be executed in the server, but will still pass to other plugins - *

- * If a move or teleport event is cancelled, the player will be moved or - * teleported back to the Location as defined by getFrom(). This will not - * fire an event - * - * @param cancel true if you wish to cancel this event - */ - @Override - public void setCancelled(boolean cancel) { - this.cancel = cancel; - } - /** * Gets the location this player moved from * diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerQuitEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerQuitEvent.java index 5966a11..f6fcad5 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerQuitEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerQuitEvent.java @@ -1,11 +1,20 @@ package com.loohp.limbo.events.player; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; import com.loohp.limbo.player.Player; -public class PlayerQuitEvent extends PlayerEvent { +public interface PlayerQuitEvent { + + /** + * Called whenever a player leaves the server + */ + Event PLAYER_QUIT_EVENT = EventFactory.createArrayBacked(PlayerQuitEvent.class, _player -> {}, callbacks -> player -> { + for (PlayerQuitEvent callback : callbacks) { + callback.onPlayerQuit(player); + } + }); - public PlayerQuitEvent(Player player) { - super(player); - } + void onPlayerQuit(Player player); } diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerSelectedSlotChangeEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerSelectedSlotChangeEvent.java index 431fccd..d86e367 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerSelectedSlotChangeEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerSelectedSlotChangeEvent.java @@ -1,11 +1,43 @@ package com.loohp.limbo.events.player; -import com.loohp.limbo.events.Cancellable; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; import com.loohp.limbo.player.Player; -public class PlayerSelectedSlotChangeEvent extends PlayerEvent implements Cancellable { +public class PlayerSelectedSlotChangeEvent extends PlayerEvent { + + /** + * Called when the client sends a Held Item Change Packet + * + * Cancelling this event will force the player to keep the same slot selected + */ + public static final Event PLAYER_SELECTED_SLOT_CHANGE_EVENT = EventFactory.createArrayBacked(PlayerSelectedSlotChangeEventCallback.class, (_1, cancel) -> cancel, callbacks -> (event, _isCancelled) -> { + boolean isCancelled = _isCancelled; + for (PlayerSelectedSlotChangeEventCallback callback : callbacks) { + isCancelled = callback.onPlayerSelectedSlotChange(event, isCancelled); + } + return isCancelled; + }); + + public interface PlayerSelectedSlotChangeEventCallback { + + /** + * Callback for the {@link PlayerSelectedSlotChangeEvent} + * This will initiate the event as non-cancelled + * @return true to cancel the event, otherwise return false + */ + default boolean onPlayerSelectedSlotChange(PlayerSelectedSlotChangeEvent event) { + return this.onPlayerSelectedSlotChange(event, false); + } + + /** + * Callback for the {@link PlayerSelectedSlotChangeEvent} + * @param isCancelled whether the event was cancelled before reaching this callback + * @return true to cancel the event, otherwise return false + */ + boolean onPlayerSelectedSlotChange(PlayerSelectedSlotChangeEvent event, boolean isCancelled); + } - private boolean cancel = false; private byte slot; public PlayerSelectedSlotChangeEvent(Player player, byte slot) { @@ -13,16 +45,6 @@ public class PlayerSelectedSlotChangeEvent extends PlayerEvent implements Cancel this.slot = slot; } - @Override - public void setCancelled(boolean cancelled) { - this.cancel = cancelled; - } - - @Override - public boolean isCancelled() { - return cancel; - } - public byte getSlot() { return slot; } diff --git a/src/main/java/com/loohp/limbo/events/player/PlayerTeleportEvent.java b/src/main/java/com/loohp/limbo/events/player/PlayerTeleportEvent.java index c466310..0d92456 100644 --- a/src/main/java/com/loohp/limbo/events/player/PlayerTeleportEvent.java +++ b/src/main/java/com/loohp/limbo/events/player/PlayerTeleportEvent.java @@ -1,10 +1,43 @@ package com.loohp.limbo.events.player; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; import com.loohp.limbo.location.Location; import com.loohp.limbo.player.Player; public class PlayerTeleportEvent extends PlayerMoveEvent { + /** + * Called when the player is about to teleport + * + * Cancelling this event will prevent the player from being teleported + */ + public static final Event PLAYER_TELEPORT_EVENT = EventFactory.createArrayBacked(PlayerTeleportEventCallback.class, (_1, cancel) -> cancel, callbacks -> (event, _isCancelled) -> { + boolean isCancelled = _isCancelled; + for (PlayerTeleportEventCallback callback : callbacks) { + isCancelled = callback.onPlayerTeleport(event, isCancelled); + } + return isCancelled; + }); + + public interface PlayerTeleportEventCallback { + /** + * Callback for {@link PlayerTeleportEvent} + * This will initiate the event as non-cancelled + * @return true to cancel the event, otherwise return false + */ + default boolean onPlayerTeleport(PlayerTeleportEvent event) { + return this.onPlayerTeleport(event, false); + } + + /** + * Callback for {@link PlayerTeleportEvent} + * @param isCancelled whether the event was cancelled before reaching this callback + * @return true to cancel the event, otherwise return false + */ + boolean onPlayerTeleport(PlayerTeleportEvent event, boolean isCancelled); + } + public PlayerTeleportEvent(Player player, Location from, Location to) { super(player, from, to); } diff --git a/src/main/java/com/loohp/limbo/events/status/StatusPingEvent.java b/src/main/java/com/loohp/limbo/events/status/StatusPingEvent.java index d076322..c200caa 100644 --- a/src/main/java/com/loohp/limbo/events/status/StatusPingEvent.java +++ b/src/main/java/com/loohp/limbo/events/status/StatusPingEvent.java @@ -1,15 +1,35 @@ package com.loohp.limbo.events.status; +import com.loohp.limbo.events.api.Event; +import com.loohp.limbo.events.api.EventFactory; +import com.loohp.limbo.server.ClientConnection; +import net.md_5.bungee.api.chat.BaseComponent; + import java.awt.image.BufferedImage; -import com.loohp.limbo.events.Event; -import com.loohp.limbo.server.ClientConnection; +public class StatusPingEvent { -import net.md_5.bungee.api.chat.BaseComponent; + /** + * Called when the ping request is being constructed + * + * Can be used to alter the status information + */ + public static final Event STATUS_PING_EVENT = EventFactory.createArrayBacked(StatusPingEventCallback.class, event -> {}, callbacks -> statusPingEvent -> { + for (StatusPingEventCallback callback : callbacks) { + callback.onStatusPing(statusPingEvent); + } + }); -public class StatusPingEvent extends Event { + public interface StatusPingEventCallback { - private ClientConnection connection; + /** + * Callback for the {@link StatusPingEvent} + * @return the (modified) event that will be used to construct a response + */ + void onStatusPing(StatusPingEvent statusData); + } + + private final ClientConnection connection; private String version; private int protocol; private BaseComponent[] motd; @@ -26,7 +46,7 @@ public class StatusPingEvent extends Event { this.playersOnline = playersOnline; this.favicon = favicon; } - + public ClientConnection getConnection() { return connection; } diff --git a/src/main/java/com/loohp/limbo/player/Player.java b/src/main/java/com/loohp/limbo/player/Player.java index dc972aa..f152c0b 100644 --- a/src/main/java/com/loohp/limbo/player/Player.java +++ b/src/main/java/com/loohp/limbo/player/Player.java @@ -1,30 +1,25 @@ package com.loohp.limbo.player; -import java.io.IOException; -import java.util.UUID; - import com.loohp.limbo.Limbo; -import com.loohp.limbo.events.player.PlayerChatEvent; -import com.loohp.limbo.events.player.PlayerTeleportEvent; -import com.loohp.limbo.server.ClientConnection; -import com.loohp.limbo.server.packets.PacketPlayOutChat; -import com.loohp.limbo.server.packets.PacketPlayOutGameState; -import com.loohp.limbo.server.packets.PacketPlayOutHeldItemChange; -import com.loohp.limbo.server.packets.PacketPlayOutPositionAndLook; -import com.loohp.limbo.server.packets.PacketPlayOutRespawn; import com.loohp.limbo.commands.CommandSender; import com.loohp.limbo.entity.DataWatcher; -import com.loohp.limbo.entity.EntityType; -import com.loohp.limbo.entity.LivingEntity; import com.loohp.limbo.entity.DataWatcher.WatchableField; import com.loohp.limbo.entity.DataWatcher.WatchableObjectType; +import com.loohp.limbo.entity.EntityType; +import com.loohp.limbo.entity.LivingEntity; +import com.loohp.limbo.events.player.PlayerChatEvent; +import com.loohp.limbo.events.player.PlayerTeleportEvent; import com.loohp.limbo.location.Location; +import com.loohp.limbo.server.ClientConnection; +import com.loohp.limbo.server.packets.*; import com.loohp.limbo.utils.GameMode; - import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; +import java.io.IOException; +import java.util.UUID; + public class Player extends LivingEntity implements CommandSender { public final ClientConnection clientConnection; @@ -173,8 +168,8 @@ public class Player extends LivingEntity implements CommandSender { @Override public void teleport(Location location) { - PlayerTeleportEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerTeleportEvent(this, getLocation(), location)); - if (!event.isCancelled()) { + PlayerTeleportEvent event = new PlayerTeleportEvent(this, getLocation(), location); + if (!PlayerTeleportEvent.PLAYER_TELEPORT_EVENT.invoker().onPlayerTeleport(event)) { location = event.getTo(); super.teleport(location); try { @@ -248,8 +243,8 @@ public class Player extends LivingEntity implements CommandSender { public void chat(String message) { String format = "<%name%> %message%"; - PlayerChatEvent event = (PlayerChatEvent) Limbo.getInstance().getEventsManager().callEvent(new PlayerChatEvent(this, format, message, false)); - if (!event.isCancelled()) { + PlayerChatEvent event = new PlayerChatEvent(this, format, message); + if (!PlayerChatEvent.PLAYER_CHAT_EVENT.invoker().onPlayerChat(event)) { String chat = event.getFormat().replace("%name%", username).replace("%message%", event.getMessage()); Limbo.getInstance().getConsole().sendMessage(chat); for (Player each : Limbo.getInstance().getPlayers()) { diff --git a/src/main/java/com/loohp/limbo/server/ClientConnection.java b/src/main/java/com/loohp/limbo/server/ClientConnection.java index a80c373..6e70cf3 100644 --- a/src/main/java/com/loohp/limbo/server/ClientConnection.java +++ b/src/main/java/com/loohp/limbo/server/ClientConnection.java @@ -1,81 +1,38 @@ package com.loohp.limbo.server; +import com.loohp.limbo.Limbo; +import com.loohp.limbo.events.player.*; +import com.loohp.limbo.events.status.StatusPingEvent; +import com.loohp.limbo.file.ServerProperties; +import com.loohp.limbo.location.Location; +import com.loohp.limbo.player.Player; +import com.loohp.limbo.player.PlayerInteractManager; +import com.loohp.limbo.server.packets.*; +import com.loohp.limbo.server.packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags; +import com.loohp.limbo.server.packets.PacketPlayOutPlayerInfo.PlayerInfoAction; +import com.loohp.limbo.server.packets.PacketPlayOutPlayerInfo.PlayerInfoData; +import com.loohp.limbo.server.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty; +import com.loohp.limbo.server.packets.PacketPlayOutTabComplete.TabCompleteMatches; +import com.loohp.limbo.utils.*; +import com.loohp.limbo.utils.MojangAPIUtils.SkinResponse; +import com.loohp.limbo.world.BlockPosition; +import com.loohp.limbo.world.World; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.chat.ComponentSerializer; + import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; -import com.loohp.limbo.Limbo; -import com.loohp.limbo.events.player.PlayerJoinEvent; -import com.loohp.limbo.events.player.PlayerLoginEvent; -import com.loohp.limbo.events.player.PlayerMoveEvent; -import com.loohp.limbo.events.player.PlayerQuitEvent; -import com.loohp.limbo.events.player.PlayerSelectedSlotChangeEvent; -import com.loohp.limbo.events.status.StatusPingEvent; -import com.loohp.limbo.file.ServerProperties; -import com.loohp.limbo.location.Location; -import com.loohp.limbo.player.Player; -import com.loohp.limbo.player.PlayerInteractManager; -import com.loohp.limbo.server.packets.Packet; -import com.loohp.limbo.server.packets.PacketHandshakingIn; -import com.loohp.limbo.server.packets.PacketLoginInLoginStart; -import com.loohp.limbo.server.packets.PacketLoginOutDisconnect; -import com.loohp.limbo.server.packets.PacketLoginOutLoginSuccess; -import com.loohp.limbo.server.packets.PacketOut; -import com.loohp.limbo.server.packets.PacketPlayInChat; -import com.loohp.limbo.server.packets.PacketPlayInHeldItemChange; -import com.loohp.limbo.server.packets.PacketPlayInKeepAlive; -import com.loohp.limbo.server.packets.PacketPlayInPosition; -import com.loohp.limbo.server.packets.PacketPlayInPositionAndLook; -import com.loohp.limbo.server.packets.PacketPlayInRotation; -import com.loohp.limbo.server.packets.PacketPlayInTabComplete; -import com.loohp.limbo.server.packets.PacketPlayOutDeclareCommands; -import com.loohp.limbo.server.packets.PacketPlayOutDisconnect; -import com.loohp.limbo.server.packets.PacketPlayOutEntityMetadata; -import com.loohp.limbo.server.packets.PacketPlayOutGameState; -import com.loohp.limbo.server.packets.PacketPlayOutHeldItemChange; -import com.loohp.limbo.server.packets.PacketPlayOutLogin; -import com.loohp.limbo.server.packets.PacketPlayOutPlayerAbilities; -import com.loohp.limbo.server.packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags; -import com.loohp.limbo.server.packets.PacketPlayOutPlayerInfo; -import com.loohp.limbo.server.packets.PacketPlayOutPlayerInfo.PlayerInfoAction; -import com.loohp.limbo.server.packets.PacketPlayOutPlayerInfo.PlayerInfoData; -import com.loohp.limbo.server.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty; -import com.loohp.limbo.server.packets.PacketPlayOutPositionAndLook; -import com.loohp.limbo.server.packets.PacketPlayOutSpawnPosition; -import com.loohp.limbo.server.packets.PacketPlayOutTabComplete; -import com.loohp.limbo.server.packets.PacketPlayOutTabComplete.TabCompleteMatches; -import com.loohp.limbo.server.packets.PacketPlayOutUpdateViewPosition; -import com.loohp.limbo.server.packets.PacketStatusInPing; -import com.loohp.limbo.server.packets.PacketStatusInRequest; -import com.loohp.limbo.server.packets.PacketStatusOutPong; -import com.loohp.limbo.server.packets.PacketStatusOutResponse; -import com.loohp.limbo.utils.CustomStringUtils; -import com.loohp.limbo.utils.DataTypeIO; -import com.loohp.limbo.utils.DeclareCommands; -import com.loohp.limbo.utils.GameMode; -import com.loohp.limbo.utils.MojangAPIUtils; -import com.loohp.limbo.utils.MojangAPIUtils.SkinResponse; -import com.loohp.limbo.utils.NamespacedKey; -import com.loohp.limbo.world.BlockPosition; -import com.loohp.limbo.world.World; - -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.chat.ComponentSerializer; - public class ClientConnection extends Thread { public static enum ClientState { @@ -186,7 +143,8 @@ public class ClientConnection extends Thread { String str = inetAddress.getHostName() + ":" + client_socket.getPort(); Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Legacy Status has pinged"); ServerProperties p = Limbo.getInstance().getServerProperties(); - StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), ComponentSerializer.parse(p.getMotdJson()), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null))); + StatusPingEvent event = new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), ComponentSerializer.parse(p.getMotdJson()), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)); + StatusPingEvent.STATUS_PING_EVENT.invoker().onStatusPing(event); String response = Limbo.getInstance().buildLegacyPingResponse(event.getVersion(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline()); byte[] bytes = response.getBytes(StandardCharsets.UTF_16BE); output.writeShort(response.length()); @@ -222,7 +180,8 @@ public class ClientConnection extends Thread { Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Handshake Status has pinged"); } ServerProperties p = Limbo.getInstance().getServerProperties(); - StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), ComponentSerializer.parse(p.getMotdJson()), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null))); + StatusPingEvent event = new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), ComponentSerializer.parse(p.getMotdJson()), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)); + StatusPingEvent.STATUS_PING_EVENT.invoker().onStatusPing(event); PacketStatusOutResponse packet = new PacketStatusOutResponse(Limbo.getInstance().buildServerListResponseJson(event.getVersion(), event.getProtocol(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline(), event.getFavicon())); sendPacket(packet); } else if (packetType.equals(PacketStatusInPing.class)) { @@ -269,7 +228,13 @@ public class ClientConnection extends Thread { PacketLoginInLoginStart start = new PacketLoginInLoginStart(input); String username = start.getUsername(); UUID uuid = isBungeecord ? bungeeUUID : UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8)); - + + PlayerLoginEvent event = new PlayerLoginEvent(this); + if (PlayerLoginEvent.PLAYER_LOGIN_EVENT.invoker().onPlayerLoginEvent(event)) { + disconnectDuringLogin(event.getCancelReason()); + break; + } + PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(uuid, username); sendPacket(success); @@ -285,11 +250,6 @@ public class ClientConnection extends Thread { } } - PlayerLoginEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerLoginEvent(this, false)); - if (event.isCancelled()) { - disconnectDuringLogin(event.getCancelReason()); - } - break; } } catch (Exception e) { @@ -303,9 +263,8 @@ public class ClientConnection extends Thread { ServerProperties properties = Limbo.getInstance().getServerProperties(); Location worldSpawn = properties.getWorldSpawn(); - - PlayerJoinEvent joinEvent = Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player, worldSpawn)); - worldSpawn = joinEvent.getSpawnLocation(); + + worldSpawn = PlayerJoinEvent.PLAYER_JOIN_EVENT.invoker().onPlayerJoin(player, worldSpawn); World world = worldSpawn.getWorld(); PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds().stream().map(each -> new NamespacedKey(each.getName()).toString()).collect(Collectors.toList()).toArray(new String[Limbo.getInstance().getWorlds().size()]), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, properties.isReducedDebugInfo(), true, false, true); @@ -363,7 +322,7 @@ public class ClientConnection extends Thread { //Limbo.getInstance().getConsole().sendMessage(packetId + " -> " + packetType); CheckedConsumer processMoveEvent = event -> { Location originalTo = event.getTo().clone(); - if (event.isCancelled()) { + if (PlayerMoveEvent.PLAYER_MOVE_EVENT.invoker().onPlayerMove(event)) { Location returnTo = event.getFrom(); PacketPlayOutPositionAndLook cancel = new PacketPlayOutPositionAndLook(returnTo.getX(), returnTo.getY(), returnTo.getZ(), returnTo.getYaw(), returnTo.getPitch(), 1, false); sendPacket(cancel); @@ -386,21 +345,21 @@ public class ClientConnection extends Thread { Location from = player.getLocation(); Location to = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ(), pos.getYaw(), pos.getPitch()); - PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to)); + PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); processMoveEvent.consume(event); } else if (packetType.equals(PacketPlayInPosition.class)) { PacketPlayInPosition pos = new PacketPlayInPosition(input); Location from = player.getLocation(); Location to = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ(), player.getLocation().getYaw(), player.getLocation().getPitch()); - PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to)); + PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); processMoveEvent.consume(event); } else if (packetType.equals(PacketPlayInRotation.class)) { PacketPlayInRotation pos = new PacketPlayInRotation(input); Location from = player.getLocation(); Location to = new Location(player.getWorld(), player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), pos.getYaw(), pos.getPitch()); - PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to)); + PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); processMoveEvent.consume(event); } else if (packetType.equals(PacketPlayInKeepAlive.class)) { PacketPlayInKeepAlive alive = new PacketPlayInKeepAlive(input); @@ -430,8 +389,8 @@ public class ClientConnection extends Thread { } } else if (packetType.equals(PacketPlayInHeldItemChange.class)) { PacketPlayInHeldItemChange change = new PacketPlayInHeldItemChange(input); - PlayerSelectedSlotChangeEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerSelectedSlotChangeEvent(player, (byte) change.getSlot())); - if (event.isCancelled()) { + PlayerSelectedSlotChangeEvent event = new PlayerSelectedSlotChangeEvent(player, (byte) change.getSlot()); + if (PlayerSelectedSlotChangeEvent.PLAYER_SELECTED_SLOT_CHANGE_EVENT.invoker().onPlayerSelectedSlotChange(event)) { PacketPlayOutHeldItemChange cancelPacket = new PacketPlayOutHeldItemChange(player.getSelectedSlot()); sendPacket(cancelPacket); } else if (change.getSlot() != event.getSlot()) { @@ -450,7 +409,7 @@ public class ClientConnection extends Thread { } } - Limbo.getInstance().getEventsManager().callEvent(new PlayerQuitEvent(player)); + PlayerQuitEvent.PLAYER_QUIT_EVENT.invoker().onPlayerQuit(player); str = inetAddress.getHostName() + ":" + client_socket.getPort() + "|" + player.getName(); Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had disconnected!");