Skip to content

Commit

Permalink
Restructure connecting code and mixins
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianMichael committed Apr 30, 2024
1 parent d325b06 commit 9f1a2e2
Show file tree
Hide file tree
Showing 39 changed files with 388 additions and 419 deletions.
29 changes: 18 additions & 11 deletions src/main/java/de/florianmichael/viaforge/common/ViaForgeCommon.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import de.florianmichael.viaforge.common.protocoltranslator.netty.VFNetworkManager;
import de.florianmichael.viaforge.common.protocoltranslator.netty.ViaForgeVLLegacyPipeline;
import io.netty.channel.Channel;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.AttributeKey;
import net.raphimc.vialoader.ViaLoader;
import net.raphimc.vialoader.impl.platform.*;
Expand All @@ -50,6 +49,7 @@ public class ViaForgeCommon {

private final VFPlatform platform;
private ProtocolVersion targetVersion;
private ProtocolVersion previousVersion;

private ViaForgeConfig config;

Expand Down Expand Up @@ -89,19 +89,22 @@ public static void init(final VFPlatform platform) {
* @param channel the channel to inject the pipeline into
*/
public void inject(final Channel channel, final VFNetworkManager networkManager) {
if (channel instanceof SocketChannel) {
if (targetVersion.equals(getNativeVersion())) {
return; // Don't inject ViaVersion into pipeline if there is nothing to translate anyway
}
channel.attr(VF_NETWORK_MANAGER).set(networkManager);
if (networkManager.viaForge$getTrackedVersion().equals(getNativeVersion())) {
return; // Don't inject ViaVersion into pipeline if there is nothing to translate anyway
}
channel.attr(VF_NETWORK_MANAGER).set(networkManager);

final UserConnection user = new UserConnectionImpl(channel, true);
new ProtocolPipelineImpl(user);
final UserConnection user = new UserConnectionImpl(channel, true);
new ProtocolPipelineImpl(user);

channel.attr(LOCAL_VIA_USER).set(user);
channel.attr(LOCAL_VIA_USER).set(user);

channel.pipeline().addLast(new ViaForgeVLLegacyPipeline(user, targetVersion));
}
channel.pipeline().addLast(new ViaForgeVLLegacyPipeline(user, targetVersion));
channel.closeFuture().addListener(future -> {
if (previousVersion != null) {
restoreVersion();
}
});
}

/**
Expand All @@ -128,7 +131,11 @@ public void restoreVersion() {
}

public void setTargetVersionSilent(final ProtocolVersion targetVersion) {
final ProtocolVersion oldVersion = this.targetVersion;
this.targetVersion = targetVersion;
if (oldVersion != targetVersion) {
previousVersion = oldVersion;
}
}

public void setTargetVersion(final ProtocolVersion targetVersion) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package de.florianmichael.viaforge.common.platform;

import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viaforge.common.ViaForgeCommon;

import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

/**
* Dirty, but needed to store the server specific version until building the netty pipeline.
*/
public class VersionTracker {

public static final Map<InetAddress, ProtocolVersion> SERVER_PROTOCOL_VERSIONS = new HashMap<>();

public static void storeServerProtocolVersion(InetAddress address, ProtocolVersion version) {
SERVER_PROTOCOL_VERSIONS.put(address, version);
ViaForgeCommon.getManager().setTargetVersionSilent(version);
}

public static ProtocolVersion getServerProtocolVersion(InetAddress address) {
return SERVER_PROTOCOL_VERSIONS.remove(address);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package de.florianmichael.viaforge.mixin.impl;
package de.florianmichael.viaforge.mixin.impl.connect;

import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
import de.florianmichael.viaforge.common.platform.VersionTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.network.NetworkManager;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.net.InetAddress;
import java.net.UnknownHostException;

@Mixin(targets = "net.minecraft.client.multiplayer.GuiConnecting$1")
public class MixinGuiConnecting_1 {

@Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;createNetworkManagerAndConnect(Ljava/net/InetAddress;IZ)Lnet/minecraft/network/NetworkManager;"))
public NetworkManager trackVersion(InetAddress address, int i, boolean b) {
// We need to track the version of the server we are connecting to, so we can later
// use it to determine the protocol version to use.
// We hope that the current server data is not null
if (Minecraft.getMinecraft().getCurrentServerData() instanceof ExtendedServerData) {
final ProtocolVersion version = ((ExtendedServerData) Minecraft.getMinecraft().getCurrentServerData()).viaForge$getVersion();
if (version != null) {
ViaForgeCommon.getManager().setTargetVersionSilent(version);
} else {
// If the server data does not contain a version, we need to restore the version
// we had before, so we don't use the wrong version.
ViaForgeCommon.getManager().restoreVersion();
}
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Ljava/net/InetAddress;getByName(Ljava/lang/String;)Ljava/net/InetAddress;"))
public InetAddress trackServerVersion(String s) throws UnknownHostException {
final InetAddress address = InetAddress.getByName(s);
ProtocolVersion version = ((ExtendedServerData) Minecraft.getMinecraft().getCurrentServerData()).viaForge$getVersion();
if (version == null) {
version = ViaForgeCommon.getManager().getTargetVersion();
}

return NetworkManager.createNetworkManagerAndConnect(address, i, b);
VersionTracker.storeServerProtocolVersion(address, version);
return address;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package de.florianmichael.viaforge.mixin.impl;
package de.florianmichael.viaforge.mixin.impl.connect;

import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.protocoltranslator.netty.VFNetworkManager;
import net.minecraft.client.network.NetHandlerLoginClient;
import net.minecraft.network.NetworkManager;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.ProtocolMetadataStorage;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
Expand All @@ -42,7 +42,8 @@ public class MixinNetHandlerLoginClient {

@Redirect(method = "handleEncryptionRequest", at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/minecraft/MinecraftSessionService;joinServer(Lcom/mojang/authlib/GameProfile;Ljava/lang/String;Ljava/lang/String;)V"))
public void onlyJoinServerIfPremium(MinecraftSessionService instance, GameProfile profile, String authenticationToken, String serverId) throws AuthenticationException {
if (ViaForgeCommon.getManager().getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
final VFNetworkManager mixinNetworkManager = (VFNetworkManager) networkManager;
if (mixinNetworkManager.viaForge$getTrackedVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
final UserConnection user = networkManager.channel().attr(ViaForgeCommon.LOCAL_VIA_USER).get();
if (user != null && user.has(ProtocolMetadataStorage.class) && !user.get(ProtocolMetadataStorage.class).authenticate) {
// We are in the 1.7 -> 1.6 protocol, so we need to skip the joinServer call
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package de.florianmichael.viaforge.mixin.impl;
package de.florianmichael.viaforge.mixin.impl.connect;

import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.platform.VersionTracker;
import de.florianmichael.viaforge.common.protocoltranslator.netty.VFNetworkManager;
import io.netty.channel.Channel;
import net.minecraft.network.NettyEncryptingDecoder;
import net.minecraft.network.NettyEncryptingEncoder;
import net.minecraft.network.NetworkManager;
import net.minecraft.util.CryptManager;
import net.minecraft.util.LazyLoadBase;
import net.minecraft.util.text.ITextComponent;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialoader.netty.VLLegacyPipeline;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
Expand All @@ -48,46 +48,39 @@ public class MixinNetworkManager implements VFNetworkManager {

@Shadow private Channel channel;

@Shadow private boolean isEncrypted;
@Unique
private Cipher viaForge$decryptionCipher;

@Unique
private ProtocolVersion viaForge$targetVersion;

@Inject(method = "createNetworkManagerAndConnect", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;group(Lio/netty/channel/EventLoopGroup;)Lio/netty/bootstrap/AbstractBootstrap;"), locals = LocalCapture.CAPTURE_FAILHARD)
private static void trackSelfTarget(InetAddress address, int serverPort, boolean useNativeTransport, CallbackInfoReturnable<NetworkManager> cir, NetworkManager networkmanager, Class oclass, LazyLoadBase lazyloadbase) {
// The connecting screen and server pinger are setting the main target version when a specific version for a server is set,
// This works for joining perfect since we can simply restore the version when the server doesn't have a specific one set,
// but for the server pinger we need to store the target version and force the pinging to use the target version.
// Due to the fact that the server pinger is being called multiple times.
((VFNetworkManager) networkmanager).viaForge$setTrackedVersion(ViaForgeCommon.getManager().getTargetVersion());
@Inject(method = "setCompressionThreshold", at = @At("RETURN"))
public void reorderPipeline(int p_setCompressionTreshold_1_, CallbackInfo ci) {
ViaForgeCommon.getManager().reorderCompression(channel);
}

@Inject(method = "enableEncryption", at = @At("HEAD"), cancellable = true)
private void storeEncryptionCiphers(SecretKey key, CallbackInfo ci) {
if (ViaForgeCommon.getManager().getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
if (viaForge$targetVersion != null && viaForge$targetVersion.olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
// Minecraft's encryption code is bad for us, we need to reorder the pipeline
ci.cancel();

// Minecraft 1.6.4 supports tile encryption which means the server can only disable one side of the encryption
// Minecraft 1.6.4 supports tile encryption which means the server can only enable one side of the encryption
// So we only enable the encryption side and later enable the decryption side if the 1.7 -> 1.6 protocol
// tells us to do, therefore we need to store the cipher instance.
this.viaForge$decryptionCipher = CryptManager.createNetCipherInstance(2, key);

// Enabling the encryption side
this.isEncrypted = true;
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new NettyEncryptingEncoder(CryptManager.createNetCipherInstance(1, key)));
}
}

@Inject(method = "closeChannel", at = @At("HEAD"))
public void restoreTargetVersion(ITextComponent message, CallbackInfo ci) {
// If the previous server forced a version, we need to restore the version to the default one.
ViaForgeCommon.getManager().restoreVersion();
}

@Inject(method = "setCompressionThreshold", at = @At("RETURN"))
public void reorderPipeline(int p_setCompressionTreshold_1_, CallbackInfo ci) {
ViaForgeCommon.getManager().reorderCompression(channel);
@Inject(method = "createNetworkManagerAndConnect", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;group(Lio/netty/channel/EventLoopGroup;)Lio/netty/bootstrap/AbstractBootstrap;"), locals = LocalCapture.CAPTURE_FAILHARD)
private static void setTargetVersion(InetAddress address, int serverPort, boolean useNativeTransport, CallbackInfoReturnable<NetworkManager> cir, NetworkManager networkmanager, Class oclass, LazyLoadBase lazyloadbase) {
final VFNetworkManager mixinNetworkManager = (VFNetworkManager) networkmanager;
mixinNetworkManager.viaForge$setTrackedVersion(VersionTracker.getServerProtocolVersion(address));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package de.florianmichael.viaforge.mixin.impl;
package de.florianmichael.viaforge.mixin.impl.connect;

import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.protocoltranslator.netty.VFNetworkManager;
Expand All @@ -35,7 +35,7 @@ public class MixinNetworkManager_5 {
NetworkManager val$networkmanager;

@Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false)
private void onInitChannel(Channel channel, CallbackInfo ci) {
private void hookViaPipeline(Channel channel, CallbackInfo ci) {
ViaForgeCommon.getManager().inject(channel, (VFNetworkManager) val$networkmanager);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package de.florianmichael.viaforge.mixin.impl;
package de.florianmichael.viaforge.mixin.impl.connect;

import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
import de.florianmichael.viaforge.common.platform.VersionTracker;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.network.ServerPinger;
import net.minecraft.network.NetworkManager;
Expand All @@ -46,22 +47,12 @@ public void trackServerData(ServerData server, CallbackInfo ci) {

@Redirect(method = "ping", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;createNetworkManagerAndConnect(Ljava/net/InetAddress;IZ)Lnet/minecraft/network/NetworkManager;"))
public NetworkManager trackVersion(InetAddress address, int i, boolean b) {
// We need to track the version of the server we are connecting to, so we can later
// use it to determine the protocol version to use.
// We hope that the current server data is not null

if (viaForge$serverData instanceof ExtendedServerData) {
final ProtocolVersion version = ((ExtendedServerData) viaForge$serverData).viaForge$getVersion();
if (version != null) {
ViaForgeCommon.getManager().setTargetVersionSilent(version);
} else {
// If the server data does not contain a version, we need to restore the version
// we had before, so we don't use the wrong version.
ViaForgeCommon.getManager().restoreVersion();
}

viaForge$serverData = null;
ProtocolVersion version = ((ExtendedServerData) viaForge$serverData).viaForge$getVersion();
if (version == null) {
version = ViaForgeCommon.getManager().getTargetVersion();
}
VersionTracker.storeServerProtocolVersion(address, version);
viaForge$serverData = null;

return NetworkManager.createNetworkManagerAndConnect(address, i, b);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public MixinEntityPlayerSP(World worldIn, GameProfile playerProfile) {

@Redirect(method = "onUpdateWalkingPlayer", at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/EntityPlayerSP;prevOnGround:Z", ordinal = 0))
public boolean emulateIdlePacket(EntityPlayerSP instance) {
System.out.println(ViaForgeCommon.getManager().getTargetVersion());
if (ViaForgeCommon.getManager().getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
// <= 1.8 spams the idle packet instead of only sending it when the ground state changes
// So we invert the original logic:
Expand Down
10 changes: 5 additions & 5 deletions viaforge-mc1122/src/main/resources/mixins.viaforge-mc1122.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"package": "de.florianmichael.viaforge.mixin.impl",
"refmap": "mixins.viaforge-mc1122.refmap.json",
"client": [
"MixinGuiConnecting_1",
"connect.MixinGuiConnecting_1",
"MixinGuiMainMenu",
"MixinGuiMultiplayer",
"MixinGuiOverlayDebug",
"MixinGuiScreenAddServer",
"MixinGuiScreenServerList",
"MixinNetHandlerLoginClient",
"MixinNetworkManager",
"MixinNetworkManager_5",
"connect.MixinNetHandlerLoginClient",
"connect.MixinNetworkManager",
"connect.MixinNetworkManager_5",
"MixinServerData",
"MixinServerPinger",
"connect.MixinServerPinger",
"fixes.MixinEntityPlayerSP"
],
"verbose": true
Expand Down
Loading

0 comments on commit 9f1a2e2

Please sign in to comment.