Recoded client phases and fixed FORGE - FORGE switch

This commit is contained in:
Adrian Bergqvist 2024-02-01 15:47:00 +01:00
parent 550328863a
commit 6dfbdecfaf
No known key found for this signature in database
GPG Key ID: 3B3DA43224B79417
6 changed files with 79 additions and 71 deletions

View File

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

View File

@ -42,7 +42,7 @@ import java.util.concurrent.TimeUnit;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19;
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet;
@Plugin(id = "ambassador", name = "Ambassador", version = "1.4.3-beta", authors = {"adde0109"})
@Plugin(id = "ambassador", name = "Ambassador", version = "1.5.0-beta", authors = {"adde0109"})
public class Ambassador {
//Don't forget to update checkCompatibleVersion() when changing this value

View File

@ -6,10 +6,8 @@ import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.network.Connections;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import org.adde0109.ambassador.Ambassador;
import org.adde0109.ambassador.forge.packet.*;
@ -69,32 +67,13 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
server.setConnectionPhase(newPhase);
if (player.getPhase() == VelocityForgeClientConnectionPhase.NOT_STARTED ||
player.getPhase() == VelocityForgeClientConnectionPhase.IN_PROGRESS) {
//Initial Forge
player.getConnection().write(message);
return;
}
//Forge -> Forge
//Reset client if not ready to receive new handshake
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
if (clientPhase.getResetType() == VelocityForgeClientConnectionPhase.clientResetType.CRP ||
clientPhase.getResetType() == VelocityForgeClientConnectionPhase.clientResetType.SR) {
clientPhase.resetConnectionPhase(player);
player.getConnection().write(message);
return;
}
//STILL WIP
if (!Ambassador.getInstance().config.isDebugMode()) {
server.disconnect();
return;
}
if (clientPhase.getResetType() == VelocityForgeClientConnectionPhase.clientResetType.NONE) {
if (!clientPhase.consideredComplete()) {
//Initial Forge
if (message instanceof ModListPacket modListPacket) {
clientPhase.forgeHandshake = new ForgeHandshake();
}
@ -103,6 +82,14 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
}
player.getConnection().write(message);
} else {
//Reset client if not ready to receive new handshake
if (clientPhase.getResetType() == VelocityForgeClientConnectionPhase.ClientResetType.CRP ||
clientPhase.getResetType() == VelocityForgeClientConnectionPhase.ClientResetType.SR) {
clientPhase.resetConnectionPhase(player);
player.getConnection().write(message);
return;
}
if (message instanceof ModListPacket modListPacket) {
remainingRegistries = new CountDownLatch(modListPacket.getRegistries().size());
@ -120,9 +107,9 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
}).thenAcceptAsync((v) -> {
if(Ambassador.getInstance().config.isDebugMode()) {
player.sendMessage(Component.text("Handshake took: " + (System.currentTimeMillis()-time)/1000 + " seconds"));
player.sendMessage(Component.text("Handshake took: " + (System.currentTimeMillis()-time) + " ms"));
player.sendMessage(Component.text("Avg packet time" +
((System.currentTimeMillis()-time)/1000)/modListPacket.getRegistries().size() + " seconds"));
(System.currentTimeMillis()-time)/modListPacket.getRegistries().size() + " ms"));
}
if (Ambassador.getInstance().config.isBypassRegistryCheck() ||

View File

@ -37,17 +37,12 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
public void complete(ConnectedPlayer player) {
//When no handshake has taken place.
//Test if the client supports CRP.
clientResetType.CRP.doReset(player);
}
@Override
public boolean consideredComplete() {
return true;
ClientResetType.CRP.doReset(player);
}
},
IN_PROGRESS {
},
WAITING_RESET {
WAITING_RESET() {
@Override
void onTransitionToNewPhase(ConnectedPlayer player) {
//We unregister so no plugin sees this client while the client is being reset.
@ -70,7 +65,7 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
if (!(server.getConnection().getType() instanceof ForgeFMLConnectionType)) {
// -> vanilla
complete(player, ((Context.ClientContext) msg.getContext()).success() ? clientResetType.CRP : clientResetType.UNKNOWN);
complete(player, ((Context.ClientContext) msg.getContext()).success() ? ClientResetType.CRP : null);
}
if (player.getConnectionInFlight() != null) {
@ -84,8 +79,15 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
}
},
COMPLETE {
private ClientResetType resetType = ClientResetType.UNKNOWN;
@Override
void onTransitionToNewPhase(ConnectedPlayer player) {
//Send Login Success to client
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
player.getConnection().getChannel().pipeline().remove(ForgeConstants.PLUGIN_PACKET_QUEUE);
((VelocityServer) Ambassador.getInstance().server).registerConnection(player);
@ -102,19 +104,29 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
}
@Override
public void complete(ConnectedPlayer player, clientResetType resetType) {
public void complete(ConnectedPlayer player) {
if (Ambassador.getInstance().config.isDebugMode()) {
player.sendMessage(Component.text("Forge -> Vanilla - Not resetting"));
player.sendMessage(Component.text("Not resetting"));
}
}
@Override
void setResetType(ConnectedPlayer player, ClientResetType resetType) {
this.resetType = resetType;
if (Ambassador.getInstance().config.isDebugMode()) {
player.sendMessage(Component.text("Reset type: " + this.resetType.toString()));
}
}
@Override
public ClientResetType getResetType() {
return resetType;
}
};
//TODO: Make a new class that's linked to each player with these fields instead of having them in this phase class
public ForgeHandshake forgeHandshake = new ForgeHandshake();
private clientResetType resetType = clientResetType.UNKNOWN;
public boolean handle(ConnectedPlayer player, IForgeLoginWrapperPacket<Context.ClientContext> msg, VelocityServerConnection server) {
if (msg instanceof ModListReplyPacket replyPacket) {
@ -137,47 +149,24 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
return true;
}
public void complete(ConnectedPlayer player) {
complete(player, getResetType(player));
complete(player, null);
}
public void complete(ConnectedPlayer player, clientResetType resetType) {
MinecraftConnection connection = player.getConnection();
//Send Login Success to client
((OutboundSuccessHolder) connection.getChannel().pipeline().get(ForgeConstants.SERVER_SUCCESS_LISTENER))
.sendPacket();
connection.setState(StateRegistry.PLAY);
public void complete(ConnectedPlayer player, ClientResetType resetType) {
//Change phase to COMPLETE
player.setPhase(COMPLETE);
COMPLETE.resetType = resetType;
COMPLETE.onTransitionToNewPhase(player);
COMPLETE.forgeHandshake = forgeHandshake;
if (resetType != null) {
COMPLETE.setResetType(player, resetType);
}
if (Ambassador.getInstance().config.isDebugMode()) {
player.sendMessage(Component.text("Forge handshake complete"));
player.sendMessage(Component.text("Reset type: " + resetType.toString()));
}
}
private clientResetType getResetType(ConnectedPlayer player) {
if (Ambassador.getInstance().config.isDebugMode()) {
player.sendMessage(Component.text("Scanning modlist for client reset mods"));
}
if (player.getModInfo().isPresent()) {
if (player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("clientresetpacket")))) {
return clientResetType.CRP;
} else if (Ambassador.getInstance().config.getServerSwitchCancellationTime() >= 0 &&
player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("serverredirect")
|| mod.getId().equals("srvredirect:red")))
&& player.getVirtualHost().isPresent()) {
return clientResetType.SR;
}
}
return clientResetType.NONE;
}
void onTransitionToNewPhase(ConnectedPlayer player) {
}
@ -191,10 +180,35 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
return false;
}
public clientResetType getResetType() {
return resetType;
public ClientResetType getResetType() {
return COMPLETE.getResetType();
}
enum clientResetType {
private ClientResetType getResetType(ConnectedPlayer player) {
if (Ambassador.getInstance().config.isDebugMode()) {
player.sendMessage(Component.text("Scanning modlist for client reset mods"));
}
if (player.getModInfo().isPresent()) {
if (player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("clientresetpacket")))) {
return ClientResetType.CRP;
} else if (Ambassador.getInstance().config.getServerSwitchCancellationTime() >= 0 &&
player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("serverredirect")
|| mod.getId().equals("srvredirect:red")))
&& player.getVirtualHost().isPresent()) {
return ClientResetType.SR;
}
}
return ClientResetType.NONE;
}
void setResetType(ConnectedPlayer player, ClientResetType resetType) {
COMPLETE.setResetType(player, resetType);
}
public void updateResetType(ConnectedPlayer player) {
COMPLETE.setResetType(player, getResetType(player));
}
public enum ClientResetType {
UNKNOWN,
NONE,
CRP {

View File

@ -71,6 +71,12 @@ public class VelocityEventHandler {
player.setModInfo(new ModInfo("Channels", event.getChannels().stream().map((id) -> {
return new ModInfo.Mod(id.getId(), "");
}).toList()));
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
//If reset typ is still unknown, set it!
if (clientPhase.getResetType() == VelocityForgeClientConnectionPhase.ClientResetType.UNKNOWN) {
clientPhase.updateResetType(player);
}
}
}

View File

@ -37,7 +37,8 @@ public class ForgeLoginSessionHandler implements MinecraftSessionHandler {
if (serverConnection.getConnection() != null) {
ConnectedPlayer player = serverConnection.getPlayer();
((VelocityForgeClientConnectionPhase) player.getPhase()).complete(player);
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
clientPhase.complete(player);
}
return true;