mirror of
https://github.com/ViaVersion/ViaForge.git
synced 2025-02-03 23:41:31 +01:00
Sync last commits to all mc version implementations
This commit is contained in:
parent
3cf92fa69f
commit
9aea3aa3ac
@ -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,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,15 +4,24 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"client": [
|
||||
"MixinAddServerScreen",
|
||||
"MixinClientLoginNetHandler",
|
||||
"MixinConnectingScreen_1",
|
||||
"MixinDebugOverlayGui",
|
||||
"MixinMainMenuScreen",
|
||||
"MixinMultiplayerScreen",
|
||||
"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,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.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,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,11 +4,17 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"client": [
|
||||
"MixinAddServerScreen",
|
||||
"MixinClientLoginNetHandler",
|
||||
"MixinConnectingScreen_1",
|
||||
"MixinDebugOverlayGui",
|
||||
"MixinMainMenuScreen",
|
||||
"MixinMultiplayerScreen",
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"MixinServerData",
|
||||
"MixinServerListScreen",
|
||||
"MixinServerPinger",
|
||||
"fixes.MixinClientPlayerEntity"
|
||||
],
|
||||
"injectors": {
|
||||
|
@ -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,60 +18,108 @@
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
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));
|
||||
@ -87,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,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,11 +4,17 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"client": [
|
||||
"MixinAddServerScreen",
|
||||
"MixinClientLoginNetHandler",
|
||||
"MixinConnectingScreen_1",
|
||||
"MixinDebugOverlayGui",
|
||||
"MixinMainMenuScreen",
|
||||
"MixinMultiplayerScreen",
|
||||
"MixinNetworkManager",
|
||||
"MixinNetworkManager_1",
|
||||
"MixinServerData",
|
||||
"MixinServerListScreen",
|
||||
"MixinServerPinger",
|
||||
"fixes.MixinClientPlayerEntity"
|
||||
],
|
||||
"injectors": {
|
||||
|
@ -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,8 +18,10 @@
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
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;
|
||||
@ -27,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));
|
||||
@ -87,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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,4 +34,4 @@ public class MixinLocalPlayer extends AbstractClientPlayer {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -4,15 +4,24 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"client": [
|
||||
"MixinClientHandshakePacketListenerImpl",
|
||||
"MixinConnection",
|
||||
"MixinConnection_1",
|
||||
"MixinDebugScreenOverlay",
|
||||
"MixinDirectJoinServerScreen",
|
||||
"MixinEditServerScreen",
|
||||
"MixinJoinMultiplayerScreen",
|
||||
"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();
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,10 @@
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
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;
|
||||
@ -27,58 +29,104 @@ 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));
|
||||
}
|
||||
}
|
||||
|
||||
public class SlotEntry extends ObjectSelectionList.Entry<SlotEntry> {
|
||||
public class SlotEntry extends Entry<SlotEntry> {
|
||||
|
||||
private final VersionEnum versionEnum;
|
||||
|
||||
@ -87,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.ViaForge118;
|
||||
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.ViaForge118;
|
||||
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.ViaForge118;
|
||||
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(ViaForge118.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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,4 +34,4 @@ public class MixinLocalPlayer extends AbstractClientPlayer {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -4,10 +4,16 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"client": [
|
||||
"MixinClientHandshakePacketListenerImpl",
|
||||
"MixinConnection",
|
||||
"MixinConnection_1",
|
||||
"MixinConnectScreen_1",
|
||||
"MixinDebugScreenOverlay",
|
||||
"MixinDirectJoinServerScreen",
|
||||
"MixinEditServerScreen",
|
||||
"MixinJoinMultiplayerScreen",
|
||||
"MixinServerData",
|
||||
"MixinServerStatusPinger",
|
||||
"MixinTitleScreen",
|
||||
"fixes.MixinLocalPlayer"
|
||||
],
|
||||
|
@ -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 ViaForge119 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,66 +18,114 @@
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
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;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
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(Component.literal("ViaForge Protocol Selector"));
|
||||
this.parent = parent;
|
||||
this.simple = simple;
|
||||
this.finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
public void init() {
|
||||
super.init();
|
||||
addRenderableWidget(Button.builder(Component.literal("<-"), b -> minecraft.setScreen(parent)).bounds(5, height - 25, 20, 20).build());
|
||||
if (!this.simple) {
|
||||
addRenderableWidget(Button.builder(Component.literal("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());
|
||||
}
|
||||
}).bounds(width - 105, 5, 100, 20).build());
|
||||
addRenderableWidget(Button.builder(Component.literal("Reload configs"), b -> Via.getManager().getConfigurationProvider().reloadConfigs()).bounds(width - 105, height - 25, 100, 20).build());
|
||||
}
|
||||
|
||||
addWidget(slotList = new SlotList(minecraft, width, height, 32, height - 32, 10));
|
||||
addRenderableWidget(new Button.Builder(Component.literal("Back"), b -> minecraft.setScreen(parent)).bounds(width / 2 - 100, height - 27, 200, 20).build());
|
||||
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, Component.literal(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));
|
||||
}
|
||||
}
|
||||
|
||||
public class SlotEntry extends ObjectSelectionList.Entry<SlotEntry> {
|
||||
public class SlotEntry extends Entry<SlotEntry> {
|
||||
|
||||
private final VersionEnum versionEnum;
|
||||
|
||||
@ -86,21 +134,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 Component.literal(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.ViaForge119;
|
||||
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;
|
||||
@ -32,14 +33,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.Builder(Component.literal("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))).bounds(5, 6, 98, 20).build());
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowDirectConnectButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addRenderableWidget(Button.builder(Component.literal("ViaForge"), b -> GuiProtocolSelector.open(minecraft)).bounds(pos.key(), pos.value(), 100, 20).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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.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(Button.builder(Component.literal(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);
|
||||
}));
|
||||
}).bounds(pos.key(), pos.value(), 100, 20).build());
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,9 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.ViaForge119;
|
||||
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;
|
||||
@ -32,14 +33,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.Builder(Component.literal("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))).bounds(5, 6, 98, 20).build());
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addRenderableWidget(Button.builder(Component.literal("ViaForge"), buttons -> GuiProtocolSelector.open(minecraft)).bounds(pos.key(), pos.value(), 100, 20).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.ViaForge119;
|
||||
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;
|
||||
@ -32,16 +34,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(ViaForge119.PLATFORM);
|
||||
|
||||
if (ViaForgeCommon.getManager().getConfig().isShowMainMenuButton()) {
|
||||
addRenderableWidget(new Button.Builder(Component.literal("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))).bounds(5, 6, 98, 20).build());
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowMainMenuButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addRenderableWidget(Button.builder(Component.literal("ViaForge"), buttons -> GuiProtocolSelector.open(minecraft)).bounds(pos.key(), pos.value(), 100, 20).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,4 +34,4 @@ public class MixinLocalPlayer extends AbstractClientPlayer {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -4,10 +4,16 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"package": "de.florianmichael.viaforge.mixin",
|
||||
"client": [
|
||||
"MixinClientHandshakePacketListenerImpl",
|
||||
"MixinConnection",
|
||||
"MixinConnection_1",
|
||||
"MixinConnectScreen_1",
|
||||
"MixinDebugScreenOverlay",
|
||||
"MixinDirectJoinServerScreen",
|
||||
"MixinEditServerScreen",
|
||||
"MixinJoinMultiplayerScreen",
|
||||
"MixinServerData",
|
||||
"MixinServerStatusPinger",
|
||||
"MixinTitleScreen",
|
||||
"fixes.MixinLocalPlayer"
|
||||
],
|
||||
|
@ -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 ViaForge120 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.getProfileId(), session.getAccessToken(), serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfileFetcher getGameProfileFetcher() {
|
||||
return new ViaForgeGameProfileFetcher();
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,11 @@
|
||||
*/
|
||||
package de.florianmichael.viaforge.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
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.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
@ -26,57 +29,102 @@ import net.minecraft.client.gui.components.ObjectSelectionList;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
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(Component.literal("ViaForge Protocol Selector"));
|
||||
this.parent = parent;
|
||||
this.simple = simple;
|
||||
this.finishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
public void init() {
|
||||
super.init();
|
||||
addRenderableWidget(Button.builder(Component.literal("<-"), b -> minecraft.setScreen(parent)).bounds(5, height - 25, 20, 20).build());
|
||||
if (!this.simple) {
|
||||
addRenderableWidget(Button.builder(Component.literal("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());
|
||||
}
|
||||
}).bounds(width - 105, 5, 100, 20).build());
|
||||
addRenderableWidget(Button.builder(Component.literal("Reload configs"), b -> Via.getManager().getConfigurationProvider().reloadConfigs()).bounds(width - 105, height - 25, 100, 20).build());
|
||||
}
|
||||
|
||||
addWidget(slotList = new SlotList(minecraft, width, height, 32, height - 32, 10));
|
||||
addRenderableWidget(new Button.Builder(Component.literal("Back"), b -> minecraft.setScreen(parent)).bounds(width / 2 - 100, height - 27, 200, 20).build());
|
||||
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(GuiGraphics p_230430_1_, int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
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(GuiGraphics graphics, int p_230430_2_, int p_230430_3_, float p_230430_4_) {
|
||||
if (System.currentTimeMillis() - this.time >= 10_000) {
|
||||
this.status = null;
|
||||
}
|
||||
|
||||
this.list.render(graphics, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
super.render(graphics, p_230430_2_, p_230430_3_, p_230430_4_);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScalef(2.0F, 2.0F, 2.0F);
|
||||
p_230430_1_.drawCenteredString(this.font, Component.literal(ChatFormatting.GOLD + "ViaForge"), this.width / 4, 6, 16777215);
|
||||
graphics.drawCenteredString(font, TextFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
|
||||
GL11.glPopMatrix();
|
||||
|
||||
p_230430_1_.drawString(this.font, "by https://github.com/ViaVersion/ViaForge", 1, 1, -1);
|
||||
p_230430_1_.drawString(this.font, "Discord: florianmichael", 1, 11, -1);
|
||||
graphics.drawCenteredString(font, "https://github.com/ViaVersion/ViaForge", width / 2, (font.lineHeight + 2) * 2 + 3, -1);
|
||||
graphics.drawString(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));
|
||||
}
|
||||
}
|
||||
|
||||
public class SlotEntry extends ObjectSelectionList.Entry<SlotEntry> {
|
||||
public class SlotEntry extends Entry<SlotEntry> {
|
||||
|
||||
private final VersionEnum versionEnum;
|
||||
|
||||
@ -85,21 +133,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(GuiGraphics 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_) {
|
||||
p_230432_1_.drawCenteredString(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 Component.literal(versionEnum.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics graphics, 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();
|
||||
}
|
||||
|
||||
graphics.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,38 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
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;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@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(Ljava/util/UUID;Ljava/lang/String;Ljava/lang/String;)V"))
|
||||
public void onlyJoinServerIfPremium(MinecraftSessionService instance, UUID uuid, 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(uuid, authenticationToken, serverId);
|
||||
}
|
||||
}
|
@ -18,22 +18,105 @@
|
||||
package de.florianmichael.viaforge.mixin;
|
||||
|
||||
import de.florianmichael.viaforge.common.ViaForgeCommon;
|
||||
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
|
||||
import de.florianmichael.viaforge.common.protocolhack.netty.VFNetworkManager;
|
||||
import io.netty.channel.Channel;
|
||||
import net.minecraft.client.Minecraft;
|
||||
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.PacketListener;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.handshake.ClientIntent;
|
||||
import net.minecraft.util.SampleLogger;
|
||||
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 = "Lnet/minecraft/network/Connection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/Connection;)Lio/netty/channel/ChannelFuture;"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private static void trackSelfTarget(InetSocketAddress p_178301_, boolean p_178302_, SampleLogger p_300093_, CallbackInfoReturnable<Connection> cir, 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 = "initiateServerboundConnection", at = @At("HEAD"))
|
||||
public void test(String p_300730_, int p_300598_, PacketListener p_298739_, ClientIntent p_297789_, CallbackInfo ci) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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.ViaForge120;
|
||||
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;
|
||||
@ -32,14 +33,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.Builder(Component.literal("ViaForge"), b -> minecraft.setScreen(new GuiProtocolSelector(this))).bounds(5, 6, 98, 20).build());
|
||||
final ViaForgeConfig config = ViaForgeCommon.getManager().getConfig();
|
||||
if (config.isShowDirectConnectButton()) {
|
||||
final Pair<Integer, Integer> pos = config.getViaForgeButtonPosition().getPosition(this.width, this.height);
|
||||
|
||||
addRenderableWidget(Button.builder(Component.literal("ViaForge"), b -> GuiProtocolSelector.open(minecraft)).bounds(pos.key(), pos.value(), 100, 20).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user