Minecraft 1.20.6, Java 21

This commit is contained in:
FlorianMichael 2024-08-21 08:53:45 +02:00
parent 45aa44519d
commit 7073457483
No known key found for this signature in database
GPG Key ID: C2FB87E71C425126
22 changed files with 1065 additions and 6 deletions

View File

@ -9,10 +9,10 @@ jobs:
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: 17
java-version: 21
distribution: 'temurin'
check-latest: true
- name: Cache Dependencies

View File

@ -40,7 +40,7 @@ See [this project](https://github.com/ViaVersionMCP/ViaMCP) for a copy-paste sol
2. Run `./gradlew build` in the root directory of the repository.
3. The compiled jar files can be found in `viaforge-mc<version>/build/libs`.
Note: Build scripts are made to be run using Java 17.
Note: Build scripts are made to be run using Java 21.
## Other ViaVersion Mods / Platforms
@ -52,4 +52,4 @@ ViaForge - https://modrinth.com/mod/viaforge/ <br>
ViaProxy (App) - https://github.com/ViaVersion/ViaProxy/#readme <br>
ViaaaS (Proxy) - https://github.com/ViaVersion/ViaaaS#readme <br>
For a more detailed summary see https://viaversion.com/suite
For a more detailed summary see https://viaversion.com

View File

@ -21,8 +21,9 @@ allprojects {
apply plugin: "xyz.wagyourtail.jvmdowngrader"
java {
// Minecraft 1.17+ required Java 16/17 to compile
toolchain.languageVersion = JavaLanguageVersion.of(17)
// Minecraft 1.17+ required Java 17 to compile,
// Minecraft 1.20.5+ required Java 21 to compile
toolchain.languageVersion = JavaLanguageVersion.of(21)
}
// We define the configuration here so we can use it across all conventions and platforms

View File

@ -11,3 +11,4 @@ include "viaforge-mc1182"
include "viaforge-mc1192"
include "viaforge-mc1194"
include "viaforge-mc1204"
include "viaforge-mc1206"

View File

@ -0,0 +1 @@
forge_version=1.20.6-50.1.12

View File

@ -0,0 +1,73 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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;
import de.florianmichael.viaforge.common.ViaForgeCommon;
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.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.raphimc.vialegacy.protocol.release.r1_7_6_10tor1_8.provider.GameProfileFetcher;
import java.io.File;
import java.util.function.Supplier;
@Mod("viaforge")
public class ViaForge1206 implements VFPlatform {
public ViaForge1206() {
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onInit);
}
private void onInit(FMLCommonSetupEvent event) {
ViaForgeCommon.init(this);
}
@Override
public int getGameVersion() {
return SharedConstants.getProtocolVersion();
}
@Override
public Supplier<Boolean> isSingleplayer() {
return () -> Minecraft.getInstance().isSingleplayer();
}
@Override
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();
}
}

View File

@ -0,0 +1,167 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.gui;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.util.DumpUtil;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
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 com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.raphimc.vialoader.util.ProtocolVersionList;
import org.lwjgl.glfw.GLFW;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
public class GuiProtocolSelector extends Screen {
public final Screen parent;
public final boolean simple;
public final FinishedCallback finishedCallback;
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));
}
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(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
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(ChatFormatting.GREEN + "Dump created and copied to clipboard");
} catch (InterruptedException | ExecutionException e) {
setStatus(ChatFormatting.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());
}
addRenderableWidget(new SlotList(minecraft, width, height, 3 + 3 /* start offset */ + (font.lineHeight + 2) * 3 /* title is 2 */, 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(GuiGraphics graphics, int p_230430_2_, int p_230430_3_, float p_230430_4_) {
if (System.currentTimeMillis() - this.time >= 10_000) {
this.status = null;
}
super.render(graphics, p_230430_2_, p_230430_3_, p_230430_4_);
final var pose = graphics.pose();
pose.pushPose();
pose.scale(2.0F, 2.0F, 2.0F);
graphics.drawCenteredString(font, ChatFormatting.GOLD + "ViaForge", width / 4, 3, 16777215);
pose.popPose();
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);
}
class SlotList extends ObjectSelectionList<SlotList.SlotEntry> {
public SlotList(Minecraft client, int width, int height, int top, int bottom, int slotHeight) {
super(client, width, height - top - bottom, top, slotHeight);
for (ProtocolVersion version : ProtocolVersionList.getProtocolsNewToOld()) {
addEntry(new SlotEntry(version));
}
}
public class SlotEntry extends Entry<SlotEntry> {
private final ProtocolVersion ProtocolVersion;
public SlotEntry(ProtocolVersion ProtocolVersion) {
this.ProtocolVersion = ProtocolVersion;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
GuiProtocolSelector.this.finishedCallback.finished(ProtocolVersion, GuiProtocolSelector.this.parent);
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public Component getNarration() {
return Component.literal(ProtocolVersion.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 ProtocolVersion targetVersion = ViaForgeCommon.getManager().getTargetVersion();
String color;
if (targetVersion == ProtocolVersion) {
color = GuiProtocolSelector.this.simple ? ChatFormatting.GOLD.toString() : ChatFormatting.GREEN.toString();
} else {
color = GuiProtocolSelector.this.simple ? ChatFormatting.WHITE.toString() : ChatFormatting.DARK_RED.toString();
}
graphics.drawCenteredString(Minecraft.getInstance().font, color + ProtocolVersion.getName(), width / 2, y, -1);
}
}
}
public interface FinishedCallback {
void finished(final ProtocolVersion version, final Screen parent);
}
}

View File

@ -0,0 +1,45 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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 de.florianmichael.viaforge.common.ViaForgeCommon;
import net.minecraft.client.gui.components.DebugScreenOverlay;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.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 ProtocolVersion version = ViaForgeCommon.getManager().getTargetVersion();
if (common.getConfig().isShowProtocolVersionInF3() && version != common.getNativeVersion() && !common.getPlatform().isSingleplayer().get()) {
cir.getReturnValue().add("");
cir.getReturnValue().add("ViaForge: " + version.toString());
}
}
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.platform.ViaForgeConfig;
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.DirectJoinServerScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(DirectJoinServerScreen.class)
public class MixinDirectJoinServerScreen extends Screen {
public MixinDirectJoinServerScreen(Component title) {
super(title);
}
@Inject(method = "init", at = @At("RETURN"))
public void hookViaForgeButton(CallbackInfo ci) {
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());
}
}
}

View File

@ -0,0 +1,68 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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 com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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 ProtocolVersion 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());
}
}
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.platform.ViaForgeConfig;
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(JoinMultiplayerScreen.class)
public class MixinJoinMultiplayerScreen extends Screen {
public MixinJoinMultiplayerScreen(Component title) {
super(title);
}
@Inject(method = "init", at = @At("RETURN"))
public void hookViaForgeButton(CallbackInfo ci) {
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());
}
}
}

View File

@ -0,0 +1,70 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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 de.florianmichael.viaforge.common.gui.ExtendedServerData;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.nbt.CompoundTag;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
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 ProtocolVersion 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.putString("viaForge$version", viaForge$version.getName());
}
}
@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(ProtocolVersion.getClosest(compoundnbt.getString("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 ProtocolVersion viaForge$getVersion() {
return viaForge$version;
}
@Override
public void viaForge$setVersion(ProtocolVersion version) {
viaForge$version = version;
}
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.platform.ViaForgeConfig;
import de.florianmichael.viaforge.gui.GuiProtocolSelector;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(TitleScreen.class)
public class MixinTitleScreen extends Screen {
public MixinTitleScreen(Component title) {
super(title);
}
@Inject(method = "init", at = @At("RETURN"))
public void hookViaForgeButton(CallbackInfo ci) {
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());
}
}
}

View File

@ -0,0 +1,59 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.connect;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.protocoltranslator.netty.VFNetworkManager;
import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl;
import net.minecraft.network.Connection;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.release.r1_6_4tor1_7_2_5.storage.ProtocolMetadataStorage;
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 {
final VFNetworkManager mixinConnection = (VFNetworkManager) connection;
if (mixinConnection.viaForge$getTrackedVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
final UserConnection user = connection.channel().attr(ViaForgeCommon.VF_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);
}
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.connect;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
import de.florianmichael.viaforge.common.platform.VersionTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ServerData;
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.net.InetSocketAddress;
import java.util.Optional;
@Mixin(targets = "net.minecraft.client.gui.screens.ConnectScreen$1")
public class MixinConnectScreen_1 {
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Ljava/util/Optional;get()Ljava/lang/Object;"))
public Object trackServerVersion(Optional instance) {
final InetSocketAddress address = (InetSocketAddress) instance.get();
ProtocolVersion version = ((ExtendedServerData) Minecraft.getInstance().getCurrentServer()).viaForge$getVersion();
if (version == null) {
version = ViaForgeCommon.getManager().getTargetVersion();
}
VersionTracker.storeServerProtocolVersion(address.getAddress(), version);
return address;
}
}

View File

@ -0,0 +1,99 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.connect;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.platform.VersionTracker;
import de.florianmichael.viaforge.common.protocoltranslator.netty.VFNetworkManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import net.minecraft.network.CipherDecoder;
import net.minecraft.network.CipherEncoder;
import net.minecraft.network.Connection;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialoader.netty.VLLegacyPipeline;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
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 javax.crypto.Cipher;
import java.net.InetSocketAddress;
@Mixin(Connection.class)
public class MixinConnection implements VFNetworkManager {
@Shadow private Channel channel;
@Shadow private boolean encrypted;
@Unique
private Cipher viaForge$decryptionCipher;
@Unique
private ProtocolVersion viaForge$targetVersion;
@Inject(method = "setupCompression", at = @At("RETURN"))
public void reorderPipeline(int p_129485_, boolean p_182682_, CallbackInfo ci) {
ViaForgeCommon.getManager().reorderCompression(channel);
}
@Inject(method = "setEncryptionKey", at = @At("HEAD"), cancellable = true)
private void storeEncryptionCiphers(Cipher p_244777_1_, Cipher p_244777_2_, CallbackInfo ci) {
if (viaForge$targetVersion != null && viaForge$targetVersion.olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
// Minecraft's encryption code is bad for us, we need to reorder the pipeline
ci.cancel();
// Minecraft 1.6.4 supports tile encryption which means the server can only enable one side of the encryption
// So we only enable the encryption side and later enable the decryption side if the 1.7 -> 1.6 protocol
// tells us to do, therefore we need to store the cipher instance.
this.viaForge$decryptionCipher = p_244777_1_;
// Enabling the encryption side
this.encrypted = true;
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new CipherEncoder(p_244777_2_));
}
}
@Inject(method = "connect", at = @At("HEAD"))
private static void setTargetVersion(InetSocketAddress p_290034_, boolean p_290035_, Connection p_290031_, CallbackInfoReturnable<ChannelFuture> cir) {
final VFNetworkManager mixinConnection = (VFNetworkManager) p_290031_;
mixinConnection.viaForge$setTrackedVersion(VersionTracker.getServerProtocolVersion(p_290034_.getAddress()));
}
@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 ProtocolVersion viaForge$getTrackedVersion() {
return viaForge$targetVersion;
}
@Override
public void viaForge$setTrackedVersion(ProtocolVersion version) {
viaForge$targetVersion = version;
}
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.connect;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.protocoltranslator.netty.VFNetworkManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(targets = "net.minecraft.network.Connection$1")
public class MixinConnection_1 {
@Inject(method = "initChannel", at = @At("TAIL"))
private void hookViaPipeline(Channel p_129552_, CallbackInfo ci) {
final ChannelHandler connection = p_129552_.pipeline().get("packet_handler");
ViaForgeCommon.getManager().inject(p_129552_, (VFNetworkManager) connection);
}
}

View File

@ -0,0 +1,61 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.connect;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import de.florianmichael.viaforge.common.gui.ExtendedServerData;
import de.florianmichael.viaforge.common.platform.VersionTracker;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.multiplayer.ServerStatusPinger;
import net.minecraft.network.Connection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.util.debugchart.LocalSampleLogger;
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 p_105460_, Runnable p_105461_, Runnable p_335024_, CallbackInfo ci) {
viaForge$serverData = p_105460_;
}
@Redirect(method = "pingServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;connectToServer(Ljava/net/InetSocketAddress;ZLnet/minecraft/util/debugchart/LocalSampleLogger;)Lnet/minecraft/network/Connection;"))
public Connection trackVersion(InetSocketAddress inetSocketAddress, boolean b, LocalSampleLogger localSampleLogger) {
ProtocolVersion version = ((ExtendedServerData) viaForge$serverData).viaForge$getVersion();
if (version == null) {
version = ViaForgeCommon.getManager().getTargetVersion();
}
VersionTracker.storeServerProtocolVersion(inetSocketAddress.getAddress(), version);
viaForge$serverData = null;
return Connection.connectToServer(inetSocketAddress, b, localSampleLogger);
}
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.fixes;
import com.mojang.authlib.GameProfile;
import de.florianmichael.viaforge.common.ViaForgeCommon;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.player.LocalPlayer;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(LocalPlayer.class)
public class MixinLocalPlayer extends AbstractClientPlayer {
@Shadow private boolean lastOnGround;
public MixinLocalPlayer(ClientLevel level, GameProfile profile) {
super(level, profile);
}
@Redirect(method = "sendPosition", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;lastOnGround:Z", ordinal = 0))
public boolean emulateIdlePacket(LocalPlayer instance) {
if (ViaForgeCommon.getManager().getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
// <= 1.8 spams the idle packet instead of only sending it when the ground state changes
// So we invert the original logic:
// if (prevOnGround != onGround) sendPacket
// To be like:
// if (!onGround != onGround) sendPacket
// Which is the same as:
// if (true) sendPacket
return !onGround();
}
return lastOnGround;
}
}

View File

@ -0,0 +1,76 @@
/*
* This file is part of ViaForge - https://github.com/FlorianMichael/ViaForge
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> 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.provider;
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.protocol.release.r1_7_6_10tor1_8.model.GameProfile;
import net.raphimc.vialegacy.protocol.release.r1_7_6_10tor1_8.provider.GameProfileFetcher;
import java.net.Proxy;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class ViaForgeGameProfileFetcher extends GameProfileFetcher {
public static final HttpAuthenticationService AUTHENTICATION_SERVICE = new YggdrasilAuthenticationService(Proxy.NO_PROXY);
public static final MinecraftSessionService SESSION_SERVICE = AUTHENTICATION_SERVICE.createMinecraftSessionService();
public static final 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}, new ProfileLookupCallback() {
@Override
public void onProfileLookupSucceeded(com.mojang.authlib.GameProfile profile) {
future.complete(profile);
}
@Override
public void onProfileLookupFailed(String profileName, 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 var result = SESSION_SERVICE.fetchProfile(uuid, true);
if (result == null) throw new ProfileNotFoundException();
final var profile = result.profile();
final var gameProfile = new GameProfile(profile.getName(), profile.getId());
for (final var entry : profile.getProperties().entries()) {
final Property prop = entry.getValue();
gameProfile.addProperty(new GameProfile.Property(prop.name(), prop.value(), prop.signature()));
}
return gameProfile;
}
}

View File

@ -0,0 +1,16 @@
modLoader="javafml"
loaderVersion="[50,)"
license="GPL-3.0 license"
issueTrackerURL="https://github.com/ViaVersion/ViaForge/issues"
showAsResourcePack=false
[[mods]]
modId="viaforge"
version="${version}"
displayName="ViaForge"
displayURL="https://github.com/FlorianMichael"
logoFile="icon.png"
credits="Github contributors"
authors="FlorianMichael/EnZaXD"
description="${description}"

View File

@ -0,0 +1,24 @@
{
"required": true,
"minVersion": "0.7.5",
"compatibilityLevel": "JAVA_8",
"package": "de.florianmichael.viaforge.mixin",
"client": [
"MixinDebugScreenOverlay",
"MixinDirectJoinServerScreen",
"MixinEditServerScreen",
"MixinJoinMultiplayerScreen",
"MixinServerData",
"MixinTitleScreen",
"connect.MixinClientHandshakePacketListenerImpl",
"connect.MixinConnection",
"connect.MixinConnection_1",
"connect.MixinConnectScreen_1",
"connect.MixinServerStatusPinger",
"fixes.MixinLocalPlayer"
],
"injectors": {
"defaultRequire": 1
},
"refmap": "mixins.viaforge-mc1206.refmap.json"
}