Changed reset mechanism
This commit is contained in:
parent
f1b1cc463c
commit
a0b38b7595
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<>();
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,17 @@ 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 com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder;
|
|
||||||
import io.netty.channel.*;
|
import io.netty.channel.*;
|
||||||
import io.netty.handler.codec.EncoderException;
|
|
||||||
import io.netty.util.ReferenceCountUtil;
|
|
||||||
|
|
||||||
|
|
||||||
public class PluginLoginPacketQueue extends ChannelOutboundHandlerAdapter {
|
public class ClientPacketQueue extends ChannelOutboundHandlerAdapter {
|
||||||
|
|
||||||
private PendingWriteQueue queue;
|
private PendingWriteQueue queue;
|
||||||
|
private final StateRegistry registry;
|
||||||
|
|
||||||
|
public ClientPacketQueue(StateRegistry registry) {
|
||||||
|
this.registry = registry;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
|
@ -23,13 +24,13 @@ public class PluginLoginPacketQueue extends ChannelOutboundHandlerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||||
MinecraftConnection connection = ctx.pipeline().get(MinecraftConnection.class);
|
MinecraftConnection connection = ctx.pipeline().get(MinecraftConnection.class);
|
||||||
if (connection.getState() == StateRegistry.LOGIN && msg instanceof MinecraftPacket packet) {
|
if (msg instanceof MinecraftPacket packet) {
|
||||||
try {
|
try {
|
||||||
StateRegistry.LOGIN.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND ,
|
registry.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND ,
|
||||||
connection.getProtocolVersion()).getPacketId(packet);
|
connection.getProtocolVersion()).getPacketId(packet);
|
||||||
ctx.write(msg,promise);
|
queue.add(msg,promise);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
queue.add(msg, promise);
|
ctx.write(msg, promise);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.write(msg,promise);
|
ctx.write(msg,promise);
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user