ViaLegacy/ViaAprilFools 😎

This commit is contained in:
FlorianMichael 2023-10-25 01:58:52 +02:00
parent 4b98412388
commit 2e09d167bf
No known key found for this signature in database
GPG Key ID: C2FB87E71C425126
18 changed files with 257 additions and 12 deletions

View File

@ -1,5 +1,5 @@
# ViaForge
Client-side Implementation of ViaVersion, ViaBackwards and ViaRewind for Legacy Minecraft Forge
Client-side Implementation of the Via* projects for Minecraft Forge
## Contact
If you encounter any issues, please report them on the

View File

@ -24,8 +24,11 @@ dependencies {
include "com.viaversion:viaversion:${project.viaversion_version}"
include "com.viaversion:viabackwards:${project.viabackwards_version}"
include "com.viaversion:viarewind-universal:${project.viarewind_version}"
include ("net.raphimc:ViaLegacy:${project.vialegacy_version}") {
exclude group: "com.google.code.gson", module: "gson"
}
include "net.raphimc:ViaAprilFools:${project.viaaprilfools_version}"
include "net.raphimc:ViaLoader:${project.vialoader_version}"
include "org.yaml:snakeyaml:${project.snake_yml_version}"
include "net.raphimc:ViaLoader:${project.vialoader_version}"
}

View File

@ -8,11 +8,12 @@ maven_version=3.5.0-SNAPSHOT
maven_group=de.florianmichael
# ViaVersion
vialoader_version=2.2.11-SNAPSHOT
viaversion_version=4.9.0-23w42a-SNAPSHOT
viabackwards_version=4.9.0-23w42a-SNAPSHOT
viarewind_version=3.0.3-SNAPSHOT
vialegacy_version=2.2.21-SNAPSHOT
viaaprilfools_version=2.0.10-SNAPSHOT
vialoader_version=2.2.11-SNAPSHOT
snake_yml_version=2.2

View File

@ -23,14 +23,14 @@ import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
import de.florianmichael.viaforge.common.platform.VFPlatform;
import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
import de.florianmichael.viaforge.common.protocolhack.ViaForgeVLInjector;
import de.florianmichael.viaforge.common.protocolhack.netty.IEncryptionSetup;
import de.florianmichael.viaforge.common.protocolhack.netty.ViaForgeVLLegacyPipeline;
import de.florianmichael.viaforge.common.protocolhack.ViaForgeVLLoader;
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.ViaBackwardsPlatformImpl;
import net.raphimc.vialoader.impl.platform.ViaRewindPlatformImpl;
import net.raphimc.vialoader.impl.platform.ViaVersionPlatformImpl;
import net.raphimc.vialoader.impl.platform.*;
import net.raphimc.vialoader.netty.CompressionReorderEvent;
import net.raphimc.vialoader.util.VersionEnum;
@ -41,6 +41,9 @@ import java.io.File;
* It is used to inject the ViaVersion pipeline into the netty pipeline. It also manages the target version.
*/
public class ViaForgeCommon {
public final static AttributeKey<UserConnection> LOCAL_VIA_USER = AttributeKey.valueOf("local_via_user");
public final static AttributeKey<IEncryptionSetup> ENCRYPTION_SETUP = AttributeKey.valueOf("encryption_setup");
private static ViaForgeCommon manager;
private final VFPlatform platform;
@ -70,7 +73,7 @@ public class ViaForgeCommon {
final File mainFolder = new File(platform.getLeadingDirectory(), "ViaForge");
ViaLoader.init(new ViaVersionPlatformImpl(mainFolder), new ViaForgeVLLoader(), new ViaForgeVLInjector(), null, ViaBackwardsPlatformImpl::new, ViaRewindPlatformImpl::new);
ViaLoader.init(new ViaVersionPlatformImpl(mainFolder), new ViaForgeVLLoader(platform), new ViaForgeVLInjector(), null, ViaBackwardsPlatformImpl::new, ViaRewindPlatformImpl::new, ViaLegacyPlatformImpl::new, ViaAprilFoolsPlatformImpl::new);
manager.config = new ViaForgeConfig(new File(mainFolder, "viaforge.yml"));
final VersionEnum configVersion = VersionEnum.fromProtocolId(manager.config.getClientSideVersion());
@ -91,6 +94,8 @@ public class ViaForgeCommon {
final UserConnection user = new UserConnectionImpl(channel, true);
new ProtocolPipelineImpl(user);
channel.attr(LOCAL_VIA_USER).set(user);
channel.pipeline().addLast(new ViaForgeVLLegacyPipeline(user, targetVersion));
}
}

View File

@ -17,6 +17,8 @@
*/
package de.florianmichael.viaforge.common.platform;
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.providers.GameProfileFetcher;
import java.io.File;
import java.util.function.Supplier;
@ -39,4 +41,16 @@ public interface VFPlatform {
* @return the leading directory of the platform
*/
File getLeadingDirectory();
/**
* Sends the joinServer API request to Mojang's authentication servers.
*
* @param serverId the server id of the server
*/
void joinServer(final String serverId) throws Throwable;
/**
* @return the game profile fetcher of the platform for ViaLegacy
*/
GameProfileFetcher getGameProfileFetcher();
}

View File

@ -15,6 +15,8 @@ public class ViaForgeConfig extends Config {
public final static String SHOW_MULTIPLAYER_BUTTON = "show-multiplayer-button";
public final static String SHOW_DIRECT_CONNECT_BUTTON = "show-direct-connect-button";
public final static String VERIFY_SESSION_IN_OLD_VERSIONS = "verify-session-in-old-versions";
/**
* @param configFile The location of where the config is loaded/saved.
*/
@ -62,4 +64,8 @@ public class ViaForgeConfig extends Config {
public boolean isShowDirectConnectButton() {
return getBoolean(SHOW_DIRECT_CONNECT_BUTTON, true);
}
public boolean isVerifySessionInOldVersions() {
return getBoolean(VERIFY_SESSION_IN_OLD_VERSIONS, true);
}
}

View File

@ -21,12 +21,24 @@ import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.version.VersionProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import de.florianmichael.viaforge.common.platform.VFPlatform;
import de.florianmichael.viaforge.common.protocolhack.provider.DummyMovementTransmitter;
import de.florianmichael.viaforge.common.protocolhack.provider.ViaForgeEncryptionProvider;
import de.florianmichael.viaforge.common.protocolhack.provider.ViaForgeOldAuthProvider;
import de.florianmichael.viaforge.common.protocolhack.provider.ViaForgeVersionProvider;
import net.raphimc.vialegacy.protocols.release.protocol1_3_1_2to1_2_4_5.providers.OldAuthProvider;
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.providers.EncryptionProvider;
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.providers.GameProfileFetcher;
import net.raphimc.vialoader.impl.viaversion.VLLoader;
public class ViaForgeVLLoader extends VLLoader {
private final VFPlatform platform;
public ViaForgeVLLoader(VFPlatform platform) {
this.platform = platform;
}
@Override
public void load() {
super.load();
@ -35,5 +47,8 @@ public class ViaForgeVLLoader extends VLLoader {
providers.use(VersionProvider.class, new ViaForgeVersionProvider());
providers.use(MovementTransmitterProvider.class, new DummyMovementTransmitter());
providers.use(OldAuthProvider.class, new ViaForgeOldAuthProvider());
providers.use(GameProfileFetcher.class, platform.getGameProfileFetcher());
providers.use(EncryptionProvider.class, new ViaForgeEncryptionProvider());
}
}

View File

@ -0,0 +1,10 @@
package de.florianmichael.viaforge.common.protocolhack.netty;
public interface IEncryptionSetup {
/**
* API method to setup the decryption side of the pipeline.
* This method is called by the {@link de.florianmichael.viaforge.common.protocolhack.provider.ViaForgeEncryptionProvider} class.
*/
void viaforge_setupPreNettyDecryption();
}

View File

@ -0,0 +1,13 @@
package de.florianmichael.viaforge.common.protocolhack.provider;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.providers.EncryptionProvider;
public class ViaForgeEncryptionProvider extends EncryptionProvider {
@Override
public void enableDecryption(UserConnection user) {
user.getChannel().attr(ViaForgeCommon.ENCRYPTION_SETUP).getAndRemove().viaforge_setupPreNettyDecryption();
}
}

View File

@ -0,0 +1,18 @@
package de.florianmichael.viaforge.common.protocolhack.provider;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import net.raphimc.vialegacy.protocols.release.protocol1_3_1_2to1_2_4_5.providers.OldAuthProvider;
public class ViaForgeOldAuthProvider extends OldAuthProvider {
@Override
public void sendAuthRequest(UserConnection user, String serverId) throws Throwable {
final ViaForgeCommon common = ViaForgeCommon.getManager();
if (!common.getConfig().isVerifySessionInOldVersions()) {
return;
}
common.getPlatform().joinServer(serverId);
}
}

View File

@ -13,5 +13,5 @@ displayURL="https://github.com/FlorianMichael"
credits="FlorianMichael/EnZaXD and all ViaVersion/ViaForge contributors"
authors="FlorianMichael/EnZaXD"
description='''
Client-side Implementation of ViaVersion, ViaBackwards and ViaRewind for Legacy Minecraft Forge
Client-side Implementation of the Via* projects for Minecraft Forge
'''

View File

@ -12,3 +12,6 @@ show-multiplayer-button: true
#
# This option indicates if the ViaForge button should be shown in the direct connect screen.
show-direct-connect-button: true
#
# Manually sends the joinServer request when connecting to <= 1.2.5 servers.
verify-session-in-old-versions: true

View File

@ -2,7 +2,7 @@
{
"modid": "viaforge",
"name": "ViaForge",
"description": "Client-side Implementation of ViaVersion, ViaBackwards and ViaRewind for Legacy Minecraft Forge",
"description": "Client-side Implementation of the Via* projects for Minecraft Forge",
"version": "${version}",
"mcversion": "[1.12.2]",
"url": "https://github.com/ViaVersion/ViaForge",

View File

@ -18,9 +18,12 @@
package de.florianmichael.viaforge;
import de.florianmichael.viaforge.common.platform.VFPlatform;
import de.florianmichael.viaforge.provider.ViaForgeGameProfileFetcher;
import net.minecraft.client.Minecraft;
import net.minecraft.realms.RealmsSharedConstants;
import net.minecraft.util.Session;
import net.minecraftforge.fml.common.Mod;
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.providers.GameProfileFetcher;
import java.io.File;
import java.util.function.Supplier;
@ -43,4 +46,16 @@ public class ViaForge112 implements VFPlatform {
public File getLeadingDirectory() {
return Minecraft.getMinecraft().gameDir;
}
@Override
public void joinServer(String serverId) throws Throwable {
final Session session = Minecraft.getMinecraft().getSession();
Minecraft.getMinecraft().getSessionService().joinServer(session.getProfile(), session.getToken(), serverId);
}
@Override
public GameProfileFetcher getGameProfileFetcher() {
return new ViaForgeGameProfileFetcher();
}
}

View File

@ -0,0 +1,37 @@
package de.florianmichael.viaforge.mixin.impl;
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 net.minecraft.client.network.NetHandlerLoginClient;
import net.minecraft.network.NetworkManager;
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.ProtocolMetadataStorage;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@SuppressWarnings("DataFlowIssue")
@Mixin(NetHandlerLoginClient.class)
public class MixinNetHandlerLoginClient {
@Shadow @Final private NetworkManager networkManager;
@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().isOlderThanOrEqualTo(VersionEnum.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
// if the server is in offline mode, due the packet changes <-> networking changes
// Minecraft's networking code is bad for us.
return;
}
}
instance.joinServer(profile, authenticationToken, serverId);
}
}

View File

@ -18,21 +18,68 @@
package de.florianmichael.viaforge.mixin.impl;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.protocolhack.netty.IEncryptionSetup;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import net.minecraft.network.NettyEncryptingDecoder;
import net.minecraft.network.NettyEncryptingEncoder;
import net.minecraft.network.NetworkManager;
import net.minecraft.util.CryptManager;
import net.raphimc.vialoader.netty.VLLegacyPipeline;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
@Mixin(NetworkManager.class)
public class MixinNetworkManager {
public class MixinNetworkManager implements IEncryptionSetup {
@Shadow private Channel channel;
@Unique
private Cipher viaforge_decryptionCipher;
@Inject(method = "channelActive", at = @At("RETURN"))
public void trackThisClass(ChannelHandlerContext p_channelActive_1_, CallbackInfo ci) {
// We need to access this class later to call the viaforge_setupPreNettyDecryption method.
// In one of the ViaLegacy's required providers, so we track this class instance as an own
// attribute in the connection and later access it from there and remove it.
// Counterpart in {@link java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeEncryptionProvider.java}
channel.attr(ViaForgeCommon.ENCRYPTION_SETUP).set(this);
}
@Inject(method = "enableEncryption", at = @At("HEAD"), cancellable = true)
private void storeEncryptionCiphers(SecretKey key, CallbackInfo ci) {
if (ViaForgeCommon.getManager().getTargetVersion().isOlderThanOrEqualTo(VersionEnum.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
// 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.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new NettyEncryptingEncoder(CryptManager.createNetCipherInstance(1, key)));
}
}
@Inject(method = "setCompressionThreshold", at = @At("RETURN"))
public void reorderPipeline(int p_setCompressionTreshold_1_, CallbackInfo ci) {
// When Minecraft enables compression, we need to reorder the pipeline
// to match the counterparts of via-decoder <-> encoder and via-encoder <-> encoder
ViaForgeCommon.getManager().reorderCompression(channel);
}
@Override
public void viaforge_setupPreNettyDecryption() {
// Enabling the decryption side for 1.6.4 if the 1.7 -> 1.6 protocol tells us to do
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "decrypt", new NettyEncryptingDecoder(this.viaforge_decryptionCipher));
}
}

View File

@ -0,0 +1,57 @@
package de.florianmichael.viaforge.provider;
import com.mojang.authlib.Agent;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.HttpAuthenticationService;
import com.mojang.authlib.ProfileLookupCallback;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.yggdrasil.ProfileNotFoundException;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.model.GameProfile;
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.providers.GameProfileFetcher;
import java.net.Proxy;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class ViaForgeGameProfileFetcher extends GameProfileFetcher {
public final static HttpAuthenticationService AUTHENTICATION_SERVICE = new YggdrasilAuthenticationService(Proxy.NO_PROXY, "");
public final static MinecraftSessionService SESSION_SERVICE = AUTHENTICATION_SERVICE.createMinecraftSessionService();
public final static GameProfileRepository GAME_PROFILE_REPOSITORY = AUTHENTICATION_SERVICE.createProfileRepository();
@Override
public UUID loadMojangUUID(String playerName) throws Exception {
final CompletableFuture<com.mojang.authlib.GameProfile> future = new CompletableFuture<>();
GAME_PROFILE_REPOSITORY.findProfilesByNames(new String[]{playerName}, Agent.MINECRAFT, new ProfileLookupCallback() {
@Override
public void onProfileLookupSucceeded(com.mojang.authlib.GameProfile profile) {
future.complete(profile);
}
@Override
public void onProfileLookupFailed(com.mojang.authlib.GameProfile profile, Exception exception) {
future.completeExceptionally(exception);
}
});
if (!future.isDone()) {
future.completeExceptionally(new ProfileNotFoundException());
}
return future.get().getId();
}
@Override
public GameProfile loadGameProfile(UUID uuid) throws Exception {
final com.mojang.authlib.GameProfile inProfile = new com.mojang.authlib.GameProfile(uuid, null);
final com.mojang.authlib.GameProfile mojangProfile = SESSION_SERVICE.fillProfileProperties(inProfile, true);
if (mojangProfile.equals(inProfile)) throw new ProfileNotFoundException();
final GameProfile gameProfile = new GameProfile(mojangProfile.getName(), mojangProfile.getId());
for (final java.util.Map.Entry<String, Property> entry : mojangProfile.getProperties().entries()) {
final Property prop = entry.getValue();
gameProfile.addProperty(new GameProfile.Property(prop.getName(), prop.getValue(), prop.getSignature()));
}
return gameProfile;
}
}

View File

@ -8,6 +8,7 @@
"MixinGuiMainMenu",
"MixinGuiMultiplayer",
"MixinGuiScreenServerList",
"MixinNetHandlerLoginClient",
"MixinNetworkManager",
"MixinNetworkManager_5",
"fixes.MixinEntityPlayerSP"