Send empty modlist when connecting to vanilla
This commit is contained in:
parent
a0b38b7595
commit
7f434a8c5e
|
|
@ -9,6 +9,7 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
|||
import com.velocitypowered.proxy.protocol.packet.AvailableCommands;
|
||||
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
|
||||
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.adde0109.ambassador.forge.pipeline.CommandDecoderErrorCatcher;
|
||||
import org.adde0109.ambassador.forge.pipeline.ForgeLoginWrapperDecoder;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.adde0109.ambassador.forge;
|
||||
|
||||
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
|
||||
import com.velocitypowered.api.util.ModInfo;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
||||
|
|
@ -13,9 +14,9 @@ import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
|||
import io.netty.buffer.Unpooled;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.adde0109.ambassador.Ambassador;
|
||||
import org.adde0109.ambassador.forge.packet.GenericForgeLoginWrapperPacket;
|
||||
import org.adde0109.ambassador.forge.packet.IForgeLoginWrapperPacket;
|
||||
import org.adde0109.ambassador.forge.packet.ModListReplyPacket;
|
||||
import org.adde0109.ambassador.forge.pipeline.ForgeLoginWrapperDecoder;
|
||||
import org.adde0109.ambassador.velocity.client.FML2CRPMResetCompleteDecoder;
|
||||
import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder;
|
||||
import org.adde0109.ambassador.velocity.client.ClientPacketQueue;
|
||||
|
|
@ -29,9 +30,6 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
|||
}
|
||||
},
|
||||
IN_PROGRESS {
|
||||
@Override
|
||||
public void resetConnectionPhase(ConnectedPlayer player) {
|
||||
}
|
||||
},
|
||||
RESETTABLE {
|
||||
@Override
|
||||
|
|
@ -41,6 +39,34 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
|||
((VelocityServer) Ambassador.getInstance().server).registerConnection(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConnectionPhase(ConnectedPlayer player) {
|
||||
MinecraftConnection connection = player.getConnection();
|
||||
|
||||
//There is no going back even if the handshake fails. No reason to still be connected.
|
||||
if (player.getConnectedServer() != null) {
|
||||
player.getConnectedServer().disconnect();
|
||||
player.setConnectedServer(null);
|
||||
}
|
||||
//Don't handle anything from the server until the reset has completed.
|
||||
//player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(false);
|
||||
|
||||
if (connection.getState() == StateRegistry.PLAY) {
|
||||
connection.write(new PluginMessage("fml:handshake", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generatePluginResetPacket())));
|
||||
connection.setState(StateRegistry.LOGIN);
|
||||
} else {
|
||||
connection.write(new LoginPluginMessage(98,"fml:handshake", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateResetPacket())));
|
||||
}
|
||||
|
||||
//Prepare to receive reset ACK
|
||||
connection.getChannel().pipeline().addBefore(Connections.MINECRAFT_DECODER,
|
||||
ForgeConstants.RESET_LISTENER, new FML2CRPMResetCompleteDecoder());
|
||||
|
||||
//Transition
|
||||
player.setPhase(WAITING_RESET);
|
||||
WAITING_RESET.onTransitionToNewPhase(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean consideredComplete() {
|
||||
return true;
|
||||
|
|
@ -52,15 +78,15 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
|||
//We unregister so no plugin sees this client while the client is being reset.
|
||||
((VelocityServer) Ambassador.getInstance().server).unregisterConnection(player);
|
||||
player.getConnection().getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,
|
||||
ForgeConstants.LOGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.LOGIN));
|
||||
ForgeConstants.LOGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.PLAY));
|
||||
if (player.getConnection().getChannel().pipeline().get(ForgeConstants.PLUGIN_PACKET_QUEUE) == null)
|
||||
player.getConnection().getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,
|
||||
ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.PLAY));
|
||||
ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.LOGIN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket msg, VelocityServerConnection server) {
|
||||
if (msg.getId() == 80) {
|
||||
if (msg.getId() == 98) {
|
||||
player.getConnection().getChannel().pipeline().remove(ForgeConstants.RESET_LISTENER);
|
||||
player.setPhase(NOT_STARTED);
|
||||
|
||||
|
|
@ -68,7 +94,7 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
|||
|
||||
if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
|
||||
// -> vanilla
|
||||
complete(player, ((GenericForgeLoginWrapperPacket) msg).success());
|
||||
complete(player);
|
||||
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(true);
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +127,14 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
|||
player.setPhase(nextPhase());
|
||||
|
||||
if (msg instanceof ModListReplyPacket replyPacket) {
|
||||
ModInfo modInfo = new ModInfo("FML2", replyPacket.getMods().stream().map(
|
||||
(v) -> new ModInfo.Mod(v,"1")).toList());
|
||||
player.setModInfo(modInfo);
|
||||
if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
|
||||
complete(player);
|
||||
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(true);
|
||||
return true;
|
||||
}
|
||||
replyPacket.getChannels().put(MinecraftChannelIdentifier.from("ambassador:commands"),"1");
|
||||
}
|
||||
|
||||
|
|
@ -108,13 +142,22 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
|||
return true;
|
||||
}
|
||||
|
||||
public void complete(ConnectedPlayer player, boolean resettable) {
|
||||
public void sendVanillaModlist(ConnectedPlayer player) {
|
||||
player.getConnection().write(new LoginPluginMessage(0, "fml:loginwrapper",
|
||||
Unpooled.wrappedBuffer(ForgeHandshakeUtils.emptyModlist)));
|
||||
|
||||
ForgeLoginWrapperDecoder decoder = (ForgeLoginWrapperDecoder) player.getConnection()
|
||||
.getChannel().pipeline().get(ForgeConstants.FORGE_HANDSHAKE_DECODER);
|
||||
decoder.registerLoginWrapperID(0);
|
||||
}
|
||||
|
||||
public void complete(ConnectedPlayer player) {
|
||||
MinecraftConnection connection = player.getConnection();
|
||||
((OutboundSuccessHolder) connection.getChannel().pipeline().get(ForgeConstants.SERVER_SUCCESS_LISTENER))
|
||||
.sendPacket();
|
||||
connection.setState(StateRegistry.PLAY);
|
||||
|
||||
if (resettable) {
|
||||
if (isResettable(player)) {
|
||||
player.setPhase(RESETTABLE);
|
||||
RESETTABLE.onTransitionToNewPhase(player);
|
||||
} else {
|
||||
|
|
@ -123,32 +166,11 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConnectionPhase(ConnectedPlayer player) {
|
||||
MinecraftConnection connection = player.getConnection();
|
||||
|
||||
//There is no going back even if the handshake fails. No reason to still be connected.
|
||||
if (player.getConnectedServer() != null) {
|
||||
player.getConnectedServer().disconnect();
|
||||
player.setConnectedServer(null);
|
||||
private boolean isResettable(ConnectedPlayer player) {
|
||||
if (player.getModInfo().isPresent()) {
|
||||
return player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("clientresetpacket")));
|
||||
}
|
||||
//Don't handle anything from the server until the reset has completed.
|
||||
//player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(false);
|
||||
|
||||
if (connection.getState() == StateRegistry.PLAY) {
|
||||
connection.write(new PluginMessage("fml:handshake", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generatePluginResetPacket())));
|
||||
connection.setState(StateRegistry.LOGIN);
|
||||
} else {
|
||||
connection.write(new LoginPluginMessage(80,"fml:handshake", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generateResetPacket())));
|
||||
}
|
||||
|
||||
//Prepare to receive reset ACK
|
||||
connection.getChannel().pipeline().addBefore(Connections.MINECRAFT_DECODER,
|
||||
ForgeConstants.RESET_LISTENER, new FML2CRPMResetCompleteDecoder());
|
||||
|
||||
//Transition
|
||||
player.setPhase(WAITING_RESET);
|
||||
WAITING_RESET.onTransitionToNewPhase(player);
|
||||
return false;
|
||||
}
|
||||
|
||||
void onTransitionToNewPhase(ConnectedPlayer player) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ package org.adde0109.ambassador.forge.packet;
|
|||
|
||||
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
|
||||
|
||||
public interface IForgeLoginWrapperPacket<T> {
|
||||
public T read(LoginPluginResponse message);
|
||||
public interface IForgeLoginWrapperPacket {
|
||||
public LoginPluginResponse encode();
|
||||
public int getId();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
package org.adde0109.ambassador.forge.packet;
|
||||
|
||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ModListPacket implements IForgeLoginWrapperPacket{
|
||||
|
||||
private List<String> mods;
|
||||
private Map<ChannelIdentifier, String> channels;
|
||||
private List<ChannelIdentifier> registries;
|
||||
private final int id;
|
||||
|
||||
public ModListPacket(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(LoginPluginResponse message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginPluginResponse encode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ public class ModListReplyPacket implements IForgeLoginWrapperPacket {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public ModListReplyPacket read(LoginPluginResponse msg) {
|
||||
public static ModListReplyPacket read(LoginPluginResponse msg) {
|
||||
ByteBuf input = msg.content();
|
||||
|
||||
List<String> mods = new ArrayList<>();
|
||||
|
|
@ -76,7 +76,7 @@ public class ModListReplyPacket implements IForgeLoginWrapperPacket {
|
|||
ProtocolUtils.writeVarInt(output, buf.readableBytes());
|
||||
output.writeBytes(buf);
|
||||
|
||||
return new LoginPluginResponse(id,true,output);
|
||||
return new LoginPluginResponse(id, true, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,25 +1,16 @@
|
|||
package org.adde0109.ambassador.velocity.backend;
|
||||
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||
import com.velocitypowered.proxy.connection.backend.*;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.StateRegistry;
|
||||
import com.velocitypowered.proxy.protocol.packet.Disconnect;
|
||||
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
|
||||
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess;
|
||||
import com.velocitypowered.proxy.util.except.QuietRuntimeException;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.adde0109.ambassador.Ambassador;
|
||||
import org.adde0109.ambassador.forge.ForgeConstants;
|
||||
import org.adde0109.ambassador.forge.ForgeFMLConnectionType;
|
||||
import org.adde0109.ambassador.forge.VelocityForgeBackendConnectionPhase;
|
||||
import org.adde0109.ambassador.forge.VelocityForgeClientConnectionPhase;
|
||||
import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder;
|
||||
import org.adde0109.ambassador.forge.*;
|
||||
|
||||
public class ForgeLoginSessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
|
|
@ -57,21 +48,25 @@ public class ForgeLoginSessionHandler implements MinecraftSessionHandler {
|
|||
}
|
||||
ConnectedPlayer player = serverConnection.getPlayer();
|
||||
if (!(serverConnection.getConnection().getType() instanceof ForgeFMLConnectionType)) {
|
||||
//Initial vanilla - because we need to find out if reset packet works
|
||||
//Forge -> vanilla
|
||||
if (player.getConnectedServer() == null) {
|
||||
//Initial Vanilla
|
||||
|
||||
//Send empty Mod list
|
||||
//Send empty mod list in order to get client mod list
|
||||
((VelocityForgeClientConnectionPhase) player.getPhase()).sendVanillaModlist(player);
|
||||
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(false);
|
||||
//((VelocityForgeClientConnectionPhase) player.getPhase()).complete(player);
|
||||
} else if (player.getConnectedServer().getConnection().getType() instanceof ForgeFMLConnectionType) {
|
||||
//Forge -> vanilla
|
||||
player.getPhase().resetConnectionPhase(player);
|
||||
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(false);
|
||||
}
|
||||
} else {
|
||||
//TODO: Read modlist
|
||||
((VelocityForgeClientConnectionPhase) player.getPhase()).complete(player, true);
|
||||
((VelocityForgeClientConnectionPhase) player.getPhase()).complete(player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean handle(Disconnect packet) {
|
||||
if (!serverConnection.getPhase().consideredComplete()) {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import io.netty.channel.*;
|
|||
public class ClientPacketQueue extends ChannelOutboundHandlerAdapter {
|
||||
|
||||
private PendingWriteQueue queue;
|
||||
private final StateRegistry registry;
|
||||
private final StateRegistry allow;
|
||||
|
||||
public ClientPacketQueue(StateRegistry registry) {
|
||||
this.registry = registry;
|
||||
this.allow = registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -26,11 +26,11 @@ public class ClientPacketQueue extends ChannelOutboundHandlerAdapter {
|
|||
MinecraftConnection connection = ctx.pipeline().get(MinecraftConnection.class);
|
||||
if (msg instanceof MinecraftPacket packet) {
|
||||
try {
|
||||
registry.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND ,
|
||||
allow.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND ,
|
||||
connection.getProtocolVersion()).getPacketId(packet);
|
||||
queue.add(msg,promise);
|
||||
ctx.write(msg,promise);
|
||||
} catch (IllegalArgumentException e) {
|
||||
ctx.write(msg, promise);
|
||||
queue.add(msg, promise);
|
||||
}
|
||||
} else {
|
||||
ctx.write(msg,promise);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class FML2CRPMResetCompleteDecoder extends ChannelInboundHandlerAdapter {
|
|||
try {
|
||||
int id = ProtocolUtils.readVarInt(buf);
|
||||
boolean success = buf.readBoolean();
|
||||
if (id == 80) {
|
||||
if (id == 98) {
|
||||
try {
|
||||
IForgeLoginWrapperPacket packet = new GenericForgeLoginWrapperPacket(Unpooled.EMPTY_BUFFER, id, success);
|
||||
ctx.fireChannelRead(packet);
|
||||
|
|
|
|||
|
|
@ -30,12 +30,12 @@ public class VelocityHandshakeSessionHandler implements MinecraftSessionHandler
|
|||
case "FML2":
|
||||
connection.setType(ForgeConstants.ForgeFML2);
|
||||
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.SERVER_SUCCESS_LISTENER, new OutboundSuccessHolder());
|
||||
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.PLAY));
|
||||
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.LOGIN));
|
||||
break;
|
||||
case "FML3":
|
||||
connection.setType(ForgeConstants.ForgeFML3);
|
||||
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.SERVER_SUCCESS_LISTENER, new OutboundSuccessHolder());
|
||||
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.PLAY));
|
||||
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.LOGIN));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user