diff --git a/README.md b/README.md
index 15aee06..cddca07 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
-# ViaForge
-## For more information switch to the master branch
-Startup VM Options: -Dfml.coreMods.load=de.florianmichael.viaforge.mixin.MixinLoader
+# Legacy development branch for ViaForge 1.8
+
+Upstream changes are merged into this branch every release.
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 1353545..d13a1b7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -18,14 +18,15 @@ apply plugin: "net.minecraftforge.gradle.forge"
apply plugin: "org.spongepowered.mixin"
apply plugin: "com.github.johnrengelman.shadow"
apply plugin: "java"
+apply plugin: "idea"
-version = "1.8.9-${mod_version}"
-group = "${mod_base_package}.${mod_id}"
-archivesBaseName = mod_id
+version = "1.8.9-${maven_version}"
+group = "${maven_group}.${maven_name}"
+archivesBaseName = maven_name
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
-compileJava.options.encoding = 'UTF-8'
+compileJava.options.encoding = "UTF-8"
repositories {
mavenCentral()
@@ -54,51 +55,47 @@ configurations {
implementation.extendsFrom(include)
}
-def viaLibs = [
- "com.viaversion:viaversion:${project.viaversion_version}",
- "com.viaversion:viabackwards:${project.viabackwards_version}",
- "com.viaversion:viarewind-universal:${project.viarewind_version}",
- "org.yaml:snakeyaml:${project.snake_yml_version}",
-
- "net.raphimc:ViaLoader:${project.vialoader_version}",
- "org.slf4j:slf4j-api:${project.slf4j_version}"
-]
-
dependencies {
- compile ("org.spongepowered:mixin:0.7.10-SNAPSHOT") {
+ include compile ("org.spongepowered:mixin:${project.mixin_version}") {
exclude module: "launchwrapper"
}
- include "org.spongepowered:mixin:0.7.10-SNAPSHOT"
- for (final def via in viaLibs) {
- include(via)
+ 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.slf4j:slf4j-api:${project.slf4j_version}"
+ include "org.yaml:snakeyaml:${project.snake_yml_version}"
}
processResources {
inputs.property "version", project.version
- inputs.property "mcversion", project.minecraft.version
from(sourceSets.main.resources.srcDirs) {
- include 'mcmod.info'
+ include "mcmod.info"
- expand 'version':project.version, 'mcversion':project.minecraft.version
+ expand "version": project.version
}
from(sourceSets.main.resources.srcDirs) {
- exclude 'mcmod.info'
+ exclude "mcmod.info"
}
rename '(.+_at.cfg)', 'META-INF/$1'
}
mixin {
- add sourceSets.main, "mixins.${mod_id}.refmap.json"
+ add sourceSets.main, "mixins.${maven_name}-mc18.refmap.json"
}
jar {
manifest.attributes(
- "MixinConfigs": "mixins.viaforge.json",
+ "MixinConfigs": "mixins.${maven_name}-mc18.json",
"tweakClass": "org.spongepowered.asm.launch.MixinTweaker",
"TweakOrder": 0,
"FMLCorePluginContainsFMLMod": "de.florianmichael.viaforge.mixin.MixinLoader"
@@ -107,8 +104,6 @@ jar {
enabled = false
}
-apply plugin: "idea"
-
idea {
module {
inheritOutputDirs = true
@@ -117,17 +112,12 @@ idea {
shadowJar {
archiveName = jar.archiveName
- configurations = [project.configurations.include]
- compileJava.options.encoding = "UTF-8"
- exclude "native-binaries/*"
- exclude "META-INF/versions/**"
+ configurations = [project.configurations.include] // Include the dependencies from the include configuration
+ duplicatesStrategy DuplicatesStrategy.EXCLUDE
- dependencies {
- for (final def lib in viaLibs) {
- include(dependency(lib))
- }
- include(dependency("org.spongepowered:mixin:0.7.10-SNAPSHOT"))
- }
+ // Prevent conflicts with Forge's weird service loading
+ exclude("META-INF/maven/**")
+ exclude("META-INF/versions/**")
}
reobf {
diff --git a/gradle.properties b/gradle.properties
index ca3bcdd..320e621 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,20 +1,22 @@
-# java
-org.gradle.jvmargs=-Xmx3G
+# Gradle Properties
+org.gradle.jvmargs=-Xmx3G -XX:+UseG1GC
org.gradle.daemon=false
-# forge
-mod_id=viaforge
-mod_name=ViaForge
-mod_version=3.5.0-SNAPSHOT
-mod_base_package=de.florianmichael
+# Project Details
+maven_name=viaforge
+maven_version=3.5.0-SNAPSHOT
+maven_group=de.florianmichael
-# via-version
-vialoader_version=2.2.11-SNAPSHOT
-viaversion_version=4.9.0-23w42a-SNAPSHOT
-viabackwards_version=4.9.0-23w42a-SNAPSHOT
+# ViaVersion
+viaversion_version=4.9.0-1.20.3-rc1-SNAPSHOT
+viabackwards_version=4.9.0-1.20.3-rc1-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
-# libs
+# Misc Libraries
slf4j_version=2.0.7
-mixin_version=0.8.3
+mixin_version=0.7.10-SNAPSHOT
diff --git a/src/main/java/de/florianmichael/viaforge/ViaForge.java b/src/main/java/de/florianmichael/viaforge/ViaForge.java
deleted file mode 100644
index 1fbc27e..0000000
--- a/src/main/java/de/florianmichael/viaforge/ViaForge.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
- * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
- */
-package de.florianmichael.viaforge;
-
-import com.viaversion.viaversion.api.Via;
-import com.viaversion.viaversion.api.connection.UserConnection;
-import com.viaversion.viaversion.api.protocol.version.VersionProvider;
-import com.viaversion.viaversion.protocols.base.BaseVersionProvider;
-import net.minecraft.client.Minecraft;
-import net.raphimc.vialoader.ViaLoader;
-import net.raphimc.vialoader.impl.platform.ViaBackwardsPlatformImpl;
-import net.raphimc.vialoader.impl.platform.ViaRewindPlatformImpl;
-import net.raphimc.vialoader.impl.viaversion.VLInjector;
-import net.raphimc.vialoader.impl.viaversion.VLLoader;
-import net.raphimc.vialoader.netty.VLLegacyPipeline;
-import net.raphimc.vialoader.util.VersionEnum;
-
-public class ViaForge {
- public final static VersionEnum NATIVE_VERSION = VersionEnum.r1_8;
-
- public static VersionEnum targetVersion = VersionEnum.r1_8;
-
- public static void start() {
- VersionEnum.SORTED_VERSIONS.remove(VersionEnum.r1_7_6tor1_7_10);
- VersionEnum.SORTED_VERSIONS.remove(VersionEnum.r1_7_2tor1_7_5);
-
- ViaLoader.init(
- null,
- new VLLoader() {
- @Override
- public void load() {
- super.load();
- Via.getManager().getProviders().use(VersionProvider.class, new BaseVersionProvider() {
- @Override
- public int getClosestServerProtocol(UserConnection connection) throws Exception {
- if (connection.isClientSide() && !Minecraft.getMinecraft().isSingleplayer()) {
- return targetVersion.getVersion();
- }
- return super.getClosestServerProtocol(connection);
- }
- });
- }
- },
- new VLInjector() {
- @Override
- public String getDecoderName() {
- return VLLegacyPipeline.VIA_DECODER_NAME;
- }
-
- @Override
- public String getEncoderName() {
- return VLLegacyPipeline.VIA_ENCODER_NAME;
- }
- },
- null,
- ViaBackwardsPlatformImpl::new, ViaRewindPlatformImpl::new
- );
- }
-}
diff --git a/src/main/java/de/florianmichael/viaforge/ViaForge18.java b/src/main/java/de/florianmichael/viaforge/ViaForge18.java
new file mode 100644
index 0000000..3a5a2b5
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/ViaForge18.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+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;
+
+@Mod(modid = "viaforge")
+public class ViaForge18 implements VFPlatform {
+ public final static ViaForge18 PLATFORM = new ViaForge18();
+
+ @Override
+ public int getGameVersion() {
+ return RealmsSharedConstants.NETWORK_PROTOCOL_VERSION;
+ }
+
+ @Override
+ public Supplier isSingleplayer() {
+ return () -> Minecraft.getMinecraft().isSingleplayer();
+ }
+
+ @Override
+ public File getLeadingDirectory() {
+ return Minecraft.getMinecraft().mcDataDir;
+ }
+
+ @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();
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/ViaForgeCommon.java b/src/main/java/de/florianmichael/viaforge/common/ViaForgeCommon.java
new file mode 100644
index 0000000..4739071
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/ViaForgeCommon.java
@@ -0,0 +1,147 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.common;
+
+import com.viaversion.viaversion.api.connection.UserConnection;
+import com.viaversion.viaversion.connection.UserConnectionImpl;
+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.VFNetworkManager;
+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.*;
+import net.raphimc.vialoader.netty.CompressionReorderEvent;
+import net.raphimc.vialoader.util.VersionEnum;
+
+import java.io.File;
+
+/**
+ * This class is used to manage the common code between the different ViaForge versions.
+ * 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 LOCAL_VIA_USER = AttributeKey.valueOf("local_via_user");
+ public final static AttributeKey VF_NETWORK_MANAGER = AttributeKey.valueOf("encryption_setup");
+
+ private static ViaForgeCommon manager;
+
+ private final VFPlatform platform;
+ private VersionEnum targetVersion;
+
+ private ViaForgeConfig config;
+
+ public ViaForgeCommon(VFPlatform platform) {
+ this.platform = platform;
+ }
+
+ /**
+ * Initializes the manager.
+ *
+ * @param platform the platform fields
+ */
+ public static void init(final VFPlatform platform) {
+ if (manager != null) {
+ return; // Already initialized, ignore it then :tm:
+ }
+ final VersionEnum version = VersionEnum.fromProtocolId(platform.getGameVersion());
+ if (version == VersionEnum.UNKNOWN) {
+ throw new IllegalArgumentException("Unknown version " + platform.getGameVersion());
+ }
+
+ manager = new ViaForgeCommon(platform);
+
+ final File mainFolder = new File(platform.getLeadingDirectory(), "ViaForge");
+
+ 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());
+ if (configVersion != VersionEnum.UNKNOWN) {
+ manager.setTargetVersion(configVersion);
+ } else {
+ manager.setTargetVersion(version);
+ }
+ }
+
+ /**
+ * Injects the ViaVersion pipeline into the netty pipeline.
+ *
+ * @param channel the channel to inject the pipeline into
+ */
+ public void inject(final Channel channel, final VFNetworkManager networkManager) {
+ if (channel instanceof SocketChannel) {
+ final UserConnection user = new UserConnectionImpl(channel, true);
+ new ProtocolPipelineImpl(user);
+
+ channel.attr(LOCAL_VIA_USER).set(user);
+ channel.attr(VF_NETWORK_MANAGER).set(networkManager);
+
+ channel.pipeline().addLast(new ViaForgeVLLegacyPipeline(user, targetVersion));
+ }
+ }
+
+ /**
+ * Reorders the compression channel.
+ *
+ * @param channel the channel to reorder the compression for
+ */
+ public void reorderCompression(final Channel channel) {
+ // When Minecraft enables compression, we need to reorder the pipeline
+ // to match the counterparts of via-decoder <-> encoder and via-encoder <-> encoder
+ channel.pipeline().fireUserEventTriggered(CompressionReorderEvent.INSTANCE);
+ }
+
+ public VersionEnum getNativeVersion() {
+ return VersionEnum.fromProtocolId(platform.getGameVersion());
+ }
+
+ public VersionEnum getTargetVersion() {
+ return targetVersion;
+ }
+
+ public void restoreVersion() {
+ this.targetVersion = VersionEnum.fromProtocolId(config.getClientSideVersion());
+ }
+
+ public void setTargetVersionSilent(final VersionEnum targetVersion) {
+ this.targetVersion = targetVersion;
+ }
+
+ public void setTargetVersion(final VersionEnum targetVersion) {
+ this.targetVersion = targetVersion;
+ config.setClientSideVersion(targetVersion.getVersion());
+ }
+
+ public VFPlatform getPlatform() {
+ return platform;
+ }
+
+ public ViaForgeConfig getConfig() {
+ return config;
+ }
+
+ public static ViaForgeCommon getManager() {
+ return manager;
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/gui/ExtendedServerData.java b/src/main/java/de/florianmichael/viaforge/common/gui/ExtendedServerData.java
new file mode 100644
index 0000000..97ca061
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/gui/ExtendedServerData.java
@@ -0,0 +1,30 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.common.gui;
+
+import net.raphimc.vialoader.util.VersionEnum;
+
+/**
+ * This interface is used to store the target version for a specific server in the server list.
+ */
+public interface ExtendedServerData {
+
+ VersionEnum viaForge$getVersion();
+
+ void viaForge$setVersion(final VersionEnum version);
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/platform/VFPlatform.java b/src/main/java/de/florianmichael/viaforge/common/platform/VFPlatform.java
new file mode 100644
index 0000000..33a54b3
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/platform/VFPlatform.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.common.platform;
+
+import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.providers.GameProfileFetcher;
+import net.raphimc.vialoader.util.VersionEnum;
+
+import java.io.File;
+import java.util.function.Supplier;
+
+/**
+ * This interface is used to access platform specific fields.
+ */
+public interface VFPlatform {
+
+ /**
+ * @return the native version of the platform
+ */
+ int getGameVersion();
+
+ /**
+ * @return if the client is in singleplayer
+ */
+ Supplier isSingleplayer();
+
+ /**
+ * @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();
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/platform/ViaForgeConfig.java b/src/main/java/de/florianmichael/viaforge/common/platform/ViaForgeConfig.java
new file mode 100644
index 0000000..18dae76
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/platform/ViaForgeConfig.java
@@ -0,0 +1,122 @@
+package de.florianmichael.viaforge.common.platform;
+
+import com.viaversion.viaversion.util.Config;
+import com.viaversion.viaversion.util.Pair;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class ViaForgeConfig extends Config {
+ public final static String CLIENT_SIDE_VERSION = "client-side-version";
+ public final static String VERIFY_SESSION_IN_OLD_VERSIONS = "verify-session-in-old-versions";
+ public final static String ALLOW_BETACRAFT_AUTHENTICATION = "allow-betacraft-authentication";
+ public final static String SHOW_PROTOCOL_VERSION_IN_F3 = "show-protocol-version-in-f3";
+
+ public final static String SHOW_MAIN_MENU_BUTTON = "show-main-menu-button";
+ 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 SHOW_ADD_SERVER_BUTTON = "show-add-server-button";
+
+ public final static String VIA_FORGE_BUTTON_POSITION = "via-forge-button-position";
+ public final static String ADD_SERVER_SCREEN_BUTTON_POSITION = "add-server-screen-button-position";
+
+ /**
+ * @param configFile The location of where the config is loaded/saved.
+ */
+ public ViaForgeConfig(File configFile) {
+ super(configFile);
+ reload();
+ }
+
+ @Override
+ public URL getDefaultConfigURL() {
+ return getClass().getClassLoader().getResource("assets/viaforge/config.yml");
+ }
+
+ @Override
+ protected void handleConfig(Map config) {
+ }
+
+ @Override
+ public List getUnsupportedOptions() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void set(String path, Object value) {
+ super.set(path, value);
+ save(); // Automatically save the config when something changes
+ }
+
+ public int getClientSideVersion() {
+ return getInt(CLIENT_SIDE_VERSION, 0);
+ }
+
+ public void setClientSideVersion(final int version) {
+ set(CLIENT_SIDE_VERSION, version);
+ }
+
+ public boolean isVerifySessionInOldVersions() {
+ return getBoolean(VERIFY_SESSION_IN_OLD_VERSIONS, true);
+ }
+
+ public boolean isAllowBetacraftAuthentication() {
+ return getBoolean(ALLOW_BETACRAFT_AUTHENTICATION, true);
+ }
+
+ public boolean isShowProtocolVersionInF3() {
+ return getBoolean(SHOW_PROTOCOL_VERSION_IN_F3, true);
+ }
+
+ public boolean isShowMainMenuButton() {
+ return getBoolean(SHOW_MAIN_MENU_BUTTON, true);
+ }
+
+ public boolean isShowMultiplayerButton() {
+ return getBoolean(SHOW_MULTIPLAYER_BUTTON, true);
+ }
+
+ public boolean isShowDirectConnectButton() {
+ return getBoolean(SHOW_DIRECT_CONNECT_BUTTON, true);
+ }
+
+ public boolean isShowAddServerButton() {
+ return getBoolean(SHOW_ADD_SERVER_BUTTON, true);
+ }
+
+ public ButtonPosition getViaForgeButtonPosition() {
+ return ButtonPosition.valueOf(getString(VIA_FORGE_BUTTON_POSITION, ButtonPosition.TOP_LEFT.name()));
+ }
+
+ public ButtonPosition getAddServerScreenButtonPosition() {
+ return ButtonPosition.valueOf(getString(ADD_SERVER_SCREEN_BUTTON_POSITION, ButtonPosition.TOP_LEFT.name()));
+ }
+
+ public enum ButtonPosition {
+ // Button width: 100
+ // Button height: 20
+ // Button margin for both coordinates: 5
+ TOP_LEFT((width, height) -> new Pair<>(5, 5)),
+ TOP_RIGHT((width, height) -> new Pair<>(width - 100 - 5, 5)),
+ BOTTOM_LEFT((width, height) -> new Pair<>(5, height - 20 - 5)),
+ BOTTOM_RIGHT((width, height) -> new Pair<>(width - 100 - 5, height - 20 - 5));
+
+ private final PositionInvoker invoker;
+
+ ButtonPosition(final PositionInvoker invoker) {
+ this.invoker = invoker;
+ }
+
+ public Pair getPosition(int width, int height) {
+ return invoker.invoke(width, height);
+ }
+
+ public interface PositionInvoker {
+
+ Pair invoke(int width, int height);
+ }
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinMinecraft.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/ViaForgeVLInjector.java
similarity index 57%
rename from src/main/java/de/florianmichael/viaforge/mixin/impl/MixinMinecraft.java
rename to src/main/java/de/florianmichael/viaforge/common/protocolhack/ViaForgeVLInjector.java
index 0587739..fbb2ec4 100644
--- a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinMinecraft.java
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/ViaForgeVLInjector.java
@@ -15,21 +15,20 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package de.florianmichael.viaforge.mixin.impl;
+package de.florianmichael.viaforge.common.protocolhack;
-import de.florianmichael.viaforge.ViaForge;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.main.GameConfiguration;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import net.raphimc.vialoader.impl.viaversion.VLInjector;
+import net.raphimc.vialoader.netty.VLLegacyPipeline;
-@Mixin(Minecraft.class)
-public class MixinMinecraft {
+public class ViaForgeVLInjector extends VLInjector {
- @Inject(method = "", at = @At("RETURN"))
- public void startVia(GameConfiguration p_i45547_1_, CallbackInfo ci) {
- ViaForge.start();
+ @Override
+ public String getDecoderName() {
+ return VLLegacyPipeline.VIA_DECODER_NAME;
+ }
+
+ @Override
+ public String getEncoderName() {
+ return VLLegacyPipeline.VIA_ENCODER_NAME;
}
}
diff --git a/src/main/java/de/florianmichael/viaforge/common/protocolhack/ViaForgeVLLoader.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/ViaForgeVLLoader.java
new file mode 100644
index 0000000..ff75d21
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/ViaForgeVLLoader.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.common.protocolhack;
+
+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.*;
+import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicMPPassProvider;
+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();
+
+ final ViaProviders providers = Via.getManager().getProviders();
+
+ 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());
+ providers.use(ClassicMPPassProvider.class, new ViaForgeClassicMPPassProvider());
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/protocolhack/netty/VFNetworkManager.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/netty/VFNetworkManager.java
new file mode 100644
index 0000000..0ae8b54
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/netty/VFNetworkManager.java
@@ -0,0 +1,24 @@
+package de.florianmichael.viaforge.common.protocolhack.netty;
+
+import net.raphimc.vialoader.util.VersionEnum;
+
+public interface VFNetworkManager {
+
+ /**
+ * 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();
+
+ /**
+ * @return the target version of the connection
+ */
+ VersionEnum viaForge$getTrackedVersion();
+
+ /**
+ * Sets the target version of the connection.
+ *
+ * @param version the target version
+ */
+ void viaForge$setTrackedVersion(final VersionEnum version);
+}
diff --git a/src/main/java/de/florianmichael/viaforge/ViaForgeVLLegacyPipeline.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/netty/ViaForgeVLLegacyPipeline.java
similarity index 96%
rename from src/main/java/de/florianmichael/viaforge/ViaForgeVLLegacyPipeline.java
rename to src/main/java/de/florianmichael/viaforge/common/protocolhack/netty/ViaForgeVLLegacyPipeline.java
index b1a77f2..ea0427f 100644
--- a/src/main/java/de/florianmichael/viaforge/ViaForgeVLLegacyPipeline.java
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/netty/ViaForgeVLLegacyPipeline.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package de.florianmichael.viaforge;
+package de.florianmichael.viaforge.common.protocolhack.netty;
import com.viaversion.viaversion.api.connection.UserConnection;
import net.raphimc.vialoader.netty.VLLegacyPipeline;
diff --git a/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/DummyMovementTransmitter.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/DummyMovementTransmitter.java
new file mode 100644
index 0000000..e4e046e
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/DummyMovementTransmitter.java
@@ -0,0 +1,12 @@
+package de.florianmichael.viaforge.common.protocolhack.provider;
+
+import com.viaversion.viaversion.api.connection.UserConnection;
+import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
+
+public class DummyMovementTransmitter extends MovementTransmitterProvider {
+
+ @Override
+ public void sendPlayer(UserConnection userConnection) {
+ // We are on the client side, so we can handle the idle packet properly
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeClassicMPPassProvider.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeClassicMPPassProvider.java
new file mode 100644
index 0000000..4eac934
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeClassicMPPassProvider.java
@@ -0,0 +1,69 @@
+package de.florianmichael.viaforge.common.protocolhack.provider;
+
+import com.viaversion.viaversion.api.Via;
+import com.viaversion.viaversion.api.connection.UserConnection;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicMPPassProvider;
+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.storage.HandshakeStorage;
+
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.util.Formatter;
+import java.util.Scanner;
+import java.util.logging.Level;
+
+public class ViaForgeClassicMPPassProvider extends ClassicMPPassProvider {
+
+ @Override
+ public String getMpPass(UserConnection user) {
+ if (ViaForgeCommon.getManager().getConfig().isAllowBetacraftAuthentication()) {
+ final HandshakeStorage handshakeStorage = user.get(HandshakeStorage.class);
+
+ return getBetacraftMpPass(user, user.getProtocolInfo().getUsername(), handshakeStorage.getHostname(), handshakeStorage.getPort());
+ }
+ return super.getMpPass(user);
+ }
+
+ /*
+ Stolen from https://github.com/FlorianMichael/Classic4J/blob/main/src/main/java/de/florianmichael/classic4j/BetaCraftHandler.java :tm:
+ */
+
+ private static String getBetacraftMpPass(final UserConnection user, final String username, final String ip, final int port) {
+ try {
+ final String server = InetAddress.getByName(ip).getHostAddress() + ":" + port;
+
+ Via.getManager().getProviders().get(OldAuthProvider.class).sendAuthRequest(user, sha1(server.getBytes()));
+
+ final InputStream connection = new URL("https://api.betacraft.uk/getmppass.jsp?user=" + username + "&server=" + server).openStream();
+ Scanner scanner = new Scanner(connection);
+ StringBuilder response = new StringBuilder();
+ while (scanner.hasNext()) {
+ response.append(scanner.next());
+ }
+ connection.close();
+
+ if (response.toString().contains("FAILED") || response.toString().contains("SERVER NOT FOUND")) return "0";
+
+ return response.toString();
+ } catch (Throwable t) {
+ Via.getPlatform().getLogger().log(Level.WARNING, "An unknown error occurred while authenticating with BetaCraft", t);
+ return "0";
+ }
+ }
+
+ private static String sha1(final byte[] input) {
+ try {
+ Formatter formatter = new Formatter();
+ final byte[] hash = MessageDigest.getInstance("SHA-1").digest(input);
+ for (byte b : hash) {
+ formatter.format("%02x", b);
+ }
+ return formatter.toString();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeEncryptionProvider.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeEncryptionProvider.java
new file mode 100644
index 0000000..dc550a4
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeEncryptionProvider.java
@@ -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.VF_NETWORK_MANAGER).getAndRemove().viaForge$setupPreNettyDecryption();
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeOldAuthProvider.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeOldAuthProvider.java
new file mode 100644
index 0000000..a075758
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeOldAuthProvider.java
@@ -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);
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeVersionProvider.java b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeVersionProvider.java
new file mode 100644
index 0000000..ab650a1
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/common/protocolhack/provider/ViaForgeVersionProvider.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.common.protocolhack.provider;
+
+import com.viaversion.viaversion.api.connection.UserConnection;
+import com.viaversion.viaversion.protocols.base.BaseVersionProvider;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import net.raphimc.vialoader.util.VersionEnum;
+
+public class ViaForgeVersionProvider extends BaseVersionProvider {
+
+ @Override
+ public int getClosestServerProtocol(UserConnection connection) throws Exception {
+ if (connection.isClientSide() && !ViaForgeCommon.getManager().getPlatform().isSingleplayer().get()) {
+ try {
+ System.out.println(connection.getChannel().attr(ViaForgeCommon.VF_NETWORK_MANAGER).get());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return connection.getChannel().attr(ViaForgeCommon.VF_NETWORK_MANAGER).get().viaForge$getTrackedVersion().getVersion();
+ }
+
+ return super.getClosestServerProtocol(connection);
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/gui/GuiProtocolSelector.java b/src/main/java/de/florianmichael/viaforge/gui/GuiProtocolSelector.java
index e88a0f6..cbe6082 100644
--- a/src/main/java/de/florianmichael/viaforge/gui/GuiProtocolSelector.java
+++ b/src/main/java/de/florianmichael/viaforge/gui/GuiProtocolSelector.java
@@ -18,47 +18,85 @@
package de.florianmichael.viaforge.gui;
import com.mojang.realmsclient.gui.ChatFormatting;
-import de.florianmichael.viaforge.ViaForge;
+import com.viaversion.viaversion.api.Via;
+import com.viaversion.viaversion.util.DumpUtil;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiSlot;
import net.raphimc.vialoader.util.VersionEnum;
+import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import java.io.IOException;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
public class GuiProtocolSelector extends GuiScreen {
private final GuiScreen parent;
+ private final boolean simple;
+ private final FinishedCallback finishedCallback;
- public SlotList list;
+ private SlotList list;
- public GuiProtocolSelector(GuiScreen parent) {
+ private String status;
+ private long time;
+
+ public GuiProtocolSelector(final GuiScreen parent) {
+ this(parent, false, (version, unused) -> {
+ // Default action is to set the target version and go back to the parent screen.
+ ViaForgeCommon.getManager().setTargetVersion(version);
+ });
+ }
+
+ public GuiProtocolSelector(final GuiScreen parent, final boolean simple, final FinishedCallback finishedCallback) {
this.parent = parent;
+ this.simple = simple;
+ this.finishedCallback = finishedCallback;
}
@Override
public void initGui() {
super.initGui();
- buttonList.add(new GuiButton(1, width / 2 - 100, height - 27, 200,
- 20, "Back"));
+ buttonList.add(new GuiButton(1, 5, height - 25, 20, 20, "<-"));
+ if (!this.simple) {
+ buttonList.add(new GuiButton(2, width - 105, 5, 100, 20, "Create dump"));
+ buttonList.add(new GuiButton(3, width - 105, height - 25, 100, 20, "Reload configs"));
+ }
- list = new SlotList(mc, width, height, 32, height - 32, 10);
+ list = new SlotList(mc, width, height, 3 + 3 /* start offset */ + (fontRendererObj.FONT_HEIGHT + 2) * 3 /* title is 2 */, height - 30, fontRendererObj.FONT_HEIGHT + 2);
+ }
+
+ public void setStatus(final String status) {
+ this.status = status;
+ this.time = System.currentTimeMillis();
}
@Override
- protected void actionPerformed(GuiButton p_actionPerformed_1_) throws IOException {
- list.actionPerformed(p_actionPerformed_1_);
+ protected void actionPerformed(GuiButton button) {
+ list.actionPerformed(button);
- if (p_actionPerformed_1_.id == 1)
+ if (button.id == 1) {
mc.displayGuiScreen(parent);
+ } else if (button.id == 2) {
+ try {
+ GuiScreen.setClipboardString(DumpUtil.postDump(UUID.randomUUID()).get());
+ setStatus(ChatFormatting.GREEN + "Dump created and copied to clipboard");
+ } catch (InterruptedException | ExecutionException e) {
+ setStatus(ChatFormatting.RED + "Failed to create dump: " + e.getMessage());
+ }
+ } else {
+ Via.getManager().getConfigurationProvider().reloadConfigs();
+ }
}
@Override
- protected void keyTyped(char p_keyTyped_1_, int p_keyTyped_2_) throws IOException {
- if (p_keyTyped_2_ == 1) //esc key
- this.mc.displayGuiScreen(parent);
+ protected void keyTyped(char typedChar, int keyCode) {
+ if (keyCode == Keyboard.KEY_ESCAPE) {
+ mc.displayGuiScreen(parent);
+ }
}
@Override
@@ -68,24 +106,28 @@ public class GuiProtocolSelector extends GuiScreen {
}
@Override
- public void drawScreen(int p_drawScreen_1_, int p_drawScreen_2_, float p_drawScreen_3_) {
- list.drawScreen(p_drawScreen_1_, p_drawScreen_2_, p_drawScreen_3_);
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ if (System.currentTimeMillis() - this.time >= 10_000) {
+ this.status = null;
+ }
+
+ list.drawScreen(mouseX, mouseY, partialTicks);
GL11.glPushMatrix();
GL11.glScalef(2.0F, 2.0F, 2.0F);
- this.drawCenteredString(this.fontRendererObj, ChatFormatting.GOLD + "ViaForge", this.width / 4, 6, 16777215);
+ drawCenteredString(fontRendererObj, ChatFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
GL11.glPopMatrix();
- drawString(this.fontRendererObj, "https://github.com/FlorianMichael/ViaForge", 1, 1, -1);
- drawString(this.fontRendererObj, "Discord: EnZaXD#6257", 1, 11, -1);
+ drawCenteredString(fontRendererObj, "https://github.com/ViaVersion/ViaForge", width / 2, (fontRendererObj.FONT_HEIGHT + 2) * 2 + 3, -1);
+ drawString(fontRendererObj, status != null ? status : "Discord: florianmichael", 3, 3, -1);
- super.drawScreen(p_drawScreen_1_, p_drawScreen_2_, p_drawScreen_3_);
+ super.drawScreen(mouseX, mouseY, partialTicks);
}
class SlotList extends GuiSlot {
- public SlotList(Minecraft p_i1052_1_, int p_i1052_2_, int p_i1052_3_, int p_i1052_4_, int p_i1052_5_, int p_i1052_6_) {
- super(p_i1052_1_, p_i1052_2_, p_i1052_3_, p_i1052_4_, p_i1052_5_, p_i1052_6_);
+ public SlotList(Minecraft client, int width, int height, int top, int bottom, int slotHeight) {
+ super(client, width, height, top, bottom, slotHeight);
}
@Override
@@ -94,12 +136,12 @@ public class GuiProtocolSelector extends GuiScreen {
}
@Override
- protected void elementClicked(int i, boolean b, int i1, int i2) {
- ViaForge.targetVersion = VersionEnum.SORTED_VERSIONS.get(i);
+ protected void elementClicked(int index, boolean b, int i1, int i2) {
+ finishedCallback.finished(VersionEnum.SORTED_VERSIONS.get(index), parent);
}
@Override
- protected boolean isSelected(int i) {
+ protected boolean isSelected(int index) {
return false;
}
@@ -109,10 +151,23 @@ public class GuiProtocolSelector extends GuiScreen {
}
@Override
- protected void drawSlot(int i, int i1, int i2, int i3, int i4, int i5) {
- final VersionEnum version = VersionEnum.SORTED_VERSIONS.get(i);
+ protected void drawSlot(int index, int x, int y, int slotHeight, int mouseX, int mouseY) {
+ final VersionEnum targetVersion = ViaForgeCommon.getManager().getTargetVersion();
+ final VersionEnum version = VersionEnum.SORTED_VERSIONS.get(index);
- drawCenteredString(mc.fontRendererObj, (ViaForge.targetVersion.getVersion() == version.getVersion() ? ChatFormatting.GREEN.toString() : ChatFormatting.DARK_RED.toString()) + version.getName(), width / 2, i2, -1);
+ String color;
+ if (targetVersion == version) {
+ color = GuiProtocolSelector.this.simple ? ChatFormatting.GOLD.toString() : ChatFormatting.GREEN.toString();
+ } else {
+ color = GuiProtocolSelector.this.simple ? ChatFormatting.WHITE.toString() : ChatFormatting.DARK_RED.toString();
+ }
+
+ drawCenteredString(mc.fontRendererObj,(color) + version.getName(), width / 2, y, -1);
}
}
+
+ public interface FinishedCallback {
+
+ void finished(final VersionEnum version, final GuiScreen parent);
+ }
}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/MixinLoader.java b/src/main/java/de/florianmichael/viaforge/mixin/MixinLoader.java
index 215a971..6f4d644 100644
--- a/src/main/java/de/florianmichael/viaforge/mixin/MixinLoader.java
+++ b/src/main/java/de/florianmichael/viaforge/mixin/MixinLoader.java
@@ -27,9 +27,8 @@ import java.util.Map;
public class MixinLoader implements IFMLLoadingPlugin {
public MixinLoader() {
- System.out.println("Starting MixinBootstrap from IFMLLoadingPlugin");
MixinBootstrap.init();
- Mixins.addConfiguration("mixins.viaforge.json");
+ Mixins.addConfiguration("mixins.viaforge-mc18.json");
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
}
@@ -49,7 +48,8 @@ public class MixinLoader implements IFMLLoadingPlugin {
}
@Override
- public void injectData(Map data) { }
+ public void injectData(Map data) {
+ }
@Override
public String getAccessTransformerClass() {
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiConnecting_1.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiConnecting_1.java
new file mode 100644
index 0000000..8160438
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiConnecting_1.java
@@ -0,0 +1,35 @@
+package de.florianmichael.viaforge.mixin.impl;
+
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.gui.ExtendedServerData;
+import net.minecraft.client.Minecraft;
+import net.minecraft.network.NetworkManager;
+import net.raphimc.vialoader.util.VersionEnum;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+import java.net.InetAddress;
+
+@Mixin(targets = "net.minecraft.client.multiplayer.GuiConnecting$1")
+public class MixinGuiConnecting_1 {
+
+ @Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;func_181124_a(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 VersionEnum 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();
+ }
+ }
+
+ return NetworkManager.func_181124_a(address, i, b);
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMainMenuGuiMultiplayerGuiServerList.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMainMenu.java
similarity index 54%
rename from src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMainMenuGuiMultiplayerGuiServerList.java
rename to src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMainMenu.java
index 7cd1a25..d8be098 100644
--- a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMainMenuGuiMultiplayerGuiServerList.java
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMainMenu.java
@@ -17,6 +17,10 @@
*/
package de.florianmichael.viaforge.mixin.impl;
+import com.viaversion.viaversion.util.Pair;
+import de.florianmichael.viaforge.ViaForge18;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
import net.minecraft.client.gui.*;
import org.spongepowered.asm.mixin.Mixin;
@@ -24,20 +28,27 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-@Mixin(value = {
- GuiMainMenu.class, GuiMultiplayer.class, GuiScreenServerList.class
-})
-public class MixinGuiMainMenuGuiMultiplayerGuiServerList extends GuiScreen {
+@Mixin(GuiMainMenu.class)
+public class MixinGuiMainMenu extends GuiScreen {
@Inject(method = "initGui", at = @At("RETURN"))
- public void hookCustomButton(CallbackInfo ci) {
- buttonList.add(new GuiButton(1337, 5, 6, 98, 20, "ViaForge"));
+ public void hookViaForgeButton(CallbackInfo ci) {
+ ViaForgeCommon.init(ViaForge18.PLATFORM);
+
+ final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
+ if (config.isShowMainMenuButton()) {
+ final Pair pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
+
+ buttonList.add(new GuiButton(1_000_000_000, pos.key(), pos.value(), 100, 20, "ViaForge"));
+ }
}
@Inject(method = "actionPerformed", at = @At("RETURN"))
- public void handleCustomButtonAction(GuiButton p_actionPerformed_1_, CallbackInfo ci) {
- if (p_actionPerformed_1_.id == 1337) {
- mc.displayGuiScreen(new GuiProtocolSelector(this));
+ public void handleViaForgeButtonClicking(GuiButton p_actionPerformed_1_, CallbackInfo ci) {
+ if (ViaForgeCommon.getManager().getConfig().isShowMainMenuButton()) {
+ if (p_actionPerformed_1_.id == 1_000_000_000) {
+ mc.displayGuiScreen(new GuiProtocolSelector(this));
+ }
}
}
}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMultiplayer.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMultiplayer.java
new file mode 100644
index 0000000..c2d57d6
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiMultiplayer.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.mixin.impl;
+
+import com.viaversion.viaversion.util.Pair;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
+import de.florianmichael.viaforge.gui.GuiProtocolSelector;
+import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.GuiMultiplayer;
+import net.minecraft.client.gui.GuiScreen;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(GuiMultiplayer.class)
+public class MixinGuiMultiplayer extends GuiScreen {
+
+ @Inject(method = "initGui", at = @At("RETURN"))
+ public void hookViaForgeButton(CallbackInfo ci) {
+ final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
+ if (config.isShowMultiplayerButton()) {
+ final Pair pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
+
+ buttonList.add(new GuiButton(1_000_000_000, pos.key(), pos.value(), 100, 20, "ViaForge"));
+ }
+ }
+
+ @Inject(method = "actionPerformed", at = @At("RETURN"))
+ public void handleViaForgeButtonClicking(GuiButton p_actionPerformed_1_, CallbackInfo ci) {
+ if (ViaForgeCommon.getManager().getConfig().isShowMultiplayerButton()) {
+ if (p_actionPerformed_1_.id == 1_000_000_000) {
+ mc.displayGuiScreen(new GuiProtocolSelector(this));
+ }
+ }
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiOverlayDebug.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiOverlayDebug.java
new file mode 100644
index 0000000..da7ad59
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiOverlayDebug.java
@@ -0,0 +1,35 @@
+package de.florianmichael.viaforge.mixin.impl;
+
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import net.minecraft.client.gui.GuiOverlayDebug;
+import net.raphimc.vialegacy.api.LegacyProtocolVersion;
+import net.raphimc.vialoader.util.VersionEnum;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import java.util.List;
+
+@Mixin(GuiOverlayDebug.class)
+public class MixinGuiOverlayDebug {
+
+ @Inject(method = "getDebugInfoRight", at = @At(value = "TAIL"))
+ public void addViaForgeVersion(CallbackInfoReturnable> cir) {
+ final ViaForgeCommon common = ViaForgeCommon.getManager();
+ final VersionEnum version = ViaForgeCommon.getManager().getTargetVersion();
+
+ if (common.getConfig().isShowProtocolVersionInF3() && version != common.getNativeVersion() && !common.getPlatform().isSingleplayer().get()) {
+ cir.getReturnValue().add("");
+
+ int protocolVersion = version.getVersion();
+ if (version.isOlderThanOrEqualTo(VersionEnum.r1_6_4)) {
+ // Older versions (<= 1.6.4) are using fake ids in ViaLegacy to prevent version duplications / mismatches
+ // So we need to unmap the version to get the real protocol version id
+ protocolVersion = LegacyProtocolVersion.getRealProtocolVersion(protocolVersion);
+ }
+
+ cir.getReturnValue().add("ViaForge: " + version.getName() + " (" + protocolVersion + ")");
+ }
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiScreenAddServer.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiScreenAddServer.java
new file mode 100644
index 0000000..8de1b8d
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiScreenAddServer.java
@@ -0,0 +1,66 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.mixin.impl;
+
+import com.viaversion.viaversion.util.Pair;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.gui.ExtendedServerData;
+import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
+import de.florianmichael.viaforge.gui.GuiProtocolSelector;
+import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.GuiScreenAddServer;
+import net.minecraft.client.multiplayer.ServerData;
+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.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(GuiScreenAddServer.class)
+public class MixinGuiScreenAddServer extends GuiScreen {
+
+ @Shadow @Final private ServerData serverData;
+
+ @Inject(method = "initGui", at = @At("RETURN"))
+ public void initGui(CallbackInfo ci) {
+ final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
+
+ if (config.isShowAddServerButton()) {
+ final Pair pos = config.getAddServerScreenButtonPosition().getPosition(this.width, this.height);
+
+ final VersionEnum target = ((ExtendedServerData) serverData).viaForge$getVersion();
+ buttonList.add(new GuiButton(1_000_000_000, pos.key(), pos.value(), 100, 20, target != null ? target.getName() : "Set Version"));
+ }
+ }
+
+ @Inject(method = "actionPerformed", at = @At("HEAD"))
+ public void actionPerformed(GuiButton button, CallbackInfo ci) {
+ if (ViaForgeCommon.getManager().getConfig().isShowAddServerButton()) {
+ if (button.id == 1_000_000_000) {
+ mc.displayGuiScreen(new GuiProtocolSelector(this, true, (version, parent) -> {
+ // Set version and go back to the parent screen.
+ ((ExtendedServerData) serverData).viaForge$setVersion(version);
+ mc.displayGuiScreen(parent);
+ }));
+ }
+ }
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiScreenServerList.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiScreenServerList.java
new file mode 100644
index 0000000..c4d1546
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinGuiScreenServerList.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
+ * Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 .
+ */
+package de.florianmichael.viaforge.mixin.impl;
+
+import com.viaversion.viaversion.util.Pair;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
+import de.florianmichael.viaforge.gui.GuiProtocolSelector;
+import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.GuiScreenServerList;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(GuiScreenServerList.class)
+public class MixinGuiScreenServerList extends GuiScreen {
+
+ @Inject(method = "initGui", at = @At("RETURN"))
+ public void hookViaForgeButton(CallbackInfo ci) {
+ final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
+ if (config.isShowDirectConnectButton()) {
+ final Pair pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
+
+ buttonList.add(new GuiButton(1_000_000_000, pos.key(), pos.value(), 100, 20, "ViaForge"));
+ }
+ }
+
+ @Inject(method = "actionPerformed", at = @At("RETURN"))
+ public void handleViaForgeButtonClicking(GuiButton p_actionPerformed_1_, CallbackInfo ci) {
+ if (ViaForgeCommon.getManager().getConfig().isShowDirectConnectButton()) {
+ if (p_actionPerformed_1_.id == 1_000_000_000) {
+ mc.displayGuiScreen(new GuiProtocolSelector(this));
+ }
+ }
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetHandlerLoginClient.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetHandlerLoginClient.java
new file mode 100644
index 0000000..19610fc
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetHandlerLoginClient.java
@@ -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);
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager.java
index 125b249..fb71119 100644
--- a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager.java
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager.java
@@ -17,22 +17,90 @@
*/
package de.florianmichael.viaforge.mixin.impl;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
import io.netty.channel.Channel;
+import net.minecraft.network.NettyEncryptingDecoder;
+import net.minecraft.network.NettyEncryptingEncoder;
import net.minecraft.network.NetworkManager;
-import net.raphimc.vialoader.netty.CompressionReorderEvent;
+import net.minecraft.util.CryptManager;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.util.LazyLoadBase;
+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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import java.net.InetAddress;
@Mixin(NetworkManager.class)
-public class MixinNetworkManager {
+public class MixinNetworkManager implements VFNetworkManager {
@Shadow private Channel channel;
+ @Unique
+ private Cipher viaForge$decryptionCipher;
+
+ @Unique
+ private VersionEnum viaForge$targetVersion;
+
+ @Inject(method = "func_181124_a", 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 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 = "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 = "closeChannel", at = @At("HEAD"))
+ public void restoreTargetVersion(IChatComponent 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 = "setCompressionTreshold", at = @At("RETURN"))
- public void reOrderPipeline(int p_setCompressionTreshold_1_, CallbackInfo ci) {
- channel.pipeline().fireUserEventTriggered(CompressionReorderEvent.INSTANCE);
+ public void reorderPipeline(int p_setCompressionTreshold_1_, CallbackInfo ci) {
+ 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));
+ }
+
+ @Override
+ public VersionEnum viaForge$getTrackedVersion() {
+ return viaForge$targetVersion;
+ }
+
+ @Override
+ public void viaForge$setTrackedVersion(VersionEnum version) {
+ viaForge$targetVersion = version;
}
}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager_5.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager_5.java
index 63c484d..35182c8 100644
--- a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager_5.java
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinNetworkManager_5.java
@@ -17,14 +17,11 @@
*/
package de.florianmichael.viaforge.mixin.impl;
-import com.viaversion.viaversion.api.connection.UserConnection;
-import com.viaversion.viaversion.connection.UserConnectionImpl;
-import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
-import de.florianmichael.viaforge.ViaForge;
-import de.florianmichael.viaforge.ViaForgeVLLegacyPipeline;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
import io.netty.channel.Channel;
-import io.netty.channel.socket.SocketChannel;
-import org.spongepowered.asm.mixin.Mixin;
+import net.minecraft.network.NetworkManager;
+import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -32,13 +29,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(targets = "net.minecraft.network.NetworkManager$5")
public class MixinNetworkManager_5 {
+ @Final
+ @Mutable
+ NetworkManager val$networkmanager;
+
@Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false)
private void onInitChannel(Channel channel, CallbackInfo ci) {
- if (channel instanceof SocketChannel && ViaForge.targetVersion != ViaForge.NATIVE_VERSION) {
- final UserConnection user = new UserConnectionImpl(channel, true);
- new ProtocolPipelineImpl(user);
-
- channel.pipeline().addLast(new ViaForgeVLLegacyPipeline(user, ViaForge.targetVersion));
- }
+ ViaForgeCommon.getManager().inject(channel, (VFNetworkManager) val$networkmanager);
}
}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinServerData.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinServerData.java
new file mode 100644
index 0000000..31f64a0
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinServerData.java
@@ -0,0 +1,51 @@
+package de.florianmichael.viaforge.mixin.impl;
+
+import de.florianmichael.viaforge.common.gui.ExtendedServerData;
+import net.minecraft.client.multiplayer.ServerData;
+import net.minecraft.nbt.NBTTagCompound;
+import net.raphimc.vialoader.util.VersionEnum;
+import org.spongepowered.asm.mixin.Mixin;
+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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+@Mixin(ServerData.class)
+public class MixinServerData implements ExtendedServerData {
+
+ @Unique
+ private VersionEnum viaForge$version;
+
+ @Inject(method = "getNBTCompound", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NBTTagCompound;setString(Ljava/lang/String;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
+ public void saveVersion(CallbackInfoReturnable cir, NBTTagCompound nbttagcompound) {
+ if (viaForge$version != null) {
+ nbttagcompound.setInteger("viaForge$version", viaForge$version.getVersion());
+ }
+ }
+
+ @Inject(method = "getServerDataFromNBTCompound", at = @At(value = "TAIL"))
+ private static void getVersion(NBTTagCompound nbtCompound, CallbackInfoReturnable cir) {
+ if (nbtCompound.hasKey("viaForge$version")) {
+ ((ExtendedServerData) cir.getReturnValue()).viaForge$setVersion(VersionEnum.fromProtocolId(nbtCompound.getInteger("viaForge$version")));
+ }
+ }
+
+ @Inject(method = "copyFrom", at = @At("HEAD"))
+ public void track(ServerData serverDataIn, CallbackInfo ci) {
+ if (serverDataIn instanceof ExtendedServerData) {
+ viaForge$version = ((ExtendedServerData) serverDataIn).viaForge$getVersion();
+ }
+ }
+
+ @Override
+ public VersionEnum viaForge$getVersion() {
+ return viaForge$version;
+ }
+
+ @Override
+ public void viaForge$setVersion(VersionEnum version) {
+ viaForge$version = version;
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinServerPinger.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinServerPinger.java
new file mode 100644
index 0000000..49c7808
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/MixinServerPinger.java
@@ -0,0 +1,50 @@
+package de.florianmichael.viaforge.mixin.impl;
+
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import de.florianmichael.viaforge.common.gui.ExtendedServerData;
+import net.minecraft.client.multiplayer.ServerData;
+import net.minecraft.client.network.OldServerPinger;
+import net.minecraft.network.NetworkManager;
+import net.raphimc.vialoader.util.VersionEnum;
+import org.spongepowered.asm.mixin.Mixin;
+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.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.net.InetAddress;
+
+@Mixin(OldServerPinger.class)
+public class MixinServerPinger {
+
+ @Unique
+ private ServerData viaForge$serverData;
+
+ @Inject(method = "ping", at = @At("HEAD"))
+ public void trackServerData(ServerData server, CallbackInfo ci) {
+ viaForge$serverData = server;
+ }
+
+ @Redirect(method = "ping", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;func_181124_a(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 VersionEnum 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;
+ }
+
+ return NetworkManager.func_181124_a(address, i, b);
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/mixin/impl/fixes/MixinEntityPlayerSP.java b/src/main/java/de/florianmichael/viaforge/mixin/impl/fixes/MixinEntityPlayerSP.java
new file mode 100644
index 0000000..452a684
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/mixin/impl/fixes/MixinEntityPlayerSP.java
@@ -0,0 +1,44 @@
+package de.florianmichael.viaforge.mixin.impl.fixes;
+
+import com.mojang.authlib.GameProfile;
+import de.florianmichael.viaforge.common.ViaForgeCommon;
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.network.NetHandlerPlayClient;
+import net.minecraft.network.Packet;
+import net.minecraft.world.World;
+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.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(EntityPlayerSP.class)
+public class MixinEntityPlayerSP extends AbstractClientPlayer {
+
+ public MixinEntityPlayerSP(World worldIn, GameProfile playerProfile) {
+ super(worldIn, playerProfile);
+ }
+
+ @Unique
+ private boolean viaForge$prevOnGround;
+
+ @Redirect(method = "onUpdateWalkingPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/NetHandlerPlayClient;addToSendQueue(Lnet/minecraft/network/Packet;)V", ordinal = 7))
+ public void emulateIdlePacket(NetHandlerPlayClient instance, Packet p_addToSendQueue_1_) {
+ if (ViaForgeCommon.getManager().getTargetVersion().isNewerThan(VersionEnum.r1_8)) {
+ // <= 1.8 spams the idle packet instead of only sending it when the ground state changes
+ if (this.viaForge$prevOnGround == this.onGround) {
+ return;
+ }
+ }
+ instance.addToSendQueue(p_addToSendQueue_1_);
+ }
+
+ @Inject(method = "onUpdateWalkingPlayer", at = @At("RETURN"))
+ public void saveGroundState(CallbackInfo ci) {
+ this.viaForge$prevOnGround = this.onGround;
+ }
+}
diff --git a/src/main/java/de/florianmichael/viaforge/provider/ViaForgeGameProfileFetcher.java b/src/main/java/de/florianmichael/viaforge/provider/ViaForgeGameProfileFetcher.java
new file mode 100644
index 0000000..2d06f53
--- /dev/null
+++ b/src/main/java/de/florianmichael/viaforge/provider/ViaForgeGameProfileFetcher.java
@@ -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 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 entry : mojangProfile.getProperties().entries()) {
+ final Property prop = entry.getValue();
+ gameProfile.addProperty(new GameProfile.Property(prop.getName(), prop.getValue(), prop.getSignature()));
+ }
+
+ return gameProfile;
+ }
+}
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
new file mode 100644
index 0000000..17fe0d6
--- /dev/null
+++ b/src/main/resources/mcmod.info
@@ -0,0 +1,18 @@
+[
+ {
+ "modid": "viaforge",
+ "name": "ViaForge",
+ "description": "Client-side Implementation of the Via* projects for Minecraft Forge",
+ "version": "${version}",
+ "mcversion": "[1.8]",
+ "url": "https://github.com/ViaVersion/ViaForge",
+ "updateUrl": "",
+ "authorList": [
+ "FlorianMichael/EnZaXD"
+ ],
+ "credits": "https://github.com/FlorianMichael/",
+ "logoFile": "",
+ "screenshots": [],
+ "dependencies": []
+ }
+]
diff --git a/src/main/resources/mixins.viaforge-mc18.json b/src/main/resources/mixins.viaforge-mc18.json
new file mode 100644
index 0000000..832ee6e
--- /dev/null
+++ b/src/main/resources/mixins.viaforge-mc18.json
@@ -0,0 +1,23 @@
+{
+ "required": true,
+ "minVersion": "0.7.5",
+ "compatibilityLevel": "JAVA_8",
+ "package": "de.florianmichael.viaforge.mixin.impl",
+ "refmap": "mixins.viaforge.refmap.json",
+ "client": [
+ "MixinGuiMainMenu",
+ "MixinGuiMultiplayer",
+ "MixinGuiOverlayDebug",
+ "MixinGuiScreenAddServer",
+ "MixinGuiScreenServerList",
+ "MixinNetHandlerLoginClient",
+ "MixinNetworkManager",
+ "MixinNetworkManager_5",
+ "MixinServerPinger",
+ "fixes.MixinEntityPlayerSP"
+ ],
+ "verbose": true,
+ "mixins": [
+ "MixinGuiConnecting_1"
+ ]
+}
diff --git a/src/main/resources/mixins.viaforge.json b/src/main/resources/mixins.viaforge.json
deleted file mode 100644
index c87fcbc..0000000
--- a/src/main/resources/mixins.viaforge.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "required": true,
- "minVersion": "0.7.5",
- "compatibilityLevel": "JAVA_8",
- "package": "de.florianmichael.viaforge.mixin.impl",
- "refmap": "mixins.viaforge.refmap.json",
- "mixins": [
- "MixinNetworkManager",
- "MixinNetworkManager_5"
- ],
- "verbose": true,
- "client": [
- "MixinGuiMainMenuGuiMultiplayerGuiServerList",
- "MixinMinecraft"
- ]
-}