diff --git a/build.gradle.kts b/build.gradle.kts index 09f2b68..cc27316 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } group = "org.adde0109" -version = "1.1.7-alpha" +version = "1.2.0-beta" repositories { mavenCentral() @@ -24,6 +24,7 @@ dependencies { implementation("org.apache.commons:commons-collections4:4.4") compileOnly("io.netty:netty-buffer:4.1.86.Final") compileOnly("io.netty:netty-transport:4.1.86.Final") + compileOnly("io.netty:netty-codec:4.1.86.Final") } tasks { diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index be7058e..ab3cd17 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -4,28 +4,37 @@ import com.google.inject.Inject; import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.ProxyServer; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.concurrent.Callable; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.network.BackendChannelInitializer; import com.velocitypowered.proxy.network.ConnectionManager; import com.velocitypowered.proxy.network.ServerChannelInitializer; +import com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier; +import com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentPropertyRegistry; +import com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentPropertySerializer; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelInitializer; import org.adde0109.ambassador.velocity.VelocityBackendChannelInitializer; import org.adde0109.ambassador.velocity.VelocityServerChannelInitializer; import org.adde0109.ambassador.velocity.VelocityEventHandler; +import org.adde0109.ambassador.velocity.protocol.EnumArgumentProperty; +import org.adde0109.ambassador.velocity.protocol.EnumArgumentPropertySerializer; +import org.adde0109.ambassador.velocity.protocol.ModIdArgumentProperty; import org.bstats.charts.SingleLineChart; import org.bstats.velocity.Metrics; import org.slf4j.Logger; import java.nio.file.Path; -@Plugin(id = "ambassador", name = "Ambassador", version = "1.1.7-alpha", authors = {"adde0109"}) +@Plugin(id = "ambassador", name = "Ambassador", version = "1.2.0-beta", authors = {"adde0109"}) public class Ambassador { public ProxyServer server; @@ -66,6 +75,23 @@ public class Ambassador { ChannelInitializer originalBackend = ((ConnectionManager) cmField.get(server)).backendChannelInitializer.get(); ((ConnectionManager) cmField.get(server)).backendChannelInitializer.set(new VelocityBackendChannelInitializer(originalBackend,(VelocityServer) server)); + + Method argumentRegistry = ArgumentPropertyRegistry.class.getDeclaredMethod("register", ArgumentIdentifier.class, Class.class, ArgumentPropertySerializer.class); + argumentRegistry.setAccessible(true); + argumentRegistry.invoke(null,ArgumentIdentifier.id("forge:enum"), EnumArgumentProperty.class, EnumArgumentPropertySerializer.ENUM); + argumentRegistry.invoke(null,ArgumentIdentifier.id("forge:modid"), ModIdArgumentProperty.class, + new ArgumentPropertySerializer<>() { + @Override + public ModIdArgumentProperty deserialize(ByteBuf buf, ProtocolVersion protocolVersion) { + return new ModIdArgumentProperty(); + } + + @Override + public void serialize(Object object, ByteBuf buf, ProtocolVersion protocolVersion) { + + } + }); + } private void initMetrics() { diff --git a/src/main/java/org/adde0109/ambassador/forge/ForgeConstants.java b/src/main/java/org/adde0109/ambassador/forge/ForgeConstants.java index e2300e2..d80e411 100644 --- a/src/main/java/org/adde0109/ambassador/forge/ForgeConstants.java +++ b/src/main/java/org/adde0109/ambassador/forge/ForgeConstants.java @@ -4,6 +4,7 @@ import com.velocitypowered.proxy.connection.ConnectionType; public class ForgeConstants { public static final String HANDLER = "Modern Forge handler"; + public static final String MARKER_ADDER = "FML2/3 Marker Adder"; public static final String OUTBOUND_CATCHER_NAME = "ambassador-catcher"; public static final String RESET_LISTENER = "ambassador-reset-listener"; diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityBackendChannelInitializer.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityBackendChannelInitializer.java index 711acda..828636a 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityBackendChannelInitializer.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityBackendChannelInitializer.java @@ -5,6 +5,7 @@ import com.velocitypowered.proxy.network.BackendChannelInitializer; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import org.adde0109.ambassador.forge.ForgeConstants; +import org.adde0109.ambassador.velocity.backend.FMLMarkerAdder; import org.adde0109.ambassador.velocity.backend.VelocityForgeBackendHandshakeHandler; @@ -39,6 +40,7 @@ public class VelocityBackendChannelInitializer extends BackendChannelInitializer } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } + ch.pipeline().addLast(ForgeConstants.MARKER_ADDER, new FMLMarkerAdder()); ch.pipeline().addLast(ForgeConstants.HANDLER, new VelocityForgeBackendHandshakeHandler(server)); } } diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/FMLMarkerAdder.java b/src/main/java/org/adde0109/ambassador/velocity/backend/FMLMarkerAdder.java new file mode 100644 index 0000000..da3672b --- /dev/null +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/FMLMarkerAdder.java @@ -0,0 +1,32 @@ +package org.adde0109.ambassador.velocity.backend; + +import com.velocitypowered.proxy.connection.MinecraftConnection; +import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; +import com.velocitypowered.proxy.network.Connections; +import com.velocitypowered.proxy.protocol.packet.Handshake; +import io.netty.channel.*; +import io.netty.handler.codec.MessageToMessageEncoder; +import org.adde0109.ambassador.forge.ForgeConstants; +import org.adde0109.ambassador.forge.ForgeFMLConnectionType; + +import java.util.ArrayList; +import java.util.List; + +public class FMLMarkerAdder extends MessageToMessageEncoder { + + public FMLMarkerAdder() { + super(Handshake.class); + } + + @Override + protected void encode(ChannelHandlerContext ctx, Handshake msg, List out) { + MinecraftConnection connection = (MinecraftConnection) ctx.pipeline().get(Connections.HANDLER); + VelocityServerConnection serverConnection = (VelocityServerConnection) connection.getAssociation(); + + if (serverConnection.getPlayer().getConnection().getType() instanceof ForgeFMLConnectionType) { + msg.setServerAddress(msg.getServerAddress() + ForgeConstants.FML2Marker); + } + out.add(msg); + ctx.pipeline().remove(this); + } +} diff --git a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java index 06328bd..5589ae6 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/backend/VelocityForgeBackendHandshakeHandler.java @@ -1,19 +1,12 @@ package org.adde0109.ambassador.velocity.backend; import com.velocitypowered.proxy.VelocityServer; -import com.velocitypowered.proxy.config.PlayerInfoForwarding; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.backend.LoginSessionHandler; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.network.Connections; -import com.velocitypowered.proxy.protocol.packet.Handshake; -import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; -import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess; import io.netty.channel.*; -import io.netty.util.ReferenceCountUtil; -import org.adde0109.ambassador.forge.ForgeConstants; import org.adde0109.ambassador.forge.ForgeFMLConnectionType; -import org.adde0109.ambassador.velocity.VelocityForgeClientConnectionPhase; import org.jetbrains.annotations.NotNull; public class VelocityForgeBackendHandshakeHandler extends ChannelInboundHandlerAdapter { @@ -29,11 +22,12 @@ public class VelocityForgeBackendHandshakeHandler extends ChannelInboundHandlerA MinecraftConnection connection = (MinecraftConnection) ctx.pipeline().get(Connections.HANDLER); VelocityServerConnection serverConnection = (VelocityServerConnection) connection.getAssociation(); + ctx.pipeline().remove(this); + if (serverConnection.getPlayer().getConnection().getType() instanceof ForgeFMLConnectionType) { connection.setSessionHandler(new ForgeHandshakeSessionHandler((LoginSessionHandler) connection.getSessionHandler(),serverConnection,server)); } - ctx.pipeline().remove(this); ctx.pipeline().fireChannelActive(); } } diff --git a/src/main/java/org/adde0109/ambassador/velocity/protocol/EnumArgumentProperty.java b/src/main/java/org/adde0109/ambassador/velocity/protocol/EnumArgumentProperty.java new file mode 100644 index 0000000..2cd6b8a --- /dev/null +++ b/src/main/java/org/adde0109/ambassador/velocity/protocol/EnumArgumentProperty.java @@ -0,0 +1,23 @@ +package org.adde0109.ambassador.velocity.protocol; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; + +public class EnumArgumentProperty implements ArgumentType { + + private final String className; + + public EnumArgumentProperty(String className) { + this.className = className; + } + + public String getClassName() { + return this.className; + } + + @Override + public String parse(StringReader reader) throws CommandSyntaxException { + return reader.readUnquotedString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/adde0109/ambassador/velocity/protocol/EnumArgumentPropertySerializer.java b/src/main/java/org/adde0109/ambassador/velocity/protocol/EnumArgumentPropertySerializer.java new file mode 100644 index 0000000..a34f454 --- /dev/null +++ b/src/main/java/org/adde0109/ambassador/velocity/protocol/EnumArgumentPropertySerializer.java @@ -0,0 +1,28 @@ +package org.adde0109.ambassador.velocity.protocol; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentPropertySerializer; +import io.netty.buffer.ByteBuf; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * An argument property serializer that will serialize and deserialize nothing. + */ +public class EnumArgumentPropertySerializer implements ArgumentPropertySerializer { + + public static final EnumArgumentPropertySerializer ENUM = new EnumArgumentPropertySerializer(); + + private EnumArgumentPropertySerializer() { + } + + @Override + public @Nullable EnumArgumentProperty deserialize(ByteBuf buf, ProtocolVersion protocolVersion) { + return new EnumArgumentProperty(ProtocolUtils.readString(buf)); + } + + @Override + public void serialize(EnumArgumentProperty object, ByteBuf buf, ProtocolVersion protocolVersion) { + ProtocolUtils.writeString(buf, object.getClassName()); + } +} diff --git a/src/main/java/org/adde0109/ambassador/velocity/protocol/ModIdArgumentProperty.java b/src/main/java/org/adde0109/ambassador/velocity/protocol/ModIdArgumentProperty.java new file mode 100644 index 0000000..d85d41e --- /dev/null +++ b/src/main/java/org/adde0109/ambassador/velocity/protocol/ModIdArgumentProperty.java @@ -0,0 +1,47 @@ +package org.adde0109.ambassador.velocity.protocol; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.util.ModInfo; +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +public class ModIdArgumentProperty implements ArgumentType { + + public ModIdArgumentProperty() {} + + @Override + public String parse(StringReader reader) throws CommandSyntaxException { + return reader.readUnquotedString(); + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, + SuggestionsBuilder builder) { + S source = context.getSource(); + + if (source instanceof Player) { + ModInfo modInfo = ((Player) source).getModInfo().orElse(null); + + if (modInfo != null) { + for (ModInfo.Mod mod : modInfo.getMods()) { + builder.suggest(mod.getId()); + } + + return builder.buildFuture(); + } + } + + return Suggestions.empty(); + } + + @Override + public Collection getExamples() { + throw new UnsupportedOperationException(); + } +} \ No newline at end of file