Changed reset mechanism

This commit is contained in:
Adrian Bergqvist 2023-05-06 16:00:30 +02:00
parent f1b1cc463c
commit a0b38b7595
No known key found for this signature in database
GPG Key ID: 3B3DA43224B79417
15 changed files with 210 additions and 159 deletions

View File

@ -5,7 +5,7 @@ plugins {
} }
group = "org.adde0109" group = "org.adde0109"
version = "1.3.4-beta" version = "1.4.0-beta"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -40,7 +40,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_3; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19_3;
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet; import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet;
@Plugin(id = "ambassador", name = "Ambassador", version = "1.3.4-beta", authors = {"adde0109"}) @Plugin(id = "ambassador", name = "Ambassador", version = "1.4.0-beta", authors = {"adde0109"})
public class Ambassador { public class Ambassador {
public ProxyServer server; public ProxyServer server;

View File

@ -8,6 +8,7 @@ public class ForgeConstants {
public static final String RESET_LISTENER = "ambassador-reset-listener"; public static final String RESET_LISTENER = "ambassador-reset-listener";
public static final String SERVER_SUCCESS_LISTENER = "ambassador-server-success-listener"; public static final String SERVER_SUCCESS_LISTENER = "ambassador-server-success-listener";
public static final String PLUGIN_PACKET_QUEUE = "ambassador-plugin-generated-packet-queue"; public static final String PLUGIN_PACKET_QUEUE = "ambassador-plugin-generated-packet-queue";
public static final String LOGIN_PACKET_QUEUE = "ambassador-login-packet-queue";
public static final String FORGE_HANDSHAKE_DECODER = "ambassador-forge-decoder"; public static final String FORGE_HANDSHAKE_DECODER = "ambassador-forge-decoder";
public static final String FORGE_HANDSHAKE_HANDLER = "ambassador-forge-handler"; public static final String FORGE_HANDSHAKE_HANDLER = "ambassador-forge-handler";
public static final String COMMAND_ERROR_CATCHER = "ambassador-command-catcher"; public static final String COMMAND_ERROR_CATCHER = "ambassador-command-catcher";

View File

@ -65,8 +65,9 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
//Reset client if not ready to receive new handshake //Reset client if not ready to receive new handshake
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase(); VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
clientPhase.resetConnectionPhase(player);
message.retain(); message.retain();
clientPhase.resetAndWrite(player, message); player.getConnection().write(message);
//Forge server //Forge server
//To avoid unnecessary resets, we wait until we get the handshake even if we know that we should //To avoid unnecessary resets, we wait until we get the handshake even if we know that we should
//reset because that the previous server was Forge. //reset because that the previous server was Forge.

View File

@ -1,7 +1,6 @@
package org.adde0109.ambassador.forge; package org.adde0109.ambassador.forge;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
@ -12,19 +11,16 @@ import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage; import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.PluginMessage; import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import net.kyori.adventure.text.Component;
import org.adde0109.ambassador.Ambassador; 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.IForgeLoginWrapperPacket;
import org.adde0109.ambassador.forge.packet.ModListReplyPacket; 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.FML2CRPMResetCompleteDecoder;
import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder; import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder;
import org.adde0109.ambassador.velocity.client.PluginLoginPacketQueue; import org.adde0109.ambassador.velocity.client.ClientPacketQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledFuture;
public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase { public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase {
//TODO:Make class when PCF is done
NOT_STARTED { NOT_STARTED {
@Override @Override
@ -33,42 +29,16 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
} }
}, },
IN_PROGRESS { IN_PROGRESS {
},
COMPLETE {
@Override
public void resetAndWrite(ConnectedPlayer player, LoginPluginMessage message) {
resetConnectionPhase(player);
pending = message;
}
@Override @Override
public void resetConnectionPhase(ConnectedPlayer player) { 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. RESETTABLE {
if (player.getConnectedServer() != null) { @Override
player.getConnectedServer().disconnect(); void onTransitionToNewPhase(ConnectedPlayer player) {
player.setConnectedServer(null); //Plugins may now send packets to client
} player.getConnection().getChannel().pipeline().remove(ForgeConstants.PLUGIN_PACKET_QUEUE);
//Don't handle anything from the server until the reset has completed. ((VelocityServer) Ambassador.getInstance().server).registerConnection(player);
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(false);
//Prepare to receive reset ACK
connection.getChannel().pipeline().addBefore(Connections.MINECRAFT_DECODER, ForgeConstants.RESET_LISTENER,new FML2CRPMResetCompleteDecoder());
((ForgeLoginWrapperDecoder) connection.getChannel().pipeline().get(ForgeConstants.FORGE_HANDSHAKE_DECODER)).registerLoginWrapperID(98);
//No more PLAY packets past this point should be sent to the client in case the reset works.
connection.write(new PluginMessage("fml:handshake", Unpooled.wrappedBuffer(ForgeHandshakeUtils.generatePluginResetPacket())));
//We unregister so no plugin sees this client while the client is being reset.
((VelocityServer) Ambassador.getInstance().server).unregisterConnection(player);
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new PluginLoginPacketQueue());
//Transition
player.setPhase(WAITING_RESET);
WAITING_RESET.onTransitionToNewPhase(player);
} }
@Override @Override
@ -77,50 +47,55 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
} }
}, },
WAITING_RESET { WAITING_RESET {
ScheduledFuture<?> scheduledFuture;
@Override @Override
void onTransitionToNewPhase(ConnectedPlayer player) { void onTransitionToNewPhase(ConnectedPlayer player) {
scheduledFuture = player.getConnection().eventLoop().schedule(()-> { //We unregister so no plugin sees this client while the client is being reset.
player.getConnection().getChannel().pipeline().remove(ForgeConstants.RESET_LISTENER); ((VelocityServer) Ambassador.getInstance().server).unregisterConnection(player);
Ambassador.getTemporaryForced().put(player.getUsername(), player.getConnectionInFlight().getServer(), player.getConnection().getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,
Ambassador.getInstance().config.getServerSwitchCancellationTime(), TimeUnit.SECONDS); ForgeConstants.LOGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.LOGIN));
//Disconnect - Reset Timeout if (player.getConnection().getChannel().pipeline().get(ForgeConstants.PLUGIN_PACKET_QUEUE) == null)
player.disconnect(Ambassador.getInstance().config.getDisconnectResetMessage()); player.getConnection().getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,
}, Ambassador.getInstance().config.getResetTimeout(), TimeUnit.MILLISECONDS); ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.PLAY));
} }
@Override @Override
public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket msg, VelocityServerConnection server) { public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket msg, VelocityServerConnection server) {
if (msg.getId() == 98) { if (msg.getId() == 80) {
if (scheduledFuture.cancel(false)) { player.getConnection().getChannel().pipeline().remove(ForgeConstants.RESET_LISTENER);
player.getConnection().getChannel().pipeline().remove(ForgeConstants.RESET_LISTENER); player.setPhase(NOT_STARTED);
player.getConnection().setState(StateRegistry.LOGIN);
player.setPhase(NOT_STARTED);
//Send all held messages player.getConnection().getChannel().pipeline().remove(ForgeConstants.LOGIN_PACKET_QUEUE);
if (pending != null)
player.getConnection().write(pending); if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
// -> vanilla
complete(player, ((GenericForgeLoginWrapperPacket) msg).success());
player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(true); player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(true);
if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
//Forge -> Vanilla
MinecraftConnection connection = player.getConnection();
((OutboundSuccessHolder) connection.getChannel().pipeline().get(ForgeConstants.SERVER_SUCCESS_LISTENER))
.sendPacket();
connection.setState(StateRegistry.PLAY);
//Plugins may now send packets to client
connection.getChannel().pipeline().remove(ForgeConstants.PLUGIN_PACKET_QUEUE);
((VelocityServer) Ambassador.getInstance().server).registerConnection(player);
}
} }
return true; return true;
} else { } else {
return false; return false;
} }
} }
},
COMPLETE {
@Override
void onTransitionToNewPhase(ConnectedPlayer player) {
//Plugins may now send packets to client
player.getConnection().getChannel().pipeline().remove(ForgeConstants.PLUGIN_PACKET_QUEUE);
((VelocityServer) Ambassador.getInstance().server).registerConnection(player);
}
@Override
public void resetConnectionPhase(ConnectedPlayer player) {
player.disconnect(Component.text("reconnect"));
}
@Override
public boolean consideredComplete() {
return true;
}
}; };
public LoginPluginMessage pending;
public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket msg, VelocityServerConnection server) { public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket msg, VelocityServerConnection server) {
player.setPhase(nextPhase()); player.setPhase(nextPhase());
@ -133,12 +108,51 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
return true; return true;
} }
void onTransitionToNewPhase(ConnectedPlayer player) { public void complete(ConnectedPlayer player, boolean resettable) {
MinecraftConnection connection = player.getConnection();
((OutboundSuccessHolder) connection.getChannel().pipeline().get(ForgeConstants.SERVER_SUCCESS_LISTENER))
.sendPacket();
connection.setState(StateRegistry.PLAY);
if (resettable) {
player.setPhase(RESETTABLE);
RESETTABLE.onTransitionToNewPhase(player);
} else {
player.setPhase(COMPLETE);
COMPLETE.onTransitionToNewPhase(player);
}
} }
public void resetAndWrite(ConnectedPlayer player, LoginPluginMessage message) { @Override
player.getConnection().write(message); 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(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);
}
void onTransitionToNewPhase(ConnectedPlayer player) {
} }
VelocityForgeClientConnectionPhase nextPhase() { VelocityForgeClientConnectionPhase nextPhase() {

View File

@ -6,10 +6,12 @@ import io.netty.buffer.ByteBuf;
public class GenericForgeLoginWrapperPacket extends DeferredByteBufHolder implements IForgeLoginWrapperPacket { public class GenericForgeLoginWrapperPacket extends DeferredByteBufHolder implements IForgeLoginWrapperPacket {
private final int id; private final int id;
private final boolean success;
public GenericForgeLoginWrapperPacket(ByteBuf input, int id) { public GenericForgeLoginWrapperPacket(ByteBuf input, int id, boolean success) {
super(input); super(input);
this.id = id; this.id = id;
this.success = success;
} }
@Override @Override
@ -21,4 +23,8 @@ public class GenericForgeLoginWrapperPacket extends DeferredByteBufHolder implem
public int getId() { public int getId() {
return id; return id;
} }
public boolean success() {
return success;
}
} }

View File

@ -2,7 +2,8 @@ package org.adde0109.ambassador.forge.packet;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse; import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
public interface IForgeLoginWrapperPacket { public interface IForgeLoginWrapperPacket<T> {
public T read(LoginPluginResponse message);
public LoginPluginResponse encode(); public LoginPluginResponse encode();
public int getId(); public int getId();
} }

View File

@ -0,0 +1,34 @@
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;
}
}

View File

@ -28,7 +28,7 @@ public class ModListReplyPacket implements IForgeLoginWrapperPacket {
this.id = id; this.id = id;
} }
public static ModListReplyPacket read(LoginPluginResponse msg) { public ModListReplyPacket read(LoginPluginResponse msg) {
ByteBuf input = msg.content(); ByteBuf input = msg.content();
List<String> mods = new ArrayList<>(); List<String> mods = new ArrayList<>();

View File

@ -26,7 +26,7 @@ public class ForgeLoginWrapperDecoder extends MessageToMessageDecoder<LoginPlugi
String channel = ProtocolUtils.readString(buf); String channel = ProtocolUtils.readString(buf);
if (!channel.equals("fml:handshake")) { if (!channel.equals("fml:handshake")) {
buf.readerIndex(originalReaderIndex); buf.readerIndex(originalReaderIndex);
out.add(new GenericForgeLoginWrapperPacket(buf.retain(), msg.getId())); out.add(new GenericForgeLoginWrapperPacket(buf.retain(), msg.getId(), true));
return; return;
} }
int length = ProtocolUtils.readVarInt(buf); int length = ProtocolUtils.readVarInt(buf);
@ -35,7 +35,7 @@ public class ForgeLoginWrapperDecoder extends MessageToMessageDecoder<LoginPlugi
out.add(ModListReplyPacket.read(msg)); out.add(ModListReplyPacket.read(msg));
} else { } else {
buf.readerIndex(originalReaderIndex); buf.readerIndex(originalReaderIndex);
out.add(new GenericForgeLoginWrapperPacket(buf.retain(), msg.getId())); out.add(new GenericForgeLoginWrapperPacket(buf.retain(), msg.getId(), true));
} }
} }

View File

@ -51,30 +51,24 @@ public class ForgeLoginSessionHandler implements MinecraftSessionHandler {
if ((serverConnection.getPhase() instanceof VelocityForgeBackendConnectionPhase phase)) { if ((serverConnection.getPhase() instanceof VelocityForgeBackendConnectionPhase phase)) {
phase.onLoginSuccess(serverConnection,serverConnection.getPlayer()); phase.onLoginSuccess(serverConnection,serverConnection.getPlayer());
} }
ConnectedPlayer player = serverConnection.getPlayer();
if (player.getConnectedServer() != null && player.getConnectedServer().getConnection().getType() instanceof ForgeFMLConnectionType) {
//Forge -> vanilla
//Has not already been reset
//Not for Vanilla -> Vanilla
player.getPhase().resetConnectionPhase(player);
} else if (player.getConnection().getState() == StateRegistry.LOGIN) {
//Initial vanilla
//Vanilla -> Forge
//Forge -> Forge
MinecraftConnection connection = player.getConnection();
((OutboundSuccessHolder) connection.getChannel().pipeline().get(ForgeConstants.SERVER_SUCCESS_LISTENER))
.sendPacket();
connection.setState(StateRegistry.PLAY);
connection.getChannel().pipeline().remove(ForgeConstants.PLUGIN_PACKET_QUEUE);
((VelocityServer) Ambassador.getInstance().server).registerConnection(player);
}
original.handle(packet); original.handle(packet);
if (serverConnection.getConnection() == null) {
return true;
}
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
serverConnection.getConnection().setSessionHandler( //Send empty Mod list
new ForgePlaySessionHandler((TransitionSessionHandler) serverConnection player.getConnectionInFlight().getConnection().getChannel().config().setAutoRead(false);
.getConnection().getSessionHandler(),serverConnection)); }
} else {
//TODO: Read modlist
((VelocityForgeClientConnectionPhase) player.getPhase()).complete(player, true);
}
return true; return true;
} }

View File

@ -20,7 +20,7 @@ public class ForgePlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public boolean handle(JoinGame packet) { public boolean handle(JoinGame packet) {
if (serverConnection.getPlayer().getPhase() instanceof VelocityForgeClientConnectionPhase clientPhase) { if (serverConnection.getPlayer().getPhase() instanceof VelocityForgeClientConnectionPhase clientPhase) {
serverConnection.getPlayer().setPhase(VelocityForgeClientConnectionPhase.COMPLETE); serverConnection.getPlayer().setPhase(VelocityForgeClientConnectionPhase.RESETTABLE);
} }
return MinecraftSessionHandler.super.handle(packet); return MinecraftSessionHandler.super.handle(packet);
} }

View File

@ -1,48 +1,49 @@
package org.adde0109.ambassador.velocity.client; package org.adde0109.ambassador.velocity.client;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder; import io.netty.channel.*;
import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder;
import io.netty.channel.*;
import io.netty.handler.codec.EncoderException; public class ClientPacketQueue extends ChannelOutboundHandlerAdapter {
import io.netty.util.ReferenceCountUtil;
private PendingWriteQueue queue;
private final StateRegistry registry;
public class PluginLoginPacketQueue extends ChannelOutboundHandlerAdapter {
public ClientPacketQueue(StateRegistry registry) {
private PendingWriteQueue queue; this.registry = registry;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception { @Override
queue = new PendingWriteQueue(ctx); public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
} queue = new PendingWriteQueue(ctx);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { @Override
MinecraftConnection connection = ctx.pipeline().get(MinecraftConnection.class); public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (connection.getState() == StateRegistry.LOGIN && msg instanceof MinecraftPacket packet) { MinecraftConnection connection = ctx.pipeline().get(MinecraftConnection.class);
try { if (msg instanceof MinecraftPacket packet) {
StateRegistry.LOGIN.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND , try {
connection.getProtocolVersion()).getPacketId(packet); registry.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND ,
ctx.write(msg,promise); connection.getProtocolVersion()).getPacketId(packet);
} catch (IllegalArgumentException e) { queue.add(msg,promise);
queue.add(msg, promise); } catch (IllegalArgumentException e) {
} ctx.write(msg, promise);
} else { }
ctx.write(msg,promise); } else {
} ctx.write(msg,promise);
} }
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { @Override
if (ctx.channel().isActive()) { public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
queue.removeAndWriteAll(); if (ctx.channel().isActive()) {
ctx.flush(); queue.removeAndWriteAll();
} else { ctx.flush();
queue.removeAndFailAll(new ChannelException()); } else {
} queue.removeAndFailAll(new ChannelException());
} }
} }
}

View File

@ -1,9 +1,8 @@
package org.adde0109.ambassador.velocity.client; package org.adde0109.ambassador.velocity.client;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import org.adde0109.ambassador.forge.packet.GenericForgeLoginWrapperPacket; import org.adde0109.ambassador.forge.packet.GenericForgeLoginWrapperPacket;
@ -25,9 +24,9 @@ public class FML2CRPMResetCompleteDecoder extends ChannelInboundHandlerAdapter {
try { try {
int id = ProtocolUtils.readVarInt(buf); int id = ProtocolUtils.readVarInt(buf);
boolean success = buf.readBoolean(); boolean success = buf.readBoolean();
if (id == 98) { if (id == 80) {
try { try {
IForgeLoginWrapperPacket packet = new GenericForgeLoginWrapperPacket(buf, id); IForgeLoginWrapperPacket packet = new GenericForgeLoginWrapperPacket(Unpooled.EMPTY_BUFFER, id, success);
ctx.fireChannelRead(packet); ctx.fireChannelRead(packet);
} finally { } finally {
buf.release(); buf.release();

View File

@ -30,12 +30,12 @@ public class VelocityHandshakeSessionHandler implements MinecraftSessionHandler
case "FML2": case "FML2":
connection.setType(ForgeConstants.ForgeFML2); 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.SERVER_SUCCESS_LISTENER, new OutboundSuccessHolder());
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new PluginLoginPacketQueue()); connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.PLAY));
break; break;
case "FML3": case "FML3":
connection.setType(ForgeConstants.ForgeFML3); 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.SERVER_SUCCESS_LISTENER, new OutboundSuccessHolder());
connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new PluginLoginPacketQueue()); connection.getChannel().pipeline().addAfter(Connections.MINECRAFT_ENCODER,ForgeConstants.PLUGIN_PACKET_QUEUE, new ClientPacketQueue(StateRegistry.PLAY));
break; break;
} }
} }