mirror of
https://github.com/ViaVersion/ViaForge.git
synced 2025-02-16 01:42:30 +01:00
Merge remote-tracking branch 'origin/dev'
This commit is contained in:
commit
be8f079e26
@ -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
|
||||
|
@ -24,7 +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 "org.yaml:snakeyaml:${project.snake_yml_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}"
|
||||
}
|
||||
|
@ -8,10 +8,13 @@ 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
|
||||
|
||||
# Misc Libraries
|
||||
|
@ -19,11 +19,11 @@ pluginManagement {
|
||||
|
||||
rootProject.name = "ViaForge"
|
||||
include "viaforge-mc112"
|
||||
include "viaforge-mc114"
|
||||
include "viaforge-mc115"
|
||||
include "viaforge-mc116"
|
||||
include "viaforge-mc117"
|
||||
include "viaforge-mc118"
|
||||
include "viaforge-mc119"
|
||||
include "viaforge-mc120"
|
||||
include 'viaforge-mc115'
|
||||
include 'viaforge-mc114'
|
||||
|
||||
|
@ -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.ViaForgeVLLegacyPipeline;
|
||||
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.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<VFNetworkManager> VF_NETWORK_MANAGER = 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());
|
||||
@ -86,11 +89,14 @@ public class ViaForgeCommon {
|
||||
*
|
||||
* @param channel the channel to inject the pipeline into
|
||||
*/
|
||||
public void inject(final Channel channel) {
|
||||
if (channel instanceof SocketChannel && targetVersion != getNativeVersion()) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -101,6 +107,8 @@ public class ViaForgeCommon {
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -112,7 +120,15 @@ public class ViaForgeCommon {
|
||||
return targetVersion;
|
||||
}
|
||||
|
||||
public void setTargetVersion(VersionEnum 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());
|
||||
}
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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);
|
||||
}
|
@ -17,6 +17,9 @@
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -39,4 +42,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();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
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;
|
||||
@ -10,10 +11,17 @@ 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.
|
||||
@ -37,13 +45,30 @@ public class ViaForgeConfig extends Config {
|
||||
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);
|
||||
save();
|
||||
}
|
||||
|
||||
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() {
|
||||
@ -57,4 +82,41 @@ public class ViaForgeConfig extends Config {
|
||||
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<Integer, Integer> getPosition(int width, int height) {
|
||||
return invoker.invoke(width, height);
|
||||
}
|
||||
|
||||
public interface PositionInvoker {
|
||||
|
||||
Pair<Integer, Integer> invoke(int width, int height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,27 +18,36 @@
|
||||
package de.florianmichael.viaforge.common.protocolhack;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
|
||||
import com.viaversion.viaversion.api.protocol.version.VersionProvider;
|
||||
import com.viaversion.viaversion.protocols.base.BaseVersionProvider;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
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();
|
||||
|
||||
Via.getManager().getProviders().use(VersionProvider.class, new BaseVersionProvider() {
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection connection) throws Exception {
|
||||
if (connection.isClientSide() && !ViaForgeCommon.getManager().getPlatform().isSingleplayer().get()) {
|
||||
return ViaForgeCommon.getManager().getTargetVersion().getVersion();
|
||||
}
|
||||
final ViaProviders providers = Via.getManager().getProviders();
|
||||
|
||||
return super.getClosestServerProtocol(connection);
|
||||
}
|
||||
});
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viaforge.common.protocolhack;
|
||||
package de.florianmichael.viaforge.common.protocolhack.netty;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import net.raphimc.vialoader.netty.VLLegacyPipeline;
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
@ -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
|
||||
'''
|
@ -1,9 +1,30 @@
|
||||
# Thanks for downloading ViaForge!
|
||||
# If you need help, you can join our Discord - https://viaversion.com/discord
|
||||
#
|
||||
# Disclaimer:
|
||||
# It cannot be guaranteed that this mod is allowed on specific servers as it can possibly cause problems with anti-cheat plugins, (USE ONLY WITH CAUTION!)
|
||||
# It cannot be guaranteed that this mod is allowed on specific servers as it can possibly cause problems with anti-cheat plugins
|
||||
# (USE ONLY WITH CAUTION!)
|
||||
#
|
||||
#----------------------------------------------------------#
|
||||
# GLOBAL OPTIONS #
|
||||
#----------------------------------------------------------#
|
||||
#
|
||||
# This option sets the protocol version to be used when connecting to servers. (can also be changed in-game)
|
||||
client-side-version: -1
|
||||
#
|
||||
# Manually sends the joinServer request when connecting to <= 1.2.5 servers.
|
||||
verify-session-in-old-versions: true
|
||||
#
|
||||
# Allow ViaForge to authenticate with BetaCraft's MP-Pass system for <= c0.30 servers.
|
||||
allow-betacraft-authentication: true
|
||||
#
|
||||
# If enabled, ViaForge will show the current protocol version in the F3 menu.
|
||||
show-protocol-version-in-f3: true
|
||||
#
|
||||
#----------------------------------------------------------#
|
||||
# GUI OPTIONS #
|
||||
#----------------------------------------------------------#
|
||||
#
|
||||
# This option indicates if the ViaForge button should be shown in the main menu.
|
||||
show-main-menu-button: true
|
||||
#
|
||||
@ -12,3 +33,14 @@ show-multiplayer-button: true
|
||||
#
|
||||
# This option indicates if the ViaForge button should be shown in the direct connect screen.
|
||||
show-direct-connect-button: true
|
||||
#
|
||||
# This option indicates if the ViaForge set version button should be shown in the server list.
|
||||
show-add-server-button: true
|
||||
#
|
||||
# This option indicates where the ViaForge button should be located in all screens.
|
||||
# Possible options: TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
|
||||
via-forge-button-position: "TOP_LEFT"
|
||||
#
|
||||
# This option indicates where the ViaForge set version button should be located in the add server screen.
|
||||
# Possible options: TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
|
||||
add-server-screen-button-position: "TOP_LEFT"
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -18,37 +18,85 @@
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.realmsclient.gui.ChatFormatting;
|
||||
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;
|
||||
|
||||
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"));
|
||||
list = new SlotList(mc, width, height, 32, height - 32, 10);
|
||||
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, 3 + 3 /* start offset */ + (fontRenderer.FONT_HEIGHT + 2) * 3 /* title is 2 */, height - 30, fontRenderer.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) mc.displayGuiScreen(parent);
|
||||
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 typedChar, int keyCode) {
|
||||
if (keyCode == Keyboard.KEY_ESCAPE) {
|
||||
mc.displayGuiScreen(parent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -58,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.fontRenderer, ChatFormatting.GOLD + "ViaForge", this.width / 4, 6, 16777215);
|
||||
drawCenteredString(fontRenderer, ChatFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
|
||||
GL11.glPopMatrix();
|
||||
|
||||
drawString(this.fontRenderer, "by https://github.com/ViaVersion/ViaForge", 1, 1, -1);
|
||||
drawString(this.fontRenderer, "Discord: florianmichael", 1, 11, -1);
|
||||
drawCenteredString(fontRenderer, "https://github.com/ViaVersion/ViaForge", width / 2, (fontRenderer.FONT_HEIGHT + 2) * 2 + 3, -1);
|
||||
drawString(fontRenderer, 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
|
||||
@ -84,12 +136,12 @@ public class GuiProtocolSelector extends GuiScreen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void elementClicked(int i, boolean b, int i1, int i2) {
|
||||
ViaForgeCommon.getManager().setTargetVersion(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;
|
||||
}
|
||||
|
||||
@ -99,11 +151,23 @@ public class GuiProtocolSelector extends GuiScreen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlot(int i, int i1, int i2, int i3, int i4, int i5, float v) {
|
||||
protected void drawSlot(int index, int x, int y, int slotHeight, int mouseX, int mouseY, float partialTicks) {
|
||||
final VersionEnum targetVersion = ViaForgeCommon.getManager().getTargetVersion();
|
||||
final VersionEnum version = VersionEnum.SORTED_VERSIONS.get(i);
|
||||
final VersionEnum version = VersionEnum.SORTED_VERSIONS.get(index);
|
||||
|
||||
drawCenteredString(mc.fontRenderer,(targetVersion == version ? 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.fontRenderer,(color) + version.getName(), width / 2, y, -1);
|
||||
}
|
||||
}
|
||||
|
||||
public interface FinishedCallback {
|
||||
|
||||
void finished(final VersionEnum version, final GuiScreen parent);
|
||||
}
|
||||
}
|
||||
|
@ -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;createNetworkManagerAndConnect(Ljava/net/InetAddress;IZ)Lnet/minecraft/network/NetworkManager;"))
|
||||
public NetworkManager trackVersion(InetAddress address, int i, boolean b) {
|
||||
// We need to track the version of the server we are connecting to, so we can later
|
||||
// use it to determine the protocol version to use.
|
||||
// We hope that the current server data is not null
|
||||
if (Minecraft.getMinecraft().getCurrentServerData() instanceof ExtendedServerData) {
|
||||
final 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.createNetworkManagerAndConnect(address, i, b);
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin.impl;
|
||||
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import de.florianmichael.viaforge.ViaForge112;
|
||||
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;
|
||||
@ -33,8 +35,11 @@ public class MixinGuiMainMenu extends GuiScreen {
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
ViaForgeCommon.init(ViaForge112.PLATFORM);
|
||||
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMainMenuButton()) {
|
||||
buttonList.add(new GuiButton(1_000_000_000, 5, 6, 98, 20, "ViaForge"));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
buttonList.add(new GuiButton(1_000_000_000, pos.key(), pos.value(), 100, 20, "ViaForge"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,9 @@
|
||||
*/
|
||||
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;
|
||||
@ -32,8 +34,11 @@ public class MixinGuiMultiplayer extends GuiScreen {
|
||||
|
||||
@Inject(method = "initGui", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMultiplayerButton()) {
|
||||
buttonList.add(new GuiButton(1_000_000_000, 5, 6, 98, 20, "ViaForge"));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMultiplayerButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
buttonList.add(new GuiButton(1_000_000_000, pos.key(), pos.value(), 100, 20, "ViaForge"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<List<String>> 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 + ")");
|
||||
}
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Integer, Integer> 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);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,9 @@
|
||||
*/
|
||||
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;
|
||||
@ -32,8 +34,11 @@ public class MixinGuiScreenServerList extends GuiScreen {
|
||||
|
||||
@Inject(method = "initGui", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowDirectConnectButton()) {
|
||||
buttonList.add(new GuiButton(1_000_000_000, 5, 6, 98, 20, "ViaForge"));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowDirectConnectButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
buttonList.add(new GuiButton(1_000_000_000, pos.key(), pos.value(), 100, 20, "ViaForge"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -18,21 +18,89 @@
|
||||
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.minecraft.util.CryptManager;
|
||||
import net.minecraft.util.LazyLoadBase;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
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 = "createNetworkManagerAndConnect", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;group(Lio/netty/channel/EventLoopGroup;)Lio/netty/bootstrap/AbstractBootstrap;"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private static void trackSelfTarget(InetAddress address, int serverPort, boolean useNativeTransport, CallbackInfoReturnable<NetworkManager> cir, NetworkManager networkmanager, Class oclass, LazyLoadBase lazyloadbase) {
|
||||
// The connecting screen and server pinger are setting the main target version when a specific version for a server is set,
|
||||
// This works for joining perfect since we can simply restore the version when the server doesn't have a specific one set,
|
||||
// but for the server pinger we need to store the target version and force the pinging to use the target version.
|
||||
// Due to the fact that the server pinger is being called multiple times.
|
||||
((VFNetworkManager) networkmanager).viaforge_setTrackedVersion(ViaForgeCommon.getManager().getTargetVersion());
|
||||
}
|
||||
|
||||
@Inject(method = "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(ITextComponent message, CallbackInfo ci) {
|
||||
// If the previous server forced a version, we need to restore the version to the default one.
|
||||
ViaForgeCommon.getManager().restoreVersion();
|
||||
}
|
||||
|
||||
@Inject(method = "setCompressionThreshold", at = @At("RETURN"))
|
||||
public void reorderPipeline(int p_setCompressionTreshold_1_, CallbackInfo ci) {
|
||||
ViaForgeCommon.getManager().reorderCompression(channel);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,10 @@
|
||||
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 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;
|
||||
@ -27,8 +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) {
|
||||
ViaForgeCommon.getManager().inject(channel);
|
||||
ViaForgeCommon.getManager().inject(channel, (VFNetworkManager) val$networkmanager);
|
||||
}
|
||||
}
|
||||
|
@ -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<NBTTagCompound> 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<ServerData> 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;
|
||||
}
|
||||
}
|
@ -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.ServerPinger;
|
||||
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(ServerPinger.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;createNetworkManagerAndConnect(Ljava/net/InetAddress;IZ)Lnet/minecraft/network/NetworkManager;"))
|
||||
public NetworkManager trackVersion(InetAddress address, int i, boolean b) {
|
||||
// We need to track the version of the server we are connecting to, so we can later
|
||||
// use it to determine the protocol version to use.
|
||||
// We hope that the current server data is not null
|
||||
|
||||
if (viaforge_serverData instanceof ExtendedServerData) {
|
||||
final 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.createNetworkManagerAndConnect(address, i, b);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
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.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.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(EntityPlayerSP.class)
|
||||
public class MixinEntityPlayerSP extends AbstractClientPlayer {
|
||||
|
||||
@Shadow private boolean prevOnGround;
|
||||
|
||||
public MixinEntityPlayerSP(World worldIn, GameProfile playerProfile) {
|
||||
super(worldIn, playerProfile);
|
||||
}
|
||||
|
||||
@Redirect(method = "onUpdateWalkingPlayer", at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/EntityPlayerSP;prevOnGround:Z", ordinal = 0))
|
||||
public boolean emulateIdlePacket(EntityPlayerSP instance) {
|
||||
if (ViaForgeCommon.getManager().getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
||||
// <= 1.8 spams the idle packet instead of only sending it when the ground state changes
|
||||
// So we invert the original logic:
|
||||
// if (prevOnGround != onGround) sendPacket
|
||||
// To be like:
|
||||
// if (!onGround != onGround) sendPacket
|
||||
// Which is the same as:
|
||||
// if (true) sendPacket
|
||||
return !onGround;
|
||||
}
|
||||
return prevOnGround;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -4,12 +4,19 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin.impl",
|
||||
"refmap": "mixins.viaforge-mc112.refmap.json",
|
||||
"mixins": [
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_5",
|
||||
"client": [
|
||||
"MixinGuiConnecting_1",
|
||||
"MixinGuiMainMenu",
|
||||
"MixinGuiMultiplayer",
|
||||
"MixinGuiScreenServerList"
|
||||
"MixinGuiOverlayDebug",
|
||||
"MixinGuiScreenAddServer",
|
||||
"MixinGuiScreenServerList",
|
||||
"MixinNetHandlerLoginClient",
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_5",
|
||||
"MixinServerData",
|
||||
"MixinServerPinger",
|
||||
"fixes.MixinEntityPlayerSP"
|
||||
],
|
||||
"verbose": true
|
||||
}
|
||||
|
@ -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.util.Session;
|
||||
import net.minecraft.util.SharedConstants;
|
||||
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 ViaForge114 implements VFPlatform {
|
||||
public File getLeadingDirectory() {
|
||||
return Minecraft.getInstance().gameDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinServer(String serverId) throws Throwable {
|
||||
final Session session = Minecraft.getInstance().getUser();
|
||||
|
||||
Minecraft.getInstance().getMinecraftSessionService().joinServer(session.getGameProfile(), session.getAccessToken(), serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfileFetcher getGameProfileFetcher() {
|
||||
return new ViaForgeGameProfileFetcher();
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.realmsclient.gui.ChatFormatting;
|
||||
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.screen.Screen;
|
||||
@ -24,53 +27,98 @@ import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.gui.widget.list.AbstractList;
|
||||
import net.minecraft.client.gui.widget.list.ExtendedList;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class GuiProtocolSelector extends Screen {
|
||||
|
||||
private final Screen parent;
|
||||
public final Screen parent;
|
||||
public final boolean simple;
|
||||
public final FinishedCallback finishedCallback;
|
||||
|
||||
private SlotList list;
|
||||
|
||||
private String status;
|
||||
private long time;
|
||||
|
||||
public static void open(final Minecraft minecraft) { // Bypass for some weird bytecode instructions errors in Forge
|
||||
minecraft.setScreen(new GuiProtocolSelector(minecraft.screen));
|
||||
}
|
||||
|
||||
private SlotList slotList;
|
||||
public GuiProtocolSelector(final Screen 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(Screen parent) {
|
||||
public GuiProtocolSelector(final Screen parent, final boolean simple, final FinishedCallback finishedCallback) {
|
||||
super(new StringTextComponent("ViaForge Protocol Selector"));
|
||||
this.parent = parent;
|
||||
this.simple = simple;
|
||||
this.finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
public void init() {
|
||||
super.init();
|
||||
addButton(new Button(5, height - 25, 20, 20, "<-", b -> minecraft.setScreen(parent)));
|
||||
if (!this.simple) {
|
||||
addButton(new Button(width - 105, 5, 100, 20, "Create dump", b -> {
|
||||
try {
|
||||
minecraft.keyboardHandler.setClipboard(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());
|
||||
}
|
||||
}));
|
||||
addButton(new Button(width - 105, height - 25, 100, 20, "Reload configs", b -> Via.getManager().getConfigurationProvider().reloadConfigs()));
|
||||
}
|
||||
|
||||
slotList = new SlotList(minecraft, width, height, 32, height - 32, 10);
|
||||
addButton(new Button(width / 2 - 100, height - 27, 200, 20, "Back", b -> minecraft.setScreen(parent)));
|
||||
list = new SlotList(minecraft, width, height, 3 + 3 /* start offset */ + (font.lineHeight + 2) * 3 /* title is 2 */, height - 30, font.lineHeight + 2);
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
this.time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int actions) {
|
||||
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||
minecraft.setScreen(parent);
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
if (System.currentTimeMillis() - this.time >= 10_000) {
|
||||
this.status = null;
|
||||
}
|
||||
|
||||
renderBackground();
|
||||
this.slotList.render(p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
this.list.render(p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
super.render(p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScalef(2.0F, 2.0F, 2.0F);
|
||||
drawCenteredString(this.font, TextFormatting.GOLD + "ViaForge", this.width / 4, 6, 16777215);
|
||||
drawCenteredString(font, ChatFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
|
||||
GL11.glPopMatrix();
|
||||
|
||||
drawString(this.font, "by https://github.com/ViaVersion/ViaForge", 1, 1, -1);
|
||||
drawString(this.font, "Discord: florianmichael", 1, 11, -1);
|
||||
drawCenteredString(font, "https://github.com/ViaVersion/ViaForge", width / 2, (font.lineHeight + 2) * 2 + 3, -1);
|
||||
drawString(font, status != null ? status : "Discord: florianmichael", 3, 3, -1);
|
||||
}
|
||||
|
||||
static class SlotList extends ExtendedList<SlotList.SlotEntry> {
|
||||
class SlotList extends ExtendedList<SlotList.SlotEntry> {
|
||||
|
||||
public SlotList(Minecraft p_i51146_1_, int p_i51146_2_, int p_i51146_3_, int p_i51146_4_, int p_i51146_5_, int p_i51146_6_) {
|
||||
super(p_i51146_1_, p_i51146_2_, p_i51146_3_, p_i51146_4_, p_i51146_5_, p_i51146_6_);
|
||||
public SlotList(Minecraft client, int width, int height, int top, int bottom, int slotHeight) {
|
||||
super(client, width, height, top, bottom, slotHeight);
|
||||
|
||||
for (VersionEnum version : VersionEnum.SORTED_VERSIONS) {
|
||||
addEntry(new SlotEntry(version));
|
||||
@ -86,16 +134,29 @@ public class GuiProtocolSelector extends Screen {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double p_231044_1_, double p_231044_3_, int p_231044_5_) {
|
||||
ViaForgeCommon.getManager().setTargetVersion(versionEnum);
|
||||
return super.mouseClicked(p_231044_1_, p_231044_3_, p_231044_5_);
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
GuiProtocolSelector.this.finishedCallback.finished(versionEnum, GuiProtocolSelector.this.parent);
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int p_230432_2_, int p_230432_3_, int p_230432_4_, int p_230432_5_, int p_230432_6_, int p_230432_7_, int p_230432_8_, boolean p_230432_9_, float p_230432_10_) {
|
||||
drawCenteredString(Minecraft.getInstance().font,
|
||||
(ViaForgeCommon.getManager().getTargetVersion() == versionEnum ? TextFormatting.GREEN.toString() : TextFormatting.DARK_RED.toString()) + versionEnum.getName(), width / 2, p_230432_3_, -1);
|
||||
public void render(int p_230432_2_, int y, int p_230432_4_, int p_230432_5_, int p_230432_6_, int p_230432_7_, int p_230432_8_, boolean p_230432_9_, float p_230432_10_) {
|
||||
final VersionEnum targetVersion = ViaForgeCommon.getManager().getTargetVersion();
|
||||
|
||||
String color;
|
||||
if (targetVersion == versionEnum) {
|
||||
color = GuiProtocolSelector.this.simple ? ChatFormatting.GOLD.toString() : ChatFormatting.GREEN.toString();
|
||||
} else {
|
||||
color = GuiProtocolSelector.this.simple ? ChatFormatting.WHITE.toString() : ChatFormatting.DARK_RED.toString();
|
||||
}
|
||||
|
||||
drawCenteredString(Minecraft.getInstance().font, color + versionEnum.getName(), width / 2, y, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface FinishedCallback {
|
||||
|
||||
void finished(final VersionEnum version, final Screen parent);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.screen.AddServerScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
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(AddServerScreen.class)
|
||||
public class MixinAddServerScreen extends Screen {
|
||||
|
||||
@Shadow @Final private ServerData serverData;
|
||||
|
||||
public MixinAddServerScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void initGui(CallbackInfo ci) {
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
|
||||
if (config.isShowAddServerButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getAddServerScreenButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
final VersionEnum target = ((ExtendedServerData) serverData).viaforge_getVersion();
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, target != null ? target.getName() : "Set Version", b -> {
|
||||
minecraft.setScreen(new GuiProtocolSelector(this, true, (version, parent) -> {
|
||||
// Set version and go back to the parent screen.
|
||||
((ExtendedServerData) serverData).viaforge_setVersion(version);
|
||||
minecraft.setScreen(parent);
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.login.ClientLoginNetHandler;
|
||||
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(ClientLoginNetHandler.class)
|
||||
public class MixinClientLoginNetHandler {
|
||||
|
||||
@Shadow @Final private NetworkManager connection;
|
||||
|
||||
@Redirect(method = "authenticateServer", 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 = connection.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);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.gui.screen.ConnectingScreen$1")
|
||||
public class MixinConnectingScreen_1 {
|
||||
|
||||
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;connectToServer(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.getInstance().getCurrentServer() instanceof ExtendedServerData) {
|
||||
final VersionEnum version = ((ExtendedServerData) Minecraft.getInstance().getCurrentServer()).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.connectToServer(address, i, b);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.gui.overlay.DebugOverlayGui;
|
||||
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(DebugOverlayGui.class)
|
||||
public class MixinDebugOverlayGui {
|
||||
|
||||
@Inject(method = "getSystemInformation", at = @At(value = "TAIL"))
|
||||
public void addViaForgeVersion(CallbackInfoReturnable<List<String>> 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 + ")");
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import de.florianmichael.viaforge.ViaForge114;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
|
||||
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
|
||||
import net.minecraft.client.gui.screen.MainMenuScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
@ -32,16 +34,19 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(MainMenuScreen.class)
|
||||
public class MixinMainMenuScreen extends Screen {
|
||||
|
||||
public MixinMainMenuScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinMainMenuScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("HEAD"))
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
ViaForgeCommon.init(ViaForge114.PLATFORM);
|
||||
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMainMenuButton()) {
|
||||
addButton(new Button(5, 6, 98, 20,"ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, "ViaForge", buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.ViaForge114;
|
||||
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.screen.MultiplayerScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
@ -32,14 +33,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(MultiplayerScreen.class)
|
||||
public class MixinMultiplayerScreen extends Screen {
|
||||
|
||||
protected MixinMultiplayerScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinMultiplayerScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMultiplayerButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, "ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, "ViaForge", buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,22 +18,89 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.LazyLoadBase;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
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 = "connectToServer", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;group(Lio/netty/channel/EventLoopGroup;)Lio/netty/bootstrap/AbstractBootstrap;"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private static void trackSelfTarget(InetAddress address, int serverPort, boolean useNativeTransport, CallbackInfoReturnable<NetworkManager> cir, NetworkManager networkmanager, Class oclass, LazyLoadBase lazyloadbase) {
|
||||
// The connecting screen and server pinger are setting the main target version when a specific version for a server is set,
|
||||
// This works for joining perfect since we can simply restore the version when the server doesn't have a specific one set,
|
||||
// but for the server pinger we need to store the target version and force the pinging to use the target version.
|
||||
// Due to the fact that the server pinger is being called multiple times.
|
||||
((VFNetworkManager) networkmanager).viaforge_setTrackedVersion(ViaForgeCommon.getManager().getTargetVersion());
|
||||
}
|
||||
|
||||
@Inject(method = "setEncryptionKey", 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.getCipher(2, key);
|
||||
|
||||
// Enabling the encryption side
|
||||
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new NettyEncryptingEncoder(CryptManager.getCipher(1, key)));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "disconnect", at = @At("HEAD"))
|
||||
public void restoreTargetVersion(ITextComponent p_150718_1_, CallbackInfo ci) {
|
||||
// If the previous server forced a version, we need to restore the version to the default one.
|
||||
ViaForgeCommon.getManager().restoreVersion();
|
||||
}
|
||||
|
||||
@Inject(method = "setupCompression", at = @At("RETURN"))
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -18,17 +18,25 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
|
||||
import io.netty.channel.Channel;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(targets = "net.minecraft.network.NetworkManager$1", remap = false)
|
||||
@Mixin(targets = "net.minecraft.network.NetworkManager$1")
|
||||
public class MixinNetworkManager_1 {
|
||||
|
||||
@Final
|
||||
@Mutable
|
||||
NetworkManager val$networkmanager;
|
||||
|
||||
@Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false)
|
||||
private void onInitChannel(Channel channel, CallbackInfo ci) {
|
||||
ViaForgeCommon.getManager().inject(channel);
|
||||
ViaForgeCommon.getManager().inject(channel, (VFNetworkManager) val$networkmanager);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
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 = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundNBT;putString(Ljava/lang/String;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void saveVersion(CallbackInfoReturnable<CompoundNBT> cir, CompoundNBT compoundnbt) {
|
||||
if (viaforge_version != null) {
|
||||
compoundnbt.putInt("viaforge_version", viaforge_version.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "read", at = @At(value = "TAIL"))
|
||||
private static void getVersion(CompoundNBT compoundnbt, CallbackInfoReturnable<ServerData> cir) {
|
||||
if (compoundnbt.contains("viaforge_version")) {
|
||||
((ExtendedServerData) cir.getReturnValue()).viaforge_setVersion(VersionEnum.fromProtocolId(compoundnbt.getInt("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;
|
||||
}
|
||||
}
|
@ -17,7 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ServerListScreen;
|
||||
@ -31,14 +33,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(ServerListScreen.class)
|
||||
public class MixinServerListScreen extends Screen {
|
||||
|
||||
protected MixinServerListScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinServerListScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowDirectConnectButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, "ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowDirectConnectButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, "ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.network.ServerPinger;
|
||||
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(ServerPinger.class)
|
||||
public class MixinServerPinger {
|
||||
|
||||
@Unique
|
||||
private ServerData viaforge_serverData;
|
||||
|
||||
@Inject(method = "pingServer", at = @At("HEAD"))
|
||||
public void trackServerData(ServerData server, CallbackInfo ci) {
|
||||
viaforge_serverData = server;
|
||||
}
|
||||
|
||||
@Redirect(method = "pingServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;connectToServer(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.connectToServer(address, i, b);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin.fixes;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.entity.player.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
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;
|
||||
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
public class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
|
||||
|
||||
@Shadow private boolean lastOnGround;
|
||||
|
||||
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
|
||||
super(world, profile);
|
||||
}
|
||||
|
||||
@Redirect(method = "sendPosition", at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/player/ClientPlayerEntity;lastOnGround:Z", ordinal = 0))
|
||||
public boolean emulateIdlePacket(ClientPlayerEntity instance) {
|
||||
if (ViaForgeCommon.getManager().getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
||||
// <= 1.8 spams the idle packet instead of only sending it when the ground state changes
|
||||
// So we invert the original logic:
|
||||
// if (prevOnGround != onGround) sendPacket
|
||||
// To be like:
|
||||
// if (!onGround != onGround) sendPacket
|
||||
// Which is the same as:
|
||||
// if (true) sendPacket
|
||||
return !onGround;
|
||||
}
|
||||
return lastOnGround;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -3,15 +3,25 @@
|
||||
"minVersion": "0.7.5",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"mixins": [
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"client": [
|
||||
"MixinAddServerScreen",
|
||||
"MixinClientLoginNetHandler",
|
||||
"MixinConnectingScreen_1",
|
||||
"MixinDebugOverlayGui",
|
||||
"MixinMainMenuScreen",
|
||||
"MixinMultiplayerScreen",
|
||||
"MixinServerListScreen"
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"MixinServerData",
|
||||
"MixinServerListScreen",
|
||||
"MixinServerPinger",
|
||||
"fixes.MixinClientPlayerEntity"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"refmap": "mixins.viaforge-mc114.refmap.json"
|
||||
"refmap": "mixins.viaforge-mc114.refmap.json",
|
||||
"mixins": [
|
||||
"MixinNetworkManager_1"
|
||||
]
|
||||
}
|
||||
|
@ -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.util.Session;
|
||||
import net.minecraft.util.SharedConstants;
|
||||
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;
|
||||
@ -44,4 +47,16 @@ public class ViaForge115 implements VFPlatform {
|
||||
public File getLeadingDirectory() {
|
||||
return Minecraft.getInstance().gameDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinServer(String serverId) throws Throwable {
|
||||
final Session session = Minecraft.getInstance().getUser();
|
||||
|
||||
Minecraft.getInstance().getMinecraftSessionService().joinServer(session.getGameProfile(), session.getAccessToken(), serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfileFetcher getGameProfileFetcher() {
|
||||
return new ViaForgeGameProfileFetcher();
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import de.florianmichael.viaforge.ViaForge115;
|
||||
import com.mojang.realmsclient.gui.ChatFormatting;
|
||||
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.screen.Screen;
|
||||
@ -25,53 +27,98 @@ import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.gui.widget.list.AbstractList;
|
||||
import net.minecraft.client.gui.widget.list.ExtendedList;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class GuiProtocolSelector extends Screen {
|
||||
|
||||
private final Screen parent;
|
||||
public final Screen parent;
|
||||
public final boolean simple;
|
||||
public final FinishedCallback finishedCallback;
|
||||
|
||||
private SlotList list;
|
||||
|
||||
private String status;
|
||||
private long time;
|
||||
|
||||
public static void open(final Minecraft minecraft) { // Bypass for some weird bytecode instructions errors in Forge
|
||||
minecraft.setScreen(new GuiProtocolSelector(minecraft.screen));
|
||||
}
|
||||
|
||||
private SlotList slotList;
|
||||
public GuiProtocolSelector(final Screen 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(Screen parent) {
|
||||
public GuiProtocolSelector(final Screen parent, final boolean simple, final FinishedCallback finishedCallback) {
|
||||
super(new StringTextComponent("ViaForge Protocol Selector"));
|
||||
this.parent = parent;
|
||||
this.simple = simple;
|
||||
this.finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
public void init() {
|
||||
super.init();
|
||||
addButton(new Button(5, height - 25, 20, 20, "<-", b -> minecraft.setScreen(parent)));
|
||||
if (!this.simple) {
|
||||
addButton(new Button(width - 105, 5, 100, 20, "Create dump", b -> {
|
||||
try {
|
||||
minecraft.keyboardHandler.setClipboard(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());
|
||||
}
|
||||
}));
|
||||
addButton(new Button(width - 105, height - 25, 100, 20, "Reload configs", b -> Via.getManager().getConfigurationProvider().reloadConfigs()));
|
||||
}
|
||||
|
||||
slotList = new SlotList(minecraft, width, height, 32, height - 32, 10);
|
||||
addButton(new Button(width / 2 - 100, height - 27, 200, 20, "Back", b -> minecraft.setScreen(parent)));
|
||||
list = new SlotList(minecraft, width, height, 3 + 3 /* start offset */ + (font.lineHeight + 2) * 3 /* title is 2 */, height - 30, font.lineHeight + 2);
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
this.time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int actions) {
|
||||
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||
minecraft.setScreen(parent);
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
if (System.currentTimeMillis() - this.time >= 10_000) {
|
||||
this.status = null;
|
||||
}
|
||||
|
||||
renderBackground();
|
||||
this.slotList.render(p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
this.list.render(p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
super.render(p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScalef(2.0F, 2.0F, 2.0F);
|
||||
drawCenteredString(this.font, TextFormatting.GOLD + "ViaForge", this.width / 4, 6, 16777215);
|
||||
drawCenteredString(font, ChatFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
|
||||
GL11.glPopMatrix();
|
||||
|
||||
drawString(this.font, "by https://github.com/ViaVersion/ViaForge", 1, 1, -1);
|
||||
drawString(this.font, "Discord: florianmichael", 1, 11, -1);
|
||||
drawCenteredString(font, "https://github.com/ViaVersion/ViaForge", width / 2, (font.lineHeight + 2) * 2 + 3, -1);
|
||||
drawString(font, status != null ? status : "Discord: florianmichael", 3, 3, -1);
|
||||
}
|
||||
|
||||
static class SlotList extends ExtendedList<SlotList.SlotEntry> {
|
||||
class SlotList extends ExtendedList<SlotList.SlotEntry> {
|
||||
|
||||
public SlotList(Minecraft p_i51146_1_, int p_i51146_2_, int p_i51146_3_, int p_i51146_4_, int p_i51146_5_, int p_i51146_6_) {
|
||||
super(p_i51146_1_, p_i51146_2_, p_i51146_3_, p_i51146_4_, p_i51146_5_, p_i51146_6_);
|
||||
public SlotList(Minecraft client, int width, int height, int top, int bottom, int slotHeight) {
|
||||
super(client, width, height, top, bottom, slotHeight);
|
||||
|
||||
for (VersionEnum version : VersionEnum.SORTED_VERSIONS) {
|
||||
addEntry(new SlotEntry(version));
|
||||
@ -87,16 +134,29 @@ public class GuiProtocolSelector extends Screen {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double p_231044_1_, double p_231044_3_, int p_231044_5_) {
|
||||
ViaForgeCommon.getManager().setTargetVersion(versionEnum);
|
||||
return super.mouseClicked(p_231044_1_, p_231044_3_, p_231044_5_);
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
GuiProtocolSelector.this.finishedCallback.finished(versionEnum, GuiProtocolSelector.this.parent);
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int p_230432_2_, int p_230432_3_, int p_230432_4_, int p_230432_5_, int p_230432_6_, int p_230432_7_, int p_230432_8_, boolean p_230432_9_, float p_230432_10_) {
|
||||
drawCenteredString(Minecraft.getInstance().font,
|
||||
(ViaForgeCommon.getManager().getTargetVersion() == versionEnum ? TextFormatting.GREEN.toString() : TextFormatting.DARK_RED.toString()) + versionEnum.getName(), width / 2, p_230432_3_, -1);
|
||||
public void render(int p_230432_2_, int y, int p_230432_4_, int p_230432_5_, int p_230432_6_, int p_230432_7_, int p_230432_8_, boolean p_230432_9_, float p_230432_10_) {
|
||||
final VersionEnum targetVersion = ViaForgeCommon.getManager().getTargetVersion();
|
||||
|
||||
String color;
|
||||
if (targetVersion == versionEnum) {
|
||||
color = GuiProtocolSelector.this.simple ? ChatFormatting.GOLD.toString() : ChatFormatting.GREEN.toString();
|
||||
} else {
|
||||
color = GuiProtocolSelector.this.simple ? ChatFormatting.WHITE.toString() : ChatFormatting.DARK_RED.toString();
|
||||
}
|
||||
|
||||
drawCenteredString(Minecraft.getInstance().font, color + versionEnum.getName(), width / 2, y, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface FinishedCallback {
|
||||
|
||||
void finished(final VersionEnum version, final Screen parent);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.screen.AddServerScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
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(AddServerScreen.class)
|
||||
public class MixinAddServerScreen extends Screen {
|
||||
|
||||
@Shadow @Final private ServerData serverData;
|
||||
|
||||
public MixinAddServerScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void initGui(CallbackInfo ci) {
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
|
||||
if (config.isShowAddServerButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getAddServerScreenButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
final VersionEnum target = ((ExtendedServerData) serverData).viaforge_getVersion();
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, target != null ? target.getName() : "Set Version", b -> {
|
||||
minecraft.setScreen(new GuiProtocolSelector(this, true, (version, parent) -> {
|
||||
// Set version and go back to the parent screen.
|
||||
((ExtendedServerData) serverData).viaforge_setVersion(version);
|
||||
minecraft.setScreen(parent);
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.login.ClientLoginNetHandler;
|
||||
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(ClientLoginNetHandler.class)
|
||||
public class MixinClientLoginNetHandler {
|
||||
|
||||
@Shadow @Final private NetworkManager connection;
|
||||
|
||||
@Redirect(method = "authenticateServer", 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 = connection.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);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.gui.screen.ConnectingScreen$1")
|
||||
public class MixinConnectingScreen_1 {
|
||||
|
||||
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;connectToServer(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.getInstance().getCurrentServer() instanceof ExtendedServerData) {
|
||||
final VersionEnum version = ((ExtendedServerData) Minecraft.getInstance().getCurrentServer()).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.connectToServer(address, i, b);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.gui.overlay.DebugOverlayGui;
|
||||
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(DebugOverlayGui.class)
|
||||
public class MixinDebugOverlayGui {
|
||||
|
||||
@Inject(method = "getSystemInformation", at = @At(value = "TAIL"))
|
||||
public void addViaForgeVersion(CallbackInfoReturnable<List<String>> 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 + ")");
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import de.florianmichael.viaforge.ViaForge115;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
|
||||
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
|
||||
import net.minecraft.client.gui.screen.MainMenuScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
@ -32,16 +34,19 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(MainMenuScreen.class)
|
||||
public class MixinMainMenuScreen extends Screen {
|
||||
|
||||
public MixinMainMenuScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinMainMenuScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("HEAD"))
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
ViaForgeCommon.init(ViaForge115.PLATFORM);
|
||||
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMainMenuButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, "ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, "ViaForge", buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.ViaForge115;
|
||||
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.screen.MultiplayerScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
@ -32,14 +33,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(MultiplayerScreen.class)
|
||||
public class MixinMultiplayerScreen extends Screen {
|
||||
|
||||
protected MixinMultiplayerScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinMultiplayerScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMultiplayerButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, "ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, "ViaForge", buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,22 +18,89 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.LazyValue;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
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 = "connectToServer", 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 p_181124_0_, int p_181124_1_, boolean p_181124_2_, CallbackInfoReturnable<NetworkManager> cir, NetworkManager networkmanager, Class oclass, LazyValue lazyvalue) {
|
||||
// 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 = "setEncryptionKey", 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.getCipher(2, key);
|
||||
|
||||
// Enabling the encryption side
|
||||
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new NettyEncryptingEncoder(CryptManager.getCipher(1, key)));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "disconnect", at = @At("HEAD"))
|
||||
public void restoreTargetVersion(ITextComponent p_150718_1_, CallbackInfo ci) {
|
||||
// If the previous server forced a version, we need to restore the version to the default one.
|
||||
ViaForgeCommon.getManager().restoreVersion();
|
||||
}
|
||||
|
||||
@Inject(method = "setupCompression", at = @At("RETURN"))
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -18,17 +18,25 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
|
||||
import io.netty.channel.Channel;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(targets = "net.minecraft.network.NetworkManager$1", remap = false)
|
||||
@Mixin(targets = "net.minecraft.network.NetworkManager$1")
|
||||
public class MixinNetworkManager_1 {
|
||||
|
||||
@Final
|
||||
@Mutable
|
||||
NetworkManager val$networkmanager;
|
||||
|
||||
@Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false)
|
||||
private void onInitChannel(Channel channel, CallbackInfo ci) {
|
||||
ViaForgeCommon.getManager().inject(channel);
|
||||
ViaForgeCommon.getManager().inject(channel, (VFNetworkManager) val$networkmanager);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
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 = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundNBT;putString(Ljava/lang/String;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void saveVersion(CallbackInfoReturnable<CompoundNBT> cir, CompoundNBT compoundnbt) {
|
||||
if (viaforge_version != null) {
|
||||
compoundnbt.putInt("viaforge_version", viaforge_version.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "read", at = @At(value = "TAIL"))
|
||||
private static void getVersion(CompoundNBT compoundnbt, CallbackInfoReturnable<ServerData> cir) {
|
||||
if (compoundnbt.contains("viaforge_version")) {
|
||||
((ExtendedServerData) cir.getReturnValue()).viaforge_setVersion(VersionEnum.fromProtocolId(compoundnbt.getInt("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;
|
||||
}
|
||||
}
|
@ -17,7 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ServerListScreen;
|
||||
@ -31,14 +33,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(ServerListScreen.class)
|
||||
public class MixinServerListScreen extends Screen {
|
||||
|
||||
protected MixinServerListScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinServerListScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowDirectConnectButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, "ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowDirectConnectButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, "ViaForge", b -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.network.ServerPinger;
|
||||
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(ServerPinger.class)
|
||||
public class MixinServerPinger {
|
||||
|
||||
@Unique
|
||||
private ServerData viaforge_serverData;
|
||||
|
||||
@Inject(method = "pingServer", at = @At("HEAD"))
|
||||
public void trackServerData(ServerData server, CallbackInfo ci) {
|
||||
viaforge_serverData = server;
|
||||
}
|
||||
|
||||
@Redirect(method = "pingServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;connectToServer(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.connectToServer(address, i, b);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin.fixes;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.entity.player.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
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;
|
||||
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
public class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
|
||||
|
||||
@Shadow private boolean lastOnGround;
|
||||
|
||||
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
|
||||
super(world, profile);
|
||||
}
|
||||
|
||||
@Redirect(method = "sendPosition", at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/player/ClientPlayerEntity;lastOnGround:Z", ordinal = 0))
|
||||
public boolean emulateIdlePacket(ClientPlayerEntity instance) {
|
||||
if (ViaForgeCommon.getManager().getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
||||
// <= 1.8 spams the idle packet instead of only sending it when the ground state changes
|
||||
// So we invert the original logic:
|
||||
// if (prevOnGround != onGround) sendPacket
|
||||
// To be like:
|
||||
// if (!onGround != onGround) sendPacket
|
||||
// Which is the same as:
|
||||
// if (true) sendPacket
|
||||
return !onGround;
|
||||
}
|
||||
return lastOnGround;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -3,12 +3,19 @@
|
||||
"minVersion": "0.7.5",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"mixins": [
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"client": [
|
||||
"MixinAddServerScreen",
|
||||
"MixinClientLoginNetHandler",
|
||||
"MixinConnectingScreen_1",
|
||||
"MixinDebugOverlayGui",
|
||||
"MixinMainMenuScreen",
|
||||
"MixinMultiplayerScreen",
|
||||
"MixinServerListScreen"
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"MixinServerData",
|
||||
"MixinServerListScreen",
|
||||
"MixinServerPinger",
|
||||
"fixes.MixinClientPlayerEntity"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
@ -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.util.Session;
|
||||
import net.minecraft.util.SharedConstants;
|
||||
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;
|
||||
@ -44,4 +47,16 @@ public class ViaForge116 implements VFPlatform {
|
||||
public File getLeadingDirectory() {
|
||||
return Minecraft.getInstance().gameDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinServer(String serverId) throws Throwable {
|
||||
final Session session = Minecraft.getInstance().getUser();
|
||||
|
||||
Minecraft.getInstance().getMinecraftSessionService().joinServer(session.getGameProfile(), session.getAccessToken(), serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfileFetcher getGameProfileFetcher() {
|
||||
return new ViaForgeGameProfileFetcher();
|
||||
}
|
||||
}
|
||||
|
@ -18,61 +18,108 @@
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import de.florianmichael.viaforge.ViaForge116;
|
||||
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.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.gui.widget.list.AbstractList;
|
||||
import net.minecraft.client.gui.widget.list.ExtendedList;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class GuiProtocolSelector extends Screen {
|
||||
|
||||
private final Screen parent;
|
||||
public final Screen parent;
|
||||
public final boolean simple;
|
||||
public final FinishedCallback finishedCallback;
|
||||
|
||||
private SlotList list;
|
||||
|
||||
private String status;
|
||||
private long time;
|
||||
|
||||
public static void open(final Minecraft minecraft) { // Bypass for some weird bytecode instructions errors in Forge
|
||||
minecraft.setScreen(new GuiProtocolSelector(minecraft.screen));
|
||||
}
|
||||
|
||||
private SlotList slotList;
|
||||
public GuiProtocolSelector(final Screen 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(Screen parent) {
|
||||
super(ITextComponent.nullToEmpty("ViaForge Protocol Selector"));
|
||||
public GuiProtocolSelector(final Screen parent, final boolean simple, final FinishedCallback finishedCallback) {
|
||||
super(new StringTextComponent("ViaForge Protocol Selector"));
|
||||
this.parent = parent;
|
||||
this.simple = simple;
|
||||
this.finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
public void init() {
|
||||
super.init();
|
||||
addButton(new Button(5, height - 25, 20, 20, new StringTextComponent("<-"), b -> minecraft.setScreen(parent)));
|
||||
if (!this.simple) {
|
||||
addButton(new Button(width - 105, 5, 100, 20, new StringTextComponent("Create dump"), b -> {
|
||||
try {
|
||||
minecraft.keyboardHandler.setClipboard(DumpUtil.postDump(UUID.randomUUID()).get());
|
||||
setStatus(TextFormatting.GREEN + "Dump created and copied to clipboard");
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
setStatus(TextFormatting.RED + "Failed to create dump: " + e.getMessage());
|
||||
}
|
||||
}));
|
||||
addButton(new Button(width - 105, height - 25, 100, 20, new StringTextComponent("Reload configs"), b -> Via.getManager().getConfigurationProvider().reloadConfigs()));
|
||||
}
|
||||
|
||||
addWidget(slotList = new SlotList(minecraft, width, height, 32, height - 32, 10));
|
||||
addButton(new Button(width / 2 - 100, height - 27, 200, 20, ITextComponent.nullToEmpty("Back"), b -> minecraft.setScreen(parent)));
|
||||
list = new SlotList(minecraft, width, height, 3 + 3 /* start offset */ + (font.lineHeight + 2) * 3 /* title is 2 */, height - 30, font.lineHeight + 2);
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
this.time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack p_230430_1_, int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
renderBackground(p_230430_1_);
|
||||
this.slotList.render(p_230430_1_, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
public boolean keyPressed(int keyCode, int scanCode, int actions) {
|
||||
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||
minecraft.setScreen(parent);
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, actions);
|
||||
}
|
||||
|
||||
super.render(p_230430_1_, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
if (System.currentTimeMillis() - this.time >= 10_000) {
|
||||
this.status = null;
|
||||
}
|
||||
|
||||
renderBackground(matrices);
|
||||
this.list.render(matrices, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
super.render(matrices, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScalef(2.0F, 2.0F, 2.0F);
|
||||
drawCenteredString(p_230430_1_, this.font, ITextComponent.nullToEmpty(TextFormatting.GOLD + "ViaForge"), this.width / 4, 6, 16777215);
|
||||
drawCenteredString(matrices, font, TextFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
|
||||
GL11.glPopMatrix();
|
||||
|
||||
drawString(p_230430_1_, this.font, "by https://github.com/ViaVersion/ViaForge", 1, 1, -1);
|
||||
drawString(p_230430_1_, this.font, "Discord: florianmichael", 1, 11, -1);
|
||||
drawCenteredString(matrices, font, "https://github.com/ViaVersion/ViaForge", width / 2, (font.lineHeight + 2) * 2 + 3, -1);
|
||||
drawString(matrices, font, status != null ? status : "Discord: florianmichael", 3, 3, -1);
|
||||
}
|
||||
|
||||
static class SlotList extends ExtendedList<SlotList.SlotEntry> {
|
||||
class SlotList extends ExtendedList<SlotList.SlotEntry> {
|
||||
|
||||
public SlotList(Minecraft p_i51146_1_, int p_i51146_2_, int p_i51146_3_, int p_i51146_4_, int p_i51146_5_, int p_i51146_6_) {
|
||||
super(p_i51146_1_, p_i51146_2_, p_i51146_3_, p_i51146_4_, p_i51146_5_, p_i51146_6_);
|
||||
public SlotList(Minecraft client, int width, int height, int top, int bottom, int slotHeight) {
|
||||
super(client, width, height, top, bottom, slotHeight);
|
||||
|
||||
for (VersionEnum version : VersionEnum.SORTED_VERSIONS) {
|
||||
addEntry(new SlotEntry(version));
|
||||
@ -88,16 +135,29 @@ public class GuiProtocolSelector extends Screen {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double p_231044_1_, double p_231044_3_, int p_231044_5_) {
|
||||
ViaForgeCommon.getManager().setTargetVersion(versionEnum);
|
||||
return super.mouseClicked(p_231044_1_, p_231044_3_, p_231044_5_);
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
GuiProtocolSelector.this.finishedCallback.finished(versionEnum, GuiProtocolSelector.this.parent);
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack p_230432_1_, int p_230432_2_, int p_230432_3_, int p_230432_4_, int p_230432_5_, int p_230432_6_, int p_230432_7_, int p_230432_8_, boolean p_230432_9_, float p_230432_10_) {
|
||||
drawCenteredString(p_230432_1_, Minecraft.getInstance().font,
|
||||
(ViaForgeCommon.getManager().getTargetVersion() == versionEnum ? TextFormatting.GREEN.toString() : TextFormatting.DARK_RED.toString()) + versionEnum.getName(), width / 2, p_230432_3_, -1);
|
||||
public void render(MatrixStack matrices, int p_230432_2_, int y, int p_230432_4_, int p_230432_5_, int p_230432_6_, int p_230432_7_, int p_230432_8_, boolean p_230432_9_, float p_230432_10_) {
|
||||
final VersionEnum targetVersion = ViaForgeCommon.getManager().getTargetVersion();
|
||||
|
||||
String color;
|
||||
if (targetVersion == versionEnum) {
|
||||
color = GuiProtocolSelector.this.simple ? TextFormatting.GOLD.toString() : TextFormatting.GREEN.toString();
|
||||
} else {
|
||||
color = GuiProtocolSelector.this.simple ? TextFormatting.WHITE.toString() : TextFormatting.DARK_RED.toString();
|
||||
}
|
||||
|
||||
drawCenteredString(matrices, Minecraft.getInstance().font, color + versionEnum.getName(), width / 2, y, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface FinishedCallback {
|
||||
|
||||
void finished(final VersionEnum version, final Screen parent);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.screen.AddServerScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
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(AddServerScreen.class)
|
||||
public class MixinAddServerScreen extends Screen {
|
||||
|
||||
@Shadow @Final private ServerData serverData;
|
||||
|
||||
public MixinAddServerScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void initGui(CallbackInfo ci) {
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
|
||||
if (config.isShowAddServerButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getAddServerScreenButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
final VersionEnum target = ((ExtendedServerData) serverData).viaforge_getVersion();
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, new StringTextComponent(target != null ? target.getName() : "Set Version"), b -> {
|
||||
minecraft.setScreen(new GuiProtocolSelector(this, true, (version, parent) -> {
|
||||
// Set version and go back to the parent screen.
|
||||
((ExtendedServerData) serverData).viaforge_setVersion(version);
|
||||
minecraft.setScreen(parent);
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.login.ClientLoginNetHandler;
|
||||
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(ClientLoginNetHandler.class)
|
||||
public class MixinClientLoginNetHandler {
|
||||
|
||||
@Shadow @Final private NetworkManager connection;
|
||||
|
||||
@Redirect(method = "authenticateServer", 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 = connection.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);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.gui.screen.ConnectingScreen$1")
|
||||
public class MixinConnectingScreen_1 {
|
||||
|
||||
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;connectToServer(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.getInstance().getCurrentServer() instanceof ExtendedServerData) {
|
||||
final VersionEnum version = ((ExtendedServerData) Minecraft.getInstance().getCurrentServer()).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.connectToServer(address, i, b);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.gui.overlay.DebugOverlayGui;
|
||||
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(DebugOverlayGui.class)
|
||||
public class MixinDebugOverlayGui {
|
||||
|
||||
@Inject(method = "getSystemInformation", at = @At(value = "TAIL"))
|
||||
public void addViaForgeVersion(CallbackInfoReturnable<List<String>> 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 + ")");
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import de.florianmichael.viaforge.ViaForge116;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
|
||||
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
|
||||
import net.minecraft.client.gui.screen.MainMenuScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
@ -33,16 +35,19 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(MainMenuScreen.class)
|
||||
public class MixinMainMenuScreen extends Screen {
|
||||
|
||||
public MixinMainMenuScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinMainMenuScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("HEAD"))
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
ViaForgeCommon.init(ViaForge116.PLATFORM);
|
||||
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMainMenuButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, new StringTextComponent("ViaForge"), b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, new StringTextComponent("ViaForge"), buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,15 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.screen.MultiplayerScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@ -31,14 +34,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(MultiplayerScreen.class)
|
||||
public class MixinMultiplayerScreen extends Screen {
|
||||
|
||||
protected MixinMultiplayerScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinMultiplayerScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMultiplayerButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, ITextComponent.nullToEmpty("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, new StringTextComponent("ViaForge"), buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,22 +18,89 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.LazyValue;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
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 = "connectToServer", 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 p_181124_0_, int p_181124_1_, boolean p_181124_2_, CallbackInfoReturnable<NetworkManager> cir, NetworkManager networkmanager, Class oclass, LazyValue lazyvalue) {
|
||||
// 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 = "setEncryptionKey", at = @At("HEAD"), cancellable = true)
|
||||
private void storeEncryptionCiphers(Cipher p_244777_1_, Cipher p_244777_2_, 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 = p_244777_1_;
|
||||
|
||||
// Enabling the encryption side
|
||||
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new NettyEncryptingEncoder(p_244777_2_));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "disconnect", at = @At("HEAD"))
|
||||
public void restoreTargetVersion(ITextComponent p_150718_1_, CallbackInfo ci) {
|
||||
// If the previous server forced a version, we need to restore the version to the default one.
|
||||
ViaForgeCommon.getManager().restoreVersion();
|
||||
}
|
||||
|
||||
@Inject(method = "setupCompression", at = @At("RETURN"))
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -18,17 +18,25 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
|
||||
import io.netty.channel.Channel;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(targets = "net.minecraft.network.NetworkManager$1", remap = false)
|
||||
@Mixin(targets = "net.minecraft.network.NetworkManager$1")
|
||||
public class MixinNetworkManager_1 {
|
||||
|
||||
@Final
|
||||
@Mutable
|
||||
NetworkManager val$networkmanager;
|
||||
|
||||
@Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false)
|
||||
private void onInitChannel(Channel channel, CallbackInfo ci) {
|
||||
ViaForgeCommon.getManager().inject(channel);
|
||||
ViaForgeCommon.getManager().inject(channel, (VFNetworkManager) val$networkmanager);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
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 = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundNBT;putString(Ljava/lang/String;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void saveVersion(CallbackInfoReturnable<CompoundNBT> cir, CompoundNBT compoundnbt) {
|
||||
if (viaforge_version != null) {
|
||||
compoundnbt.putInt("viaforge_version", viaforge_version.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "read", at = @At(value = "TAIL"))
|
||||
private static void getVersion(CompoundNBT compoundnbt, CallbackInfoReturnable<ServerData> cir) {
|
||||
if (compoundnbt.contains("viaforge_version")) {
|
||||
((ExtendedServerData) cir.getReturnValue()).viaforge_setVersion(VersionEnum.fromProtocolId(compoundnbt.getInt("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;
|
||||
}
|
||||
}
|
@ -17,13 +17,15 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.ViaForge116;
|
||||
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.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ServerListScreen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@ -32,14 +34,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(ServerListScreen.class)
|
||||
public class MixinServerListScreen extends Screen {
|
||||
|
||||
protected MixinServerListScreen(ITextComponent p_i51108_1_) {
|
||||
super(p_i51108_1_);
|
||||
public MixinServerListScreen(ITextComponent title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowDirectConnectButton()) {
|
||||
addButton(new Button(5, 6, 98, 20, ITextComponent.nullToEmpty("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowDirectConnectButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addButton(new Button(pos.key(), pos.value(), 100, 20, new StringTextComponent("ViaForge"), b -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.network.ServerPinger;
|
||||
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(ServerPinger.class)
|
||||
public class MixinServerPinger {
|
||||
|
||||
@Unique
|
||||
private ServerData viaforge_serverData;
|
||||
|
||||
@Inject(method = "pingServer", at = @At("HEAD"))
|
||||
public void trackServerData(ServerData server, Runnable p_147224_2_, CallbackInfo ci) {
|
||||
viaforge_serverData = server;
|
||||
}
|
||||
|
||||
@Redirect(method = "pingServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkManager;connectToServer(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.connectToServer(address, i, b);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin.fixes;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.entity.player.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
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;
|
||||
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
public class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
|
||||
|
||||
@Shadow private boolean lastOnGround;
|
||||
|
||||
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
|
||||
super(world, profile);
|
||||
}
|
||||
|
||||
@Redirect(method = "sendPosition", at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/player/ClientPlayerEntity;lastOnGround:Z", ordinal = 0))
|
||||
public boolean emulateIdlePacket(ClientPlayerEntity instance) {
|
||||
if (ViaForgeCommon.getManager().getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
||||
// <= 1.8 spams the idle packet instead of only sending it when the ground state changes
|
||||
// So we invert the original logic:
|
||||
// if (prevOnGround != onGround) sendPacket
|
||||
// To be like:
|
||||
// if (!onGround != onGround) sendPacket
|
||||
// Which is the same as:
|
||||
// if (true) sendPacket
|
||||
return !onGround;
|
||||
}
|
||||
return lastOnGround;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -3,12 +3,19 @@
|
||||
"minVersion": "0.7.5",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"mixins": [
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"client": [
|
||||
"MixinAddServerScreen",
|
||||
"MixinClientLoginNetHandler",
|
||||
"MixinConnectingScreen_1",
|
||||
"MixinDebugOverlayGui",
|
||||
"MixinMainMenuScreen",
|
||||
"MixinMultiplayerScreen",
|
||||
"MixinServerListScreen"
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"MixinServerData",
|
||||
"MixinServerListScreen",
|
||||
"MixinServerPinger",
|
||||
"fixes.MixinClientPlayerEntity"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
@ -18,9 +18,12 @@
|
||||
package de.florianmichael.viaforge;
|
||||
|
||||
import de.florianmichael.viaforge.common.platform.VFPlatform;
|
||||
import de.florianmichael.viaforge.provider.ViaForgeGameProfileFetcher;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.User;
|
||||
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;
|
||||
@ -44,4 +47,16 @@ public class ViaForge117 implements VFPlatform {
|
||||
public File getLeadingDirectory() {
|
||||
return Minecraft.getInstance().gameDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinServer(String serverId) throws Throwable {
|
||||
final User session = Minecraft.getInstance().getUser();
|
||||
|
||||
Minecraft.getInstance().getMinecraftSessionService().joinServer(session.getGameProfile(), session.getAccessToken(), serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfileFetcher getGameProfileFetcher() {
|
||||
return new ViaForgeGameProfileFetcher();
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,10 @@
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import de.florianmichael.viaforge.ViaForge117;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.util.DumpUtil;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.lenni0451.mcstructs.core.TextFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.ObjectSelectionList;
|
||||
@ -28,51 +29,97 @@ import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class GuiProtocolSelector extends Screen {
|
||||
|
||||
private final Screen parent;
|
||||
public final Screen parent;
|
||||
public final boolean simple;
|
||||
public final FinishedCallback finishedCallback;
|
||||
|
||||
private SlotList list;
|
||||
|
||||
private String status;
|
||||
private long time;
|
||||
|
||||
public static void open(final Minecraft minecraft) { // Bypass for some weird bytecode instructions errors in Forge
|
||||
minecraft.setScreen(new GuiProtocolSelector(minecraft.screen));
|
||||
}
|
||||
|
||||
private SlotList slotList;
|
||||
public GuiProtocolSelector(final Screen 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(Screen parent) {
|
||||
public GuiProtocolSelector(final Screen parent, final boolean simple, final FinishedCallback finishedCallback) {
|
||||
super(new TextComponent("ViaForge Protocol Selector"));
|
||||
this.parent = parent;
|
||||
this.simple = simple;
|
||||
this.finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
public void init() {
|
||||
super.init();
|
||||
addRenderableWidget(new Button(5, height - 25, 20, 20, new TextComponent("<-"), b -> minecraft.setScreen(parent)));
|
||||
if (!this.simple) {
|
||||
addRenderableWidget(new Button(width - 105, 5, 100, 20, new TextComponent("Create dump"), b -> {
|
||||
try {
|
||||
minecraft.keyboardHandler.setClipboard(DumpUtil.postDump(UUID.randomUUID()).get());
|
||||
setStatus(TextFormatting.GREEN + "Dump created and copied to clipboard");
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
setStatus(TextFormatting.RED + "Failed to create dump: " + e.getMessage());
|
||||
}
|
||||
}));
|
||||
addRenderableWidget(new Button(width - 105, height - 25, 100, 20, new TextComponent("Reload configs"), b -> Via.getManager().getConfigurationProvider().reloadConfigs()));
|
||||
}
|
||||
|
||||
addWidget(slotList = new SlotList(minecraft, width, height, 32, height - 32, 10));
|
||||
addRenderableWidget(new Button(width / 2 - 100, height - 27, 200, 20, new TextComponent("Back"), b -> minecraft.setScreen(parent)));
|
||||
list = new SlotList(minecraft, width, height, 3 + 3 /* start offset */ + (font.lineHeight + 2) * 3 /* title is 2 */, height - 30, font.lineHeight + 2);
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
this.time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack p_230430_1_, int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
renderBackground(p_230430_1_);
|
||||
this.slotList.render(p_230430_1_, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
public boolean keyPressed(int keyCode, int scanCode, int actions) {
|
||||
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||
minecraft.setScreen(parent);
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, actions);
|
||||
}
|
||||
|
||||
super.render(p_230430_1_, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
@Override
|
||||
public void render(PoseStack matrices, int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
if (System.currentTimeMillis() - this.time >= 10_000) {
|
||||
this.status = null;
|
||||
}
|
||||
|
||||
renderBackground(matrices);
|
||||
this.list.render(matrices, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
super.render(matrices, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScalef(2.0F, 2.0F, 2.0F);
|
||||
drawCenteredString(p_230430_1_, this.font, new TextComponent(ChatFormatting.GOLD + "ViaForge"), this.width / 4, 6, 16777215);
|
||||
drawCenteredString(matrices, font, TextFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
|
||||
GL11.glPopMatrix();
|
||||
|
||||
drawString(p_230430_1_, this.font, "by https://github.com/ViaVersion/ViaForge", 1, 1, -1);
|
||||
drawString(p_230430_1_, this.font, "Discord: florianmichael", 1, 11, -1);
|
||||
drawCenteredString(matrices, font, "https://github.com/ViaVersion/ViaForge", width / 2, (font.lineHeight + 2) * 2 + 3, -1);
|
||||
drawString(matrices, font, status != null ? status : "Discord: florianmichael", 3, 3, -1);
|
||||
}
|
||||
|
||||
static class SlotList extends ObjectSelectionList<SlotList.SlotEntry> {
|
||||
class SlotList extends ObjectSelectionList<SlotList.SlotEntry> {
|
||||
|
||||
public SlotList(Minecraft p_i51146_1_, int p_i51146_2_, int p_i51146_3_, int p_i51146_4_, int p_i51146_5_, int p_i51146_6_) {
|
||||
super(p_i51146_1_, p_i51146_2_, p_i51146_3_, p_i51146_4_, p_i51146_5_, p_i51146_6_);
|
||||
public SlotList(Minecraft client, int width, int height, int top, int bottom, int slotHeight) {
|
||||
super(client, width, height, top, bottom, slotHeight);
|
||||
|
||||
for (VersionEnum version : VersionEnum.SORTED_VERSIONS) {
|
||||
addEntry(new SlotEntry(version));
|
||||
@ -88,21 +135,34 @@ public class GuiProtocolSelector extends Screen {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double p_231044_1_, double p_231044_3_, int p_231044_5_) {
|
||||
ViaForgeCommon.getManager().setTargetVersion(versionEnum);
|
||||
return super.mouseClicked(p_231044_1_, p_231044_3_, p_231044_5_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack p_230432_1_, int p_230432_2_, int p_230432_3_, int p_230432_4_, int p_230432_5_, int p_230432_6_, int p_230432_7_, int p_230432_8_, boolean p_230432_9_, float p_230432_10_) {
|
||||
drawCenteredString(p_230432_1_, Minecraft.getInstance().font,
|
||||
(ViaForgeCommon.getManager().getTargetVersion() == versionEnum ? ChatFormatting.GREEN.toString() : ChatFormatting.DARK_RED.toString()) + versionEnum.getName(), width / 2, p_230432_3_, -1);
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
GuiProtocolSelector.this.finishedCallback.finished(versionEnum, GuiProtocolSelector.this.parent);
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getNarration() {
|
||||
return new TextComponent(versionEnum.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack matrices, int p_93524_, int y, int p_93526_, int p_93527_, int p_93528_, int p_93529_, int p_93530_, boolean p_93531_, float p_93532_) {
|
||||
final VersionEnum targetVersion = ViaForgeCommon.getManager().getTargetVersion();
|
||||
|
||||
String color;
|
||||
if (targetVersion == versionEnum) {
|
||||
color = GuiProtocolSelector.this.simple ? TextFormatting.GOLD.toString() : TextFormatting.GREEN.toString();
|
||||
} else {
|
||||
color = GuiProtocolSelector.this.simple ? TextFormatting.WHITE.toString() : TextFormatting.DARK_RED.toString();
|
||||
}
|
||||
|
||||
drawCenteredString(matrices, Minecraft.getInstance().font, color + versionEnum.getName(), width / 2, y, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface FinishedCallback {
|
||||
|
||||
void finished(final VersionEnum version, final Screen parent);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.multiplayer.ClientHandshakePacketListenerImpl;
|
||||
import net.minecraft.network.Connection;
|
||||
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(ClientHandshakePacketListenerImpl.class)
|
||||
public class MixinClientHandshakePacketListenerImpl {
|
||||
|
||||
@Shadow @Final private Connection connection;
|
||||
|
||||
@Redirect(method = "authenticateServer", 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 = connection.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);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.Connection;
|
||||
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.InetSocketAddress;
|
||||
|
||||
@Mixin(targets = "net.minecraft.client.gui.screens.ConnectScreen$1")
|
||||
public class MixinConnectScreen_1 {
|
||||
|
||||
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;connectToServer(Ljava/net/InetSocketAddress;Z)Lnet/minecraft/network/Connection;"))
|
||||
public Connection trackVersion(InetSocketAddress oclass, boolean lazyloadedvalue) {
|
||||
// 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.getInstance().getCurrentServer() instanceof ExtendedServerData) {
|
||||
final VersionEnum version = ((ExtendedServerData) Minecraft.getInstance().getCurrentServer()).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 Connection.connectToServer(oclass, lazyloadedvalue);
|
||||
}
|
||||
}
|
@ -18,22 +18,86 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
|
||||
import io.netty.channel.Channel;
|
||||
import net.minecraft.network.CipherDecoder;
|
||||
import net.minecraft.network.CipherEncoder;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.raphimc.vialoader.netty.CompressionReorderEvent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
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 java.net.InetSocketAddress;
|
||||
|
||||
@Mixin(Connection.class)
|
||||
public class MixinConnection {
|
||||
public class MixinConnection implements VFNetworkManager {
|
||||
|
||||
@Shadow private Channel channel;
|
||||
|
||||
@Unique
|
||||
private Cipher viaforge_decryptionCipher;
|
||||
|
||||
@Unique
|
||||
private VersionEnum viaforge_targetVersion;
|
||||
|
||||
@Inject(method = "connectToServer", 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(InetSocketAddress p_178301_, boolean p_178302_, CallbackInfoReturnable<Connection> cir, final Connection connection) {
|
||||
// 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) connection).viaforge_setTrackedVersion(ViaForgeCommon.getManager().getTargetVersion());
|
||||
}
|
||||
|
||||
@Inject(method = "setEncryptionKey", at = @At("HEAD"), cancellable = true)
|
||||
private void storeEncryptionCiphers(Cipher p_244777_1_, Cipher p_244777_2_, 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 = p_244777_1_;
|
||||
|
||||
// Enabling the encryption side
|
||||
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new CipherEncoder(p_244777_2_));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "disconnect", at = @At("HEAD"))
|
||||
public void restoreTargetVersion(Component p_129508_, CallbackInfo ci) {
|
||||
// If the previous server forced a version, we need to restore the version to the default one.
|
||||
ViaForgeCommon.getManager().restoreVersion();
|
||||
}
|
||||
|
||||
@Inject(method = "setupCompression", at = @At("RETURN"))
|
||||
public void reorderPipeline(int p_129485_, boolean p_182682_, 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 CipherDecoder(this.viaforge_decryptionCipher));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VersionEnum viaforge_getTrackedVersion() {
|
||||
return viaforge_targetVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viaforge_setTrackedVersion(VersionEnum version) {
|
||||
viaforge_targetVersion = version;
|
||||
}
|
||||
}
|
||||
|
@ -18,17 +18,25 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
|
||||
import io.netty.channel.Channel;
|
||||
import net.minecraft.network.Connection;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(targets = "net.minecraft.network.Connection$1", remap = false)
|
||||
@Mixin(targets = "net.minecraft.network.Connection$1")
|
||||
public class MixinConnection_1 {
|
||||
|
||||
@Final
|
||||
@Mutable
|
||||
Connection val$connection;
|
||||
|
||||
@Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false)
|
||||
private void onInitChannel(Channel channel, CallbackInfo ci) {
|
||||
ViaForgeCommon.getManager().inject(channel);
|
||||
ViaForgeCommon.getManager().inject(channel, (VFNetworkManager) val$connection);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.gui.components.DebugScreenOverlay;
|
||||
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(DebugScreenOverlay.class)
|
||||
public class MixinDebugScreenOverlay {
|
||||
|
||||
@Inject(method = "getSystemInformation", at = @At(value = "TAIL"))
|
||||
public void addViaForgeVersion(CallbackInfoReturnable<List<String>> 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 + ")");
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.ViaForge117;
|
||||
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.components.Button;
|
||||
import net.minecraft.client.gui.screens.DirectJoinServerScreen;
|
||||
@ -33,14 +34,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(DirectJoinServerScreen.class)
|
||||
public class MixinDirectJoinServerScreen extends Screen {
|
||||
|
||||
protected MixinDirectJoinServerScreen(Component p_96550_) {
|
||||
super(p_96550_);
|
||||
public MixinDirectJoinServerScreen(Component title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowDirectConnectButton()) {
|
||||
addRenderableWidget(new Button(5, 6, 98, 20, new TextComponent("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowDirectConnectButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addRenderableWidget(new Button(pos.key(), pos.value(), 100, 20, new TextComponent("ViaForge"), b -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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.components.Button;
|
||||
import net.minecraft.client.gui.screens.EditServerScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
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(EditServerScreen.class)
|
||||
public class MixinEditServerScreen extends Screen {
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private ServerData serverData;
|
||||
|
||||
public MixinEditServerScreen(Component title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void initGui(CallbackInfo ci) {
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
|
||||
if (config.isShowAddServerButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getAddServerScreenButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
final VersionEnum target = ((ExtendedServerData) serverData).viaforge_getVersion();
|
||||
addRenderableWidget(new Button(pos.key(), pos.value(), 100, 20, new TextComponent(target != null ? target.getName() : "Set Version"), b -> {
|
||||
minecraft.setScreen(new GuiProtocolSelector(this, true, (version, parent) -> {
|
||||
// Set version and go back to the parent screen.
|
||||
((ExtendedServerData) serverData).viaforge_setVersion(version);
|
||||
minecraft.setScreen(parent);
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.ViaForge117;
|
||||
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.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
@ -33,14 +34,17 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(JoinMultiplayerScreen.class)
|
||||
public class MixinJoinMultiplayerScreen extends Screen {
|
||||
|
||||
protected MixinJoinMultiplayerScreen(Component p_96550_) {
|
||||
super(p_96550_);
|
||||
public MixinJoinMultiplayerScreen(Component title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMultiplayerButton()) {
|
||||
addRenderableWidget(new Button(5, 6, 98, 20, new TextComponent("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addRenderableWidget(new Button(pos.key(), pos.value(), 100, 20, new TextComponent("ViaForge"), buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
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 = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;putString(Ljava/lang/String;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
public void saveVersion(CallbackInfoReturnable<CompoundTag> cir, CompoundTag compoundtag) {
|
||||
if (viaforge_version != null) {
|
||||
compoundtag.putInt("viaforge_version", viaforge_version.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "read", at = @At(value = "TAIL"))
|
||||
private static void getVersion(CompoundTag compoundnbt, CallbackInfoReturnable<ServerData> cir) {
|
||||
if (compoundnbt.contains("viaforge_version")) {
|
||||
((ExtendedServerData) cir.getReturnValue()).viaforge_setVersion(VersionEnum.fromProtocolId(compoundnbt.getInt("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;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.multiplayer.ServerStatusPinger;
|
||||
import net.minecraft.network.Connection;
|
||||
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.InetSocketAddress;
|
||||
|
||||
@Mixin(ServerStatusPinger.class)
|
||||
public class MixinServerStatusPinger {
|
||||
|
||||
@Unique
|
||||
private ServerData viaforge_serverData;
|
||||
|
||||
@Inject(method = "pingServer", at = @At("HEAD"))
|
||||
public void trackServerData(ServerData server, Runnable p_147224_2_, CallbackInfo ci) {
|
||||
viaforge_serverData = server;
|
||||
}
|
||||
|
||||
@Redirect(method = "pingServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;connectToServer(Ljava/net/InetSocketAddress;Z)Lnet/minecraft/network/Connection;"))
|
||||
public Connection trackVersion(InetSocketAddress oclass, boolean lazyloadedvalue) {
|
||||
// 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 Connection.connectToServer(oclass, lazyloadedvalue);
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import de.florianmichael.viaforge.ViaForge117;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.platform.ViaForgeConfig;
|
||||
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
@ -33,16 +35,19 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(TitleScreen.class)
|
||||
public class MixinTitleScreen extends Screen {
|
||||
|
||||
protected MixinTitleScreen(Component p_96550_) {
|
||||
super(p_96550_);
|
||||
public MixinTitleScreen(Component title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "init", at = @At("HEAD"))
|
||||
@Inject(method = "init", at = @At("RETURN"))
|
||||
public void hookViaForgeButton(CallbackInfo ci) {
|
||||
ViaForgeCommon.init(ViaForge117.PLATFORM);
|
||||
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMainMenuButton()) {
|
||||
addRenderableWidget(new Button(5, 6, 98, 20, new TextComponent("ViaForge"), b -> GuiProtocolSelector.open(minecraft)));
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addRenderableWidget(new Button(pos.key(), pos.value(), 100, 20, new TextComponent("ViaForge"), buttons -> GuiProtocolSelector.open(minecraft)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package de.florianmichael.viaforge.mixin.fixes;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.raphimc.vialoader.util.VersionEnum;
|
||||
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;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class MixinLocalPlayer extends AbstractClientPlayer {
|
||||
|
||||
@Shadow private boolean lastOnGround;
|
||||
|
||||
public MixinLocalPlayer(ClientLevel level, GameProfile profile) {
|
||||
super(level, profile);
|
||||
}
|
||||
|
||||
@Redirect(method = "sendPosition", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;lastOnGround:Z", ordinal = 0))
|
||||
public boolean emulateIdlePacket(LocalPlayer instance) {
|
||||
if (ViaForgeCommon.getManager().getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
||||
// <= 1.8 spams the idle packet instead of only sending it when the ground state changes
|
||||
// So we invert the original logic:
|
||||
// if (prevOnGround != onGround) sendPacket
|
||||
// To be like:
|
||||
// if (!onGround != onGround) sendPacket
|
||||
// Which is the same as:
|
||||
// if (true) sendPacket
|
||||
return !onGround;
|
||||
}
|
||||
return lastOnGround;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -3,15 +3,25 @@
|
||||
"minVersion": "0.7.5",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"mixins": [
|
||||
"client": [
|
||||
"MixinClientHandshakePacketListenerImpl",
|
||||
"MixinConnection",
|
||||
"MixinConnection_1",
|
||||
"MixinTitleScreen",
|
||||
"MixinDebugScreenOverlay",
|
||||
"MixinDirectJoinServerScreen",
|
||||
"MixinEditServerScreen",
|
||||
"MixinJoinMultiplayerScreen",
|
||||
"MixinDirectJoinServerScreen"
|
||||
"MixinServerData",
|
||||
"MixinServerStatusPinger",
|
||||
"MixinTitleScreen",
|
||||
"fixes.MixinLocalPlayer"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"refmap": "mixins.viaforge-mc117.refmap.json"
|
||||
"refmap": "mixins.viaforge-mc117.refmap.json",
|
||||
"mixins": [
|
||||
"MixinConnection_1",
|
||||
"MixinConnectScreen_1"
|
||||
]
|
||||
}
|
||||
|
@ -18,9 +18,12 @@
|
||||
package de.florianmichael.viaforge;
|
||||
|
||||
import de.florianmichael.viaforge.common.platform.VFPlatform;
|
||||
import de.florianmichael.viaforge.provider.ViaForgeGameProfileFetcher;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.User;
|
||||
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;
|
||||
@ -44,4 +47,16 @@ public class ViaForge118 implements VFPlatform {
|
||||
public File getLeadingDirectory() {
|
||||
return Minecraft.getInstance().gameDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinServer(String serverId) throws Throwable {
|
||||
final User session = Minecraft.getInstance().getUser();
|
||||
|
||||
Minecraft.getInstance().getMinecraftSessionService().joinServer(session.getGameProfile(), session.getAccessToken(), serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfileFetcher getGameProfileFetcher() {
|
||||
return new ViaForgeGameProfileFetcher();
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user