diff --git a/api/src/main/java/org/geysermc/floodgate/api/packet/PacketHandler.java b/api/src/main/java/org/geysermc/floodgate/api/packet/PacketHandler.java new file mode 100644 index 00000000..4ccc2bd8 --- /dev/null +++ b/api/src/main/java/org/geysermc/floodgate/api/packet/PacketHandler.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.api.packet; + +import io.netty.channel.ChannelHandlerContext; + +/** + * For advanced users only! You shouldn't play with this unless you know what you're doing. + */ +public interface PacketHandler { + /** + * Called when a registered packet has been seen. + * + * @param ctx the channel handler context of the connection + * @param packet the packet instance + * @param serverbound if the packet is serverbound + * @return the packet it should forward. Can be null or a different packet / instance + */ + Object handle(ChannelHandlerContext ctx, Object packet, boolean serverbound); +} diff --git a/api/src/main/java/org/geysermc/floodgate/api/packet/PacketHandlers.java b/api/src/main/java/org/geysermc/floodgate/api/packet/PacketHandlers.java new file mode 100644 index 00000000..4f025231 --- /dev/null +++ b/api/src/main/java/org/geysermc/floodgate/api/packet/PacketHandlers.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.api.packet; + +import io.netty.channel.ChannelHandlerContext; +import org.geysermc.floodgate.api.util.TriFunction; + +public interface PacketHandlers { + /** + * Register a specific class for a specific consumer. + * + * @param handler the packet handler instance + * @param packetClass the class to start listening for + * @param consumer the consumer to call once the packet has been seen + */ + void register( + PacketHandler handler, + Class packetClass, + TriFunction consumer); + + /** + * Register a specific class for the given packet handler's {@link + * PacketHandler#handle(ChannelHandlerContext, Object, boolean)}. + * + * @param handler the packet handler instance + * @param packetClass the class to start listening for + */ + default void register(PacketHandler handler, Class packetClass) { + register(handler, packetClass, handler::handle); + } + + /** + * Register every packet for the given packet handler's {@link PacketHandler#handle(ChannelHandlerContext, + * Object, boolean)} + */ + void registerAll(PacketHandler handler); + + /** + * Unregisters all handlers registered under the given packet handler + * + * @param handler the packet handler instance + */ + void deregister(PacketHandler handler); +} diff --git a/api/src/main/java/org/geysermc/floodgate/api/util/TriFunction.java b/api/src/main/java/org/geysermc/floodgate/api/util/TriFunction.java new file mode 100644 index 00000000..4816e6b7 --- /dev/null +++ b/api/src/main/java/org/geysermc/floodgate/api/util/TriFunction.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.api.util; + +import java.util.Objects; +import java.util.function.Function; + +/** + * Represents a function that accepts three arguments and produces a result. This is the three-arity + * specialization of {@link Function}. + * + *

This is a functional interface + * whose functional method is {@link #apply(Object, Object, Object)}. + * + * @param the type of the first argument to the function + * @param the type of the second argument to the function + * @param the type of the third argument of the function + * @param the type of the result of the function + * @see Function + * @since 1.8 + */ +@FunctionalInterface +public interface TriFunction { + /** + * Performs this operation on the given arguments. + * + * @param t the first input argument + * @param u the second input argument + * @param v the third input argument + */ + R apply(T t, U u, V v); + + /** + * Returns a composed function that first applies this function to its input, and then applies + * the {@code after} function to the result. If evaluation of either function throws an + * exception, it is relayed to the caller of the composed function. + * + * @param the type of output of the {@code after} function, and of the composed function + * @param after the function to apply after this function is applied + * @return a composed function that first applies this function and then applies the {@code + * after} function + * @throws NullPointerException if after is null + */ + default TriFunction andThen(Function after) { + Objects.requireNonNull(after); + return (T t, U u, V v) -> after.apply(apply(t, u, v)); + } +} diff --git a/bungee/src/main/java/org/geysermc/floodgate/module/BungeeAddonModule.java b/bungee/src/main/java/org/geysermc/floodgate/module/BungeeAddonModule.java index 95701696..ebe7f8a2 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/module/BungeeAddonModule.java +++ b/bungee/src/main/java/org/geysermc/floodgate/module/BungeeAddonModule.java @@ -30,6 +30,7 @@ import com.google.inject.Singleton; import com.google.inject.multibindings.ProvidesIntoSet; import org.geysermc.floodgate.addon.AddonManagerAddon; import org.geysermc.floodgate.addon.DebugAddon; +import org.geysermc.floodgate.addon.PacketHandlerAddon; import org.geysermc.floodgate.addon.data.BungeeDataAddon; import org.geysermc.floodgate.api.inject.InjectorAddon; import org.geysermc.floodgate.register.AddonRegister; @@ -57,4 +58,10 @@ public final class BungeeAddonModule extends AbstractModule { public InjectorAddon debugAddon() { return new DebugAddon(); } + + @Singleton + @ProvidesIntoSet + public InjectorAddon packetHandlerAddon() { + return new PacketHandlerAddon(); + } } diff --git a/common/src/main/java/org/geysermc/floodgate/addon/PacketHandlerAddon.java b/common/src/main/java/org/geysermc/floodgate/addon/PacketHandlerAddon.java new file mode 100644 index 00000000..d5f67d97 --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/addon/PacketHandlerAddon.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.addon; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import io.netty.channel.Channel; +import io.netty.channel.ChannelPipeline; +import org.geysermc.floodgate.addon.packethandler.ChannelInPacketHandler; +import org.geysermc.floodgate.addon.packethandler.ChannelOutPacketHandler; +import org.geysermc.floodgate.api.inject.InjectorAddon; +import org.geysermc.floodgate.packet.PacketHandlersImpl; +import org.geysermc.floodgate.util.Utils; + +public class PacketHandlerAddon implements InjectorAddon { + @Inject private PacketHandlersImpl packetHandlers; + + @Inject + @Named("packetEncoder") + private String packetEncoder; + + @Inject + @Named("packetDecoder") + private String packetDecoder; + + @Override + public void onInject(Channel channel, boolean toServer) { + channel.pipeline().addAfter( + packetEncoder, "floodgate_phaddon_out", + new ChannelOutPacketHandler(packetHandlers, toServer) + ).addAfter( + packetDecoder, "floodgate_phaddon_in", + new ChannelInPacketHandler(packetHandlers, toServer) + ); + } + + @Override + public void onLoginDone(Channel channel) { + + } + + @Override + public void onRemoveInject(Channel channel) { + ChannelPipeline pipeline = channel.pipeline(); + + Utils.removeHandler(pipeline, "floodgate_phaddon_out"); + Utils.removeHandler(pipeline, "floodgate_phaddon_in"); + } + + @Override + public boolean shouldInject() { + // this means that there has to be at least one PacketHandler registered to inject + return packetHandlers.hasHandlers(); + } +} diff --git a/common/src/main/java/org/geysermc/floodgate/addon/packethandler/ChannelInPacketHandler.java b/common/src/main/java/org/geysermc/floodgate/addon/packethandler/ChannelInPacketHandler.java new file mode 100644 index 00000000..6456decf --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/addon/packethandler/ChannelInPacketHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.addon.packethandler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.geysermc.floodgate.api.util.TriFunction; +import org.geysermc.floodgate.packet.PacketHandlersImpl; + +public class ChannelInPacketHandler extends SimpleChannelInboundHandler { + private final PacketHandlersImpl packetHandlers; + private final boolean toServer; + + public ChannelInPacketHandler(PacketHandlersImpl packetHandlers, boolean toServer) { + this.packetHandlers = packetHandlers; + this.toServer = toServer; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object msg) { + Object packet = msg; + for (TriFunction consumer : + packetHandlers.getPacketHandlers(msg.getClass())) { + + Object res = consumer.apply(ctx, msg, toServer); + if (!res.equals(msg)) { + packet = res; + } + } + + ctx.fireChannelRead(packet); + } +} diff --git a/common/src/main/java/org/geysermc/floodgate/addon/packethandler/ChannelOutPacketHandler.java b/common/src/main/java/org/geysermc/floodgate/addon/packethandler/ChannelOutPacketHandler.java new file mode 100644 index 00000000..0347101f --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/addon/packethandler/ChannelOutPacketHandler.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.addon.packethandler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; +import java.util.List; +import org.geysermc.floodgate.api.util.TriFunction; +import org.geysermc.floodgate.packet.PacketHandlersImpl; + +public class ChannelOutPacketHandler extends MessageToMessageEncoder { + private final PacketHandlersImpl packetHandlers; + private final boolean toServer; + + public ChannelOutPacketHandler(PacketHandlersImpl packetHandlers, boolean toServer) { + this.packetHandlers = packetHandlers; + this.toServer = toServer; + } + + @Override + protected void encode(ChannelHandlerContext ctx, Object msg, List out) { + Object packet = msg; + for (TriFunction consumer : + packetHandlers.getPacketHandlers(msg.getClass())) { + + Object res = consumer.apply(ctx, msg, toServer); + if (!res.equals(msg)) { + packet = res; + } + } + + out.add(packet); + } +} diff --git a/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java b/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java index a53c6c5e..a4e6fae2 100644 --- a/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java +++ b/common/src/main/java/org/geysermc/floodgate/module/CommonModule.java @@ -38,6 +38,7 @@ import org.geysermc.floodgate.api.SimpleFloodgateApi; import org.geysermc.floodgate.api.handshake.HandshakeHandlers; import org.geysermc.floodgate.api.inject.PlatformInjector; import org.geysermc.floodgate.api.logger.FloodgateLogger; +import org.geysermc.floodgate.api.packet.PacketHandlers; import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.config.FloodgateConfigHolder; @@ -51,6 +52,7 @@ import org.geysermc.floodgate.crypto.Base64Topping; import org.geysermc.floodgate.crypto.FloodgateCipher; import org.geysermc.floodgate.crypto.KeyProducer; import org.geysermc.floodgate.inject.CommonPlatformInjector; +import org.geysermc.floodgate.packet.PacketHandlersImpl; import org.geysermc.floodgate.player.FloodgateHandshakeHandler; import org.geysermc.floodgate.pluginmessage.PluginMessageManager; import org.geysermc.floodgate.skin.SkinApplier; @@ -66,6 +68,9 @@ public class CommonModule extends AbstractModule { bind(FloodgateApi.class).to(SimpleFloodgateApi.class); bind(PlatformInjector.class).to(CommonPlatformInjector.class); bind(HandshakeHandlers.class).to(HandshakeHandlersImpl.class); + + bind(PacketHandlers.class).to(PacketHandlersImpl.class); + bind(PacketHandlersImpl.class).asEagerSingleton(); } @Provides diff --git a/common/src/main/java/org/geysermc/floodgate/packet/PacketHandlersImpl.java b/common/src/main/java/org/geysermc/floodgate/packet/PacketHandlersImpl.java new file mode 100644 index 00000000..7456ccde --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/packet/PacketHandlersImpl.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Floodgate + */ + +package org.geysermc.floodgate.packet; + +import io.netty.channel.ChannelHandlerContext; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.geysermc.floodgate.api.packet.PacketHandler; +import org.geysermc.floodgate.api.packet.PacketHandlers; +import org.geysermc.floodgate.api.util.TriFunction; + +public final class PacketHandlersImpl implements PacketHandlers { + private final Map> handlers = new HashMap<>(); + private final Set> globalPacketHandlers = new HashSet<>(); + private final Map, Set>> packetHandlers = new HashMap<>(); + + @Override + public void register( + PacketHandler handler, + Class packetClass, + TriFunction consumer) { + + if (handler == null || packetClass == null || consumer == null) { + return; + } + + handlers.computeIfAbsent(handler, $ -> new ArrayList<>()) + .add(new HandlerEntry(packetClass, consumer)); + + packetHandlers.computeIfAbsent(packetClass, $ -> new HashSet<>(globalPacketHandlers)) + .add(consumer); + } + + @Override + public void registerAll(PacketHandler handler) { + if (handler == null) { + return; + } + + TriFunction packetHandler = handler::handle; + + handlers.computeIfAbsent(handler, $ -> new ArrayList<>()) + .add(new HandlerEntry(null, packetHandler)); + + globalPacketHandlers.add(packetHandler); + for (Set> handle : packetHandlers.values()) { + handle.add(packetHandler); + } + } + + @Override + public void deregister(PacketHandler handler) { + if (handler == null) { + return; + } + + List values = handlers.remove(handler); + if (values != null) { + for (HandlerEntry value : values) { + Set handlers = packetHandlers.get(value.getPacket()); + + if (handlers != null) { + handlers.removeIf(o -> o.equals(value.getHandler())); + if (handlers.isEmpty()) { + packetHandlers.remove(value.getPacket()); + } + } + + globalPacketHandlers.remove(value.getHandler()); + } + } + } + + public Collection> getPacketHandlers( + Class packet) { + return packetHandlers.getOrDefault(packet, Collections.emptySet()); + } + + public boolean hasHandlers() { + return !handlers.isEmpty(); + } + + @AllArgsConstructor + @Getter + private final static class HandlerEntry { + private final Class packet; + private final TriFunction handler; + } +} diff --git a/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java b/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java index 9ffed551..3871ebcb 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java +++ b/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java @@ -28,7 +28,6 @@ package org.geysermc.floodgate; import com.google.inject.Guice; import com.google.inject.Injector; import org.bukkit.plugin.java.JavaPlugin; -import org.geysermc.floodgate.api.InstanceHolder; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.module.PluginMessageModule; import org.geysermc.floodgate.module.ServerCommonModule; @@ -42,6 +41,7 @@ import org.geysermc.floodgate.util.SpigotProtocolSupportListener; public final class SpigotPlugin extends JavaPlugin { private SpigotPlatform platform; + private Injector injector; @Override public void onLoad() { @@ -49,7 +49,7 @@ public final class SpigotPlugin extends JavaPlugin { ReflectionUtils.setPrefix("net.minecraft.server." + minecraftVersion); long ctm = System.currentTimeMillis(); - Injector injector = Guice.createInjector( + injector = Guice.createInjector( new ServerCommonModule(getDataFolder().toPath()), new SpigotPlatformModule(this) ); @@ -72,8 +72,7 @@ public final class SpigotPlugin extends JavaPlugin { // add ProtocolSupport support (hack) if (getServer().getPluginManager().getPlugin("ProtocolSupport") != null) { - InstanceHolder.getHandshakeHandlers() - .addHandshakeHandler(new SpigotProtocolSupportHandler()); + injector.getInstance(SpigotProtocolSupportHandler.class); SpigotProtocolSupportListener.registerHack(this); } } diff --git a/spigot/src/main/java/org/geysermc/floodgate/module/SpigotAddonModule.java b/spigot/src/main/java/org/geysermc/floodgate/module/SpigotAddonModule.java index 524995ef..45ad3493 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/module/SpigotAddonModule.java +++ b/spigot/src/main/java/org/geysermc/floodgate/module/SpigotAddonModule.java @@ -30,6 +30,7 @@ import com.google.inject.Singleton; import com.google.inject.multibindings.ProvidesIntoSet; import org.geysermc.floodgate.addon.AddonManagerAddon; import org.geysermc.floodgate.addon.DebugAddon; +import org.geysermc.floodgate.addon.PacketHandlerAddon; import org.geysermc.floodgate.addon.data.SpigotDataAddon; import org.geysermc.floodgate.api.inject.InjectorAddon; import org.geysermc.floodgate.register.AddonRegister; @@ -57,4 +58,10 @@ public final class SpigotAddonModule extends AbstractModule { public InjectorAddon debugAddon() { return new DebugAddon(); } + + @Singleton + @ProvidesIntoSet + public InjectorAddon packetHandlerAddon() { + return new PacketHandlerAddon(); + } } diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotProtocolSupportHandler.java b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotProtocolSupportHandler.java index 825162e3..f8cf9334 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotProtocolSupportHandler.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotProtocolSupportHandler.java @@ -25,13 +25,18 @@ package org.geysermc.floodgate.util; +import com.google.inject.Inject; +import com.google.inject.name.Named; import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.util.AttributeKey; import java.lang.reflect.Method; import java.util.UUID; -import org.geysermc.floodgate.api.handshake.HandshakeData; -import org.geysermc.floodgate.api.handshake.HandshakeHandler; +import org.geysermc.floodgate.api.packet.PacketHandler; +import org.geysermc.floodgate.api.packet.PacketHandlers; +import org.geysermc.floodgate.api.player.FloodgatePlayer; -public class SpigotProtocolSupportHandler implements HandshakeHandler { +public class SpigotProtocolSupportHandler implements PacketHandler { private static final Method getFromChannel; private static final Method getLoginProfile; @@ -51,7 +56,8 @@ public class SpigotProtocolSupportHandler implements HandshakeHandler { getFromChannel = ReflectionUtils.getMethod(connectionImpl, "getFromChannel", Channel.class); getLoginProfile = ReflectionUtils.getMethod(connectionImpl, "getLoginProfile"); - Class profile = ReflectionUtils.getClass("protocolsupport.protocol.utils.authlib.LoginProfile"); + Class profile = + ReflectionUtils.getClass("protocolsupport.protocol.utils.authlib.LoginProfile"); setName = ReflectionUtils.getMethod(profile, "setName", String.class); setOriginalName = ReflectionUtils.getMethod(profile, "setOriginalName", String.class); @@ -69,24 +75,38 @@ public class SpigotProtocolSupportHandler implements HandshakeHandler { Class loginListener = ReflectionUtils.getClass( "protocolsupport.protocol.packet.handler.AbstractLoginListener"); - handleLoginStart = ReflectionUtils.getMethod(loginListener, "handleLoginStart", String.class); + handleLoginStart = + ReflectionUtils.getMethod(loginListener, "handleLoginStart", String.class); + } + + @Inject + @Named("playerAttribute") + private AttributeKey playerAttribute; + + @Inject + public void register(PacketHandlers packetHandlers) { + packetHandlers.register(this, ReflectionUtils.getPrefixedClass("PacketLoginInStart")); } @Override - public void handle(HandshakeData data) { - if (data.isFloodgatePlayer() && !SpigotUtils.isBungeeData()) { - Object connection = ReflectionUtils.invoke(null, getFromChannel, data.getChannel()); - Object profile = ReflectionUtils.invoke(connection, getLoginProfile); - - // set correct uuid and name on ProtocolSupport's end, since we skip the LoginStart - ReflectionUtils.invoke(profile, setName, data.getCorrectUsername()); - ReflectionUtils.invoke(profile, setOriginalName, data.getCorrectUsername()); - ReflectionUtils.invoke(profile, setUuid, data.getCorrectUniqueId()); - ReflectionUtils.invoke(profile, setOriginalUuid, data.getCorrectUniqueId()); - - Object temp = ReflectionUtils.invoke(connection, getNetworkManagerWrapper); - temp = ReflectionUtils.invoke(temp, getPacketListener); - ReflectionUtils.invoke(temp, handleLoginStart, data.getCorrectUsername()); + public Object handle(ChannelHandlerContext ctx, Object packet, boolean serverbound) { + FloodgatePlayer player = ctx.channel().attr(playerAttribute).get(); + if (player == null) { + return packet; } + + Object connection = ReflectionUtils.invoke(null, getFromChannel, ctx.channel()); + Object profile = ReflectionUtils.invoke(connection, getLoginProfile); + + // set correct uuid and name on ProtocolSupport's end, since we skip the LoginStart + ReflectionUtils.invoke(profile, setName, player.getCorrectUsername()); + ReflectionUtils.invoke(profile, setOriginalName, player.getCorrectUsername()); + ReflectionUtils.invoke(profile, setUuid, player.getCorrectUniqueId()); + ReflectionUtils.invoke(profile, setOriginalUuid, player.getCorrectUniqueId()); + + Object temp = ReflectionUtils.invoke(connection, getNetworkManagerWrapper); + temp = ReflectionUtils.invoke(temp, getPacketListener); + ReflectionUtils.invoke(temp, handleLoginStart, player.getCorrectUsername()); + return packet; } } diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml index 5e6b7f0e..972691db 100644 --- a/spigot/src/main/resources/plugin.yml +++ b/spigot/src/main/resources/plugin.yml @@ -4,6 +4,4 @@ version: ${project.version} author: ${project.organization.name} website: ${project.url} main: org.geysermc.floodgate.SpigotPlugin -api-version: 1.13 -softdepend: - - ProtocolSupport \ No newline at end of file +api-version: 1.13 \ No newline at end of file diff --git a/velocity/src/main/java/org/geysermc/floodgate/module/VelocityAddonModule.java b/velocity/src/main/java/org/geysermc/floodgate/module/VelocityAddonModule.java index c441c641..9188eccf 100644 --- a/velocity/src/main/java/org/geysermc/floodgate/module/VelocityAddonModule.java +++ b/velocity/src/main/java/org/geysermc/floodgate/module/VelocityAddonModule.java @@ -30,6 +30,7 @@ import com.google.inject.Singleton; import com.google.inject.multibindings.ProvidesIntoSet; import org.geysermc.floodgate.addon.AddonManagerAddon; import org.geysermc.floodgate.addon.DebugAddon; +import org.geysermc.floodgate.addon.PacketHandlerAddon; import org.geysermc.floodgate.addon.data.VelocityDataAddon; import org.geysermc.floodgate.api.inject.InjectorAddon; import org.geysermc.floodgate.register.AddonRegister; @@ -57,4 +58,10 @@ public final class VelocityAddonModule extends AbstractModule { public InjectorAddon debugAddon() { return new DebugAddon(); } + + @Singleton + @ProvidesIntoSet + public InjectorAddon packetHandlerAddon() { + return new PacketHandlerAddon(); + } }