diff --git a/build.gradle b/build.gradle index 2c94bab..685f5cc 100644 --- a/build.gradle +++ b/build.gradle @@ -150,7 +150,7 @@ processResources { } } -List versionToAdd = new ArrayList<>(Arrays.asList("Fabric", "1.18.2", "1.17.1", +List versionToAdd = new ArrayList<>(Arrays.asList("Fabric", "1.19-Snapshot", "1.18.2", "1.17.1", "1.16.5", "1.15.2", "1.14.4", "1.8.9")) versionToAdd.addAll(IntStream.rangeClosed(8, 18) .mapToObj { n -> (String) "Java $n" } diff --git a/gradle.properties b/gradle.properties index f18bf05..908f0c6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # rip my ram -org.gradle.jvmargs=-Xms32M -Xmx3G +org.gradle.jvmargs=-Xms32M -Xmx4G loader_version=0.13.3 -viaver_version=4.2.1 +viaver_version=4.3.0-22w11a-SNAPSHOT yaml_version=1.30 diff --git a/settings.gradle b/settings.gradle index df538e5..52606aa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,3 +13,4 @@ include "viafabric-mc115" include "viafabric-mc116" include "viafabric-mc117" include "viafabric-mc118" +include "viafabric-mc119" diff --git a/src/main/java/com/viaversion/fabric/common/config/AbstractViaConfigScreen.java b/src/main/java/com/viaversion/fabric/common/config/AbstractViaConfigScreen.java new file mode 100644 index 0000000..4a99fb9 --- /dev/null +++ b/src/main/java/com/viaversion/fabric/common/config/AbstractViaConfigScreen.java @@ -0,0 +1,15 @@ +package com.viaversion.fabric.common.config; + +public interface AbstractViaConfigScreen { + String TITLE_TRANSLATE_ID = "gui.viafabric_config.title"; + String VERSION_TRANSLATE_ID = "gui.protocol_version_field.name"; + + default int getProtocolTextColor(boolean valid, boolean supported) { + if (!valid) { + return 0xff0000; // Red + } else if (!supported) { + return 0xFFA500; // Orange + } + return 0xE0E0E0; // Default + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ffbad5d..51ae013 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ }, "depends": { "fabricloader": ">=0.10.0", - "minecraft": ["1.8.x", "1.14.x", "1.15.x", "1.16.x", "1.17.x", "1.18.x"], + "minecraft": ["1.8.x", "1.14.x", "1.15.x", "1.16.x", "1.17.x", "1.18.x", "1.19.x"], "viaversion": ">=4.0.0" }, "environment": "*", diff --git a/viafabric-mc114/src/main/java/com/viaversion/fabric/mc114/gui/ViaConfigScreen.java b/viafabric-mc114/src/main/java/com/viaversion/fabric/mc114/gui/ViaConfigScreen.java index 2e14050..b79dfc2 100644 --- a/viafabric-mc114/src/main/java/com/viaversion/fabric/mc114/gui/ViaConfigScreen.java +++ b/viafabric-mc114/src/main/java/com/viaversion/fabric/mc114/gui/ViaConfigScreen.java @@ -1,5 +1,6 @@ package com.viaversion.fabric.mc114.gui; +import com.viaversion.fabric.common.config.AbstractViaConfigScreen; import com.viaversion.fabric.mc114.ViaFabric; import com.viaversion.fabric.common.util.ProtocolUtils; import net.fabricmc.api.EnvType; @@ -14,26 +15,16 @@ import net.minecraft.text.TranslatableText; import java.util.concurrent.CompletableFuture; @Environment(EnvType.CLIENT) -public class ViaConfigScreen extends Screen { +public class ViaConfigScreen extends Screen implements AbstractViaConfigScreen { private static CompletableFuture latestProtocolSave; private final Screen parent; private TextFieldWidget protocolVersion; public ViaConfigScreen(Screen parent) { - super(new TranslatableText("gui.viafabric_config.title")); + super(new TranslatableText(TITLE_TRANSLATE_ID)); this.parent = parent; } - private static int getProtocolTextColor(boolean valid, boolean supported) { - - if (!valid) { - return 0xff0000; // Red - } else if (!supported) { - return 0xFFA500; // Orange - } - return 0xE0E0E0; // Default - } - @Override protected void init() { int entries = 0; @@ -54,7 +45,7 @@ public class ViaConfigScreen extends Screen { this.width / 2 - 155 + entries % 2 * 160, this.height / 6 + 24 * (entries >> 1), 150, - 20, new TranslatableText("gui.protocol_version_field.name").asString()); + 20, new TranslatableText(VERSION_TRANSLATE_ID).asString()); entries++; protocolVersion.setTextPredicate(ProtocolUtils::isStartOfProtocolText); diff --git a/viafabric-mc115/src/main/java/com/viaversion/fabric/mc115/gui/ViaConfigScreen.java b/viafabric-mc115/src/main/java/com/viaversion/fabric/mc115/gui/ViaConfigScreen.java index 8c82a01..f928324 100644 --- a/viafabric-mc115/src/main/java/com/viaversion/fabric/mc115/gui/ViaConfigScreen.java +++ b/viafabric-mc115/src/main/java/com/viaversion/fabric/mc115/gui/ViaConfigScreen.java @@ -1,5 +1,6 @@ package com.viaversion.fabric.mc115.gui; +import com.viaversion.fabric.common.config.AbstractViaConfigScreen; import com.viaversion.fabric.mc115.ViaFabric; import com.viaversion.fabric.common.util.ProtocolUtils; import net.fabricmc.api.EnvType; @@ -14,26 +15,16 @@ import net.minecraft.text.TranslatableText; import java.util.concurrent.CompletableFuture; @Environment(EnvType.CLIENT) -public class ViaConfigScreen extends Screen { +public class ViaConfigScreen extends Screen implements AbstractViaConfigScreen { private static CompletableFuture latestProtocolSave; private final Screen parent; private TextFieldWidget protocolVersion; public ViaConfigScreen(Screen parent) { - super(new TranslatableText("gui.viafabric_config.title")); + super(new TranslatableText(TITLE_TRANSLATE_ID)); this.parent = parent; } - private static int getProtocolTextColor(boolean valid, boolean supported) { - - if (!valid) { - return 0xff0000; // Red - } else if (!supported) { - return 0xFFA500; // Orange - } - return 0xE0E0E0; // Default - } - @Override protected void init() { int entries = 0; @@ -54,7 +45,7 @@ public class ViaConfigScreen extends Screen { this.width / 2 - 155 + entries % 2 * 160, this.height / 6 + 24 * (entries >> 1), 150, - 20, new TranslatableText("gui.protocol_version_field.name").asString()); + 20, new TranslatableText(VERSION_TRANSLATE_ID).asString()); entries++; protocolVersion.setTextPredicate(ProtocolUtils::isStartOfProtocolText); diff --git a/viafabric-mc116/src/main/java/com/viaversion/fabric/mc116/gui/ViaConfigScreen.java b/viafabric-mc116/src/main/java/com/viaversion/fabric/mc116/gui/ViaConfigScreen.java index 244421a..48338c4 100644 --- a/viafabric-mc116/src/main/java/com/viaversion/fabric/mc116/gui/ViaConfigScreen.java +++ b/viafabric-mc116/src/main/java/com/viaversion/fabric/mc116/gui/ViaConfigScreen.java @@ -1,5 +1,6 @@ package com.viaversion.fabric.mc116.gui; +import com.viaversion.fabric.common.config.AbstractViaConfigScreen; import com.viaversion.fabric.mc116.ViaFabric; import com.viaversion.fabric.common.util.ProtocolUtils; import net.fabricmc.api.EnvType; @@ -16,26 +17,16 @@ import net.minecraft.text.TranslatableText; import java.util.concurrent.CompletableFuture; @Environment(EnvType.CLIENT) -public class ViaConfigScreen extends Screen { +public class ViaConfigScreen extends Screen implements AbstractViaConfigScreen { private static CompletableFuture latestProtocolSave; private final Screen parent; private TextFieldWidget protocolVersion; public ViaConfigScreen(Screen parent) { - super(new TranslatableText("gui.viafabric_config.title")); + super(new TranslatableText(TITLE_TRANSLATE_ID)); this.parent = parent; } - private static int getProtocolTextColor(boolean valid, boolean supported) { - - if (!valid) { - return 0xff0000; // Red - } else if (!supported) { - return 0xFFA500; // Orange - } - return 0xE0E0E0; // Default - } - @Override protected void init() { int entries = 0; @@ -56,7 +47,7 @@ public class ViaConfigScreen extends Screen { this.width / 2 - 155 + entries % 2 * 160, this.height / 6 + 24 * (entries >> 1), 150, - 20, new TranslatableText("gui.protocol_version_field.name")); + 20, new TranslatableText(VERSION_TRANSLATE_ID)); entries++; protocolVersion.setTextPredicate(ProtocolUtils::isStartOfProtocolText); diff --git a/viafabric-mc117/src/main/java/com/viaversion/fabric/mc117/gui/ViaConfigScreen.java b/viafabric-mc117/src/main/java/com/viaversion/fabric/mc117/gui/ViaConfigScreen.java index 78f73d0..d59b0c6 100644 --- a/viafabric-mc117/src/main/java/com/viaversion/fabric/mc117/gui/ViaConfigScreen.java +++ b/viafabric-mc117/src/main/java/com/viaversion/fabric/mc117/gui/ViaConfigScreen.java @@ -1,5 +1,6 @@ package com.viaversion.fabric.mc117.gui; +import com.viaversion.fabric.common.config.AbstractViaConfigScreen; import com.viaversion.fabric.mc117.ViaFabric; import com.viaversion.fabric.common.util.ProtocolUtils; import net.fabricmc.api.EnvType; @@ -16,26 +17,16 @@ import net.minecraft.text.TranslatableText; import java.util.concurrent.CompletableFuture; @Environment(EnvType.CLIENT) -public class ViaConfigScreen extends Screen { +public class ViaConfigScreen extends Screen implements AbstractViaConfigScreen { private static CompletableFuture latestProtocolSave; private final Screen parent; private TextFieldWidget protocolVersion; public ViaConfigScreen(Screen parent) { - super(new TranslatableText("gui.viafabric_config.title")); + super(new TranslatableText(TITLE_TRANSLATE_ID)); this.parent = parent; } - private static int getProtocolTextColor(boolean valid, boolean supported) { - - if (!valid) { - return 0xff0000; // Red - } else if (!supported) { - return 0xFFA500; // Orange - } - return 0xE0E0E0; // Default - } - @Override protected void init() { int entries = 0; @@ -56,7 +47,7 @@ public class ViaConfigScreen extends Screen { this.width / 2 - 155 + entries % 2 * 160, this.height / 6 + 24 * (entries >> 1), 150, - 20, new TranslatableText("gui.protocol_version_field.name")); + 20, new TranslatableText(VERSION_TRANSLATE_ID)); entries++; protocolVersion.setTextPredicate(ProtocolUtils::isStartOfProtocolText); diff --git a/viafabric-mc118/src/main/java/com/viaversion/fabric/mc118/gui/ViaConfigScreen.java b/viafabric-mc118/src/main/java/com/viaversion/fabric/mc118/gui/ViaConfigScreen.java index 673f195..eb559f4 100644 --- a/viafabric-mc118/src/main/java/com/viaversion/fabric/mc118/gui/ViaConfigScreen.java +++ b/viafabric-mc118/src/main/java/com/viaversion/fabric/mc118/gui/ViaConfigScreen.java @@ -1,5 +1,6 @@ package com.viaversion.fabric.mc118.gui; +import com.viaversion.fabric.common.config.AbstractViaConfigScreen; import com.viaversion.fabric.mc118.ViaFabric; import com.viaversion.fabric.common.util.ProtocolUtils; import net.fabricmc.api.EnvType; @@ -16,26 +17,16 @@ import net.minecraft.text.TranslatableText; import java.util.concurrent.CompletableFuture; @Environment(EnvType.CLIENT) -public class ViaConfigScreen extends Screen { +public class ViaConfigScreen extends Screen implements AbstractViaConfigScreen { private static CompletableFuture latestProtocolSave; private final Screen parent; private TextFieldWidget protocolVersion; public ViaConfigScreen(Screen parent) { - super(new TranslatableText("gui.viafabric_config.title")); + super(new TranslatableText(TITLE_TRANSLATE_ID)); this.parent = parent; } - private static int getProtocolTextColor(boolean valid, boolean supported) { - - if (!valid) { - return 0xff0000; // Red - } else if (!supported) { - return 0xFFA500; // Orange - } - return 0xE0E0E0; // Default - } - @Override protected void init() { int entries = 0; @@ -56,7 +47,7 @@ public class ViaConfigScreen extends Screen { this.width / 2 - 155 + entries % 2 * 160, this.height / 6 + 24 * (entries >> 1), 150, - 20, new TranslatableText("gui.protocol_version_field.name")); + 20, new TranslatableText(VERSION_TRANSLATE_ID)); entries++; protocolVersion.setTextPredicate(ProtocolUtils::isStartOfProtocolText); diff --git a/viafabric-mc119/build.gradle.kts b/viafabric-mc119/build.gradle.kts new file mode 100644 index 0000000..e97a9e8 --- /dev/null +++ b/viafabric-mc119/build.gradle.kts @@ -0,0 +1,7 @@ +dependencies { + minecraft("com.mojang:minecraft:22w11a") + mappings("net.fabricmc:yarn:22w11a+build.2:v2") + + modImplementation("net.fabricmc.fabric-api:fabric-api:0.49.2+1.19") + modImplementation("com.terraformersmc:modmenu:3.0.0") +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/ViaFabric.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/ViaFabric.java new file mode 100644 index 0000000..2be921e --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/ViaFabric.java @@ -0,0 +1,102 @@ +package com.viaversion.fabric.mc119; + +import com.google.common.collect.Range; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.viaversion.fabric.common.config.VFConfig; +import com.viaversion.fabric.common.platform.FabricInjector; +import com.viaversion.fabric.common.protocol.HostnameParserProtocol; +import com.viaversion.fabric.common.util.JLoggerToLog4j; +import com.viaversion.fabric.mc119.commands.VRCommandHandler; +import com.viaversion.fabric.mc119.platform.FabricPlatform; +import com.viaversion.fabric.mc119.platform.VFLoader; +import com.viaversion.viaversion.ViaManagerImpl; +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.data.MappingDataLoader; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import io.netty.channel.DefaultEventLoop; +import io.netty.channel.EventLoop; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager; +import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.command.CommandSource; +import org.apache.logging.log4j.LogManager; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.logging.Logger; + +public class ViaFabric implements ModInitializer { + public static final Logger JLOGGER = new JLoggerToLog4j(LogManager.getLogger("ViaFabric")); + public static final ExecutorService ASYNC_EXECUTOR; + public static final EventLoop EVENT_LOOP; + public static final CompletableFuture INIT_FUTURE = new CompletableFuture<>(); + public static VFConfig config; + + static { + ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ViaFabric-%d").build(); + ASYNC_EXECUTOR = Executors.newFixedThreadPool(8, factory); + EVENT_LOOP = new DefaultEventLoop(factory); + EVENT_LOOP.submit(INIT_FUTURE::join); // https://github.com/ViaVersion/ViaFabric/issues/53 ugly workaround code but works tm + } + + public static LiteralArgumentBuilder command(String commandName) { + return LiteralArgumentBuilder.literal(commandName) + .then( + RequiredArgumentBuilder + .argument("args", StringArgumentType.greedyString()) + .executes(((VRCommandHandler) Via.getManager().getCommandHandler())::execute) + .suggests(((VRCommandHandler) Via.getManager().getCommandHandler())::suggestion) + ) + .executes(((VRCommandHandler) Via.getManager().getCommandHandler())::execute); + } + + @Override + public void onInitialize() { + FabricPlatform platform = new FabricPlatform(); + + Via.init(ViaManagerImpl.builder() + .injector(new FabricInjector()) + .loader(new VFLoader()) + .commandHandler(new VRCommandHandler()) + .platform(platform).build()); + + platform.init(); + + FabricLoader.getInstance().getModContainer("viabackwards").ifPresent(mod -> MappingDataLoader.enableMappingsCache()); + + ((ViaManagerImpl) Via.getManager()).init(); + + Via.getManager().getProtocolManager().registerBaseProtocol(HostnameParserProtocol.INSTANCE, Range.lessThan(Integer.MIN_VALUE)); + ProtocolVersion.register(-2, "AUTO"); + + FabricLoader.getInstance().getEntrypoints("viafabric:via_api_initialized", Runnable.class).forEach(Runnable::run); + + registerCommandsV1(); + + config = new VFConfig(FabricLoader.getInstance().getConfigDir().resolve("ViaFabric") + .resolve("viafabric.yml").toFile()); + + INIT_FUTURE.complete(null); + } + + + private void registerCommandsV1() { + try { + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(command("viaversion"))); + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(command("viaver"))); + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(command("vvfabric"))); + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { + ClientCommandManager.DISPATCHER.register(command("viafabricclient")); + } + } catch (NoClassDefFoundError ignored) { + JLOGGER.info("Couldn't register command as Fabric Commands V1 isn't installed"); + } + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/ViaFabricClient.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/ViaFabricClient.java new file mode 100644 index 0000000..1a0f824 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/ViaFabricClient.java @@ -0,0 +1,39 @@ +package com.viaversion.fabric.mc119; + +import com.viaversion.fabric.mc119.gui.ViaConfigScreen; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.TexturedButtonWidget; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Identifier; + +public class ViaFabricClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + registerGui(); + } + + private void registerGui() { + try { + ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + if (!(screen instanceof MultiplayerScreen)) return; + ButtonWidget enableClientSideViaVersion = new TexturedButtonWidget(scaledWidth / 2 + 113, 10, + 40, 20, // Size + 0, 0, // Start pos of texture + 20, // v Hover offset + new Identifier("viafabric:textures/gui/widgets.png"), + 256, 256, // Texture size + it -> MinecraftClient.getInstance().setScreen(new ViaConfigScreen(screen)), + new TranslatableText("gui.via_button")); + if (ViaFabric.config.isHideButton()) enableClientSideViaVersion.visible = false; + Screens.getButtons(screen).add(enableClientSideViaVersion); + }); + } catch (NoClassDefFoundError ignored) { + ViaFabric.JLOGGER.info("Couldn't register screen handler as Fabric Screen isn't installed"); + } + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/commands/NMSCommandSender.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/commands/NMSCommandSender.java new file mode 100644 index 0000000..2859ad6 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/commands/NMSCommandSender.java @@ -0,0 +1,55 @@ +package com.viaversion.fabric.mc119.commands; + +import com.viaversion.fabric.common.util.RemappingUtil; +import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource; +import net.minecraft.command.CommandSource; +import net.minecraft.entity.Entity; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; +import com.viaversion.viaversion.api.command.ViaCommandSender; + +import java.util.UUID; + +public class NMSCommandSender implements ViaCommandSender { + private final CommandSource source; + + public NMSCommandSender(CommandSource source) { + this.source = source; + } + + @Override + public boolean hasPermission(String s) { + // https://gaming.stackexchange.com/questions/138602/what-does-op-permission-level-do + return source.hasPermissionLevel(3); + } + + @Override + public void sendMessage(String s) { + if (source instanceof ServerCommandSource) { + ((ServerCommandSource) source).sendFeedback(Text.Serializer.fromJson(RemappingUtil.legacyToJson(s)), false); + } else if (source instanceof FabricClientCommandSource) { + ((FabricClientCommandSource) source).sendFeedback(Text.Serializer.fromJson(RemappingUtil.legacyToJson(s))); + } + } + + @Override + public UUID getUUID() { + if (source instanceof ServerCommandSource) { + Entity entity = ((ServerCommandSource) source).getEntity(); + if (entity != null) return entity.getUuid(); + } else if (source instanceof FabricClientCommandSource) { + return ((FabricClientCommandSource) source).getPlayer().getUuid(); + } + return UUID.fromString(getName()); + } + + @Override + public String getName() { + if (source instanceof ServerCommandSource) { + return ((ServerCommandSource) source).getName(); + } else if (source instanceof FabricClientCommandSource) { + return ((FabricClientCommandSource) source).getPlayer().getEntityName(); + } + return "?"; + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/commands/VRCommandHandler.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/commands/VRCommandHandler.java new file mode 100644 index 0000000..cffd134 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/commands/VRCommandHandler.java @@ -0,0 +1,55 @@ +package com.viaversion.fabric.mc119.commands; + +import com.viaversion.fabric.common.commands.subs.LeakDetectSubCommand; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.command.CommandSource; +import com.viaversion.viaversion.commands.ViaCommandHandler; + +import java.util.concurrent.CompletableFuture; + +public class VRCommandHandler extends ViaCommandHandler { + { + try { + registerSubCommand(new LeakDetectSubCommand()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public int execute(CommandContext ctx) { + String[] args = new String[0]; + try { + args = StringArgumentType.getString(ctx, "args").split(" "); + } catch (IllegalArgumentException ignored) { + } + onCommand( + new NMSCommandSender(ctx.getSource()), + args + ); + return 1; + } + + public CompletableFuture suggestion(CommandContext ctx, SuggestionsBuilder builder) { + String[] args; + try { + args = StringArgumentType.getString(ctx, "args").split(" ", -1); + } catch (IllegalArgumentException ignored) { + args = new String[]{""}; + } + String[] pref = args.clone(); + pref[pref.length - 1] = ""; + String prefix = String.join(" ", pref); + onTabComplete(new NMSCommandSender(ctx.getSource()), args) + .stream() + .map(it -> { + SuggestionsBuilder b = new SuggestionsBuilder(builder.getInput(), prefix.length() + builder.getStart()); + b.suggest(it); + return b; + }) + .forEach(builder::add); + return builder.buildFuture(); + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/gui/ModMenuConfig.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/gui/ModMenuConfig.java new file mode 100644 index 0000000..960f9c0 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/gui/ModMenuConfig.java @@ -0,0 +1,19 @@ +package com.viaversion.fabric.mc119.gui; + +import com.google.common.collect.ImmutableMap; +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; + +import java.util.Map; + +public class ModMenuConfig implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return ViaConfigScreen::new; + } + + @Override + public Map> getProvidedConfigScreenFactories() { + return ImmutableMap.of("viafabric", getModConfigScreenFactory()); + } +} \ No newline at end of file diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/gui/ViaConfigScreen.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/gui/ViaConfigScreen.java new file mode 100644 index 0000000..963f400 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/gui/ViaConfigScreen.java @@ -0,0 +1,160 @@ +package com.viaversion.fabric.mc119.gui; + +import com.viaversion.fabric.common.config.AbstractViaConfigScreen; +import com.viaversion.fabric.mc119.ViaFabric; +import com.viaversion.fabric.common.util.ProtocolUtils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ConfirmScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ScreenTexts; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; + +import java.util.concurrent.CompletableFuture; + +@Environment(EnvType.CLIENT) +public class ViaConfigScreen extends Screen implements AbstractViaConfigScreen { + private static CompletableFuture latestProtocolSave; + private final Screen parent; + private TextFieldWidget protocolVersion; + + public ViaConfigScreen(Screen parent) { + super(new TranslatableText(TITLE_TRANSLATE_ID)); + this.parent = parent; + } + + @Override + protected void init() { + int entries = 0; + + this.addDrawableChild(new ButtonWidget(this.width / 2 - 155 + entries % 2 * 160, + this.height / 6 + 24 * (entries >> 1), + 150, + 20, getClientSideText(), this::onClickClientSide)); + entries++; + + this.addDrawableChild(new ButtonWidget(this.width / 2 - 155 + entries % 2 * 160, + this.height / 6 + 24 * (entries >> 1), + 150, + 20, getHideViaButtonText(), this::onHideViaButton)); + entries++; + + protocolVersion = new TextFieldWidget(this.textRenderer, + this.width / 2 - 155 + entries % 2 * 160, + this.height / 6 + 24 * (entries >> 1), + 150, + 20, new TranslatableText("gui.protocol_version_field.name")); + entries++; + + protocolVersion.setTextPredicate(ProtocolUtils::isStartOfProtocolText); + protocolVersion.setChangedListener(this::onChangeVersionField); + int clientSideVersion = ViaFabric.config.getClientSideVersion(); + protocolVersion.setText(ProtocolUtils.getProtocolName(clientSideVersion)); + + this.addDrawableChild(protocolVersion); + + //noinspection ConstantConditions + if (entries % 2 == 1) { + entries++; + } + + this.addDrawableChild(new ButtonWidget(this.width / 2 - 100, this.height / 6 + 24 * (entries >> 1), 200, 20, ScreenTexts.DONE, (buttonWidget) -> this.client.setScreen(this.parent))); + } + + private void onChangeVersionField(String text) { + protocolVersion.setSuggestion(null); + int newVersion = ViaFabric.config.getClientSideVersion(); + + Integer parsed = ProtocolUtils.parseProtocolId(text); + boolean validProtocol; + + if (parsed != null) { + newVersion = parsed; + validProtocol = true; + } else { + validProtocol = false; + String[] suggestions = ProtocolUtils.getProtocolSuggestions(text); + if (suggestions.length == 1) { + protocolVersion.setSuggestion(suggestions[0].substring(text.length())); + } + } + + protocolVersion.setEditableColor( + getProtocolTextColor(ProtocolUtils.isSupportedClientSide(newVersion), + validProtocol)); + + int finalNewVersion = newVersion; + if (latestProtocolSave == null) latestProtocolSave = CompletableFuture.completedFuture(null); + ViaFabric.config.setClientSideVersion(finalNewVersion); + latestProtocolSave = latestProtocolSave.thenRunAsync(ViaFabric.config::saveConfig, ViaFabric.ASYNC_EXECUTOR); + } + + private void onClickClientSide(ButtonWidget widget) { + if (!ViaFabric.config.isClientSideEnabled()) { + MinecraftClient.getInstance().setScreen(new ConfirmScreen( + answer -> { + if (answer) { + ViaFabric.config.setClientSideEnabled(true); + ViaFabric.config.setClientSideVersion(-2); // AUTO + ViaFabric.config.saveConfig(); + widget.setMessage(getClientSideText()); + } + MinecraftClient.getInstance().setScreen(this); + }, + new TranslatableText("gui.enable_client_side.question"), + new TranslatableText("gui.enable_client_side.warning"), + new TranslatableText("gui.enable_client_side.enable"), + new TranslatableText("gui.cancel") + )); + } else { + ViaFabric.config.setClientSideEnabled(false); + ViaFabric.config.saveConfig(); + } + widget.setMessage(getClientSideText()); + } + + @Override + public void removed() { + ViaFabric.config.saveConfig(); + } + + @Override + public void close() { + this.client.setScreen(this.parent); + } + + private TranslatableText getClientSideText() { + return ViaFabric.config.isClientSideEnabled() ? + new TranslatableText("gui.client_side.disable") + : new TranslatableText("gui.client_side.enable"); + } + + private TranslatableText getHideViaButtonText() { + return ViaFabric.config.isHideButton() ? + new TranslatableText("gui.hide_via_button.disable") : new TranslatableText("gui.hide_via_button.enable"); + } + + private void onHideViaButton(ButtonWidget widget) { + ViaFabric.config.setHideButton(!ViaFabric.config.isHideButton()); + ViaFabric.config.saveConfig(); + widget.setMessage(getHideViaButtonText()); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + this.renderBackground(matrices); + drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 20, 16777215); + super.render(matrices, mouseX, mouseY, delta); + } + + @Override + public void tick() { + super.tick(); + protocolVersion.tick(); + } +} + diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/address/client/MixinAllowedAddressResolver.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/address/client/MixinAllowedAddressResolver.java new file mode 100644 index 0000000..70ca3a0 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/address/client/MixinAllowedAddressResolver.java @@ -0,0 +1,44 @@ +package com.viaversion.fabric.mc119.mixin.address.client; + +import com.viaversion.fabric.common.AddressParser; +import net.minecraft.client.network.Address; +import net.minecraft.client.network.AllowedAddressResolver; +import net.minecraft.client.network.ServerAddress; +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.CallbackInfoReturnable; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.Optional; + +@Mixin(AllowedAddressResolver.class) +public abstract class MixinAllowedAddressResolver { + @Shadow + public abstract Optional
resolve(ServerAddress address); + + @Inject(method = "resolve", at = @At(value = "HEAD"), cancellable = true) + private void resolveVF(ServerAddress address, CallbackInfoReturnable> cir) { + AddressParser viaAddr = new AddressParser().parse(address.getAddress()); + if (viaAddr.viaSuffix == null) { + return; + } + + ServerAddress realAddress = new ServerAddress(viaAddr.serverAddress, address.getPort()); + + cir.setReturnValue(resolve(realAddress).map(it -> viaFabricAddSuffix(it, viaAddr.getSuffixWithOptions()))); + } + + private Address viaFabricAddSuffix(Address it, String viaSuffix) { + try { + return Address.create(new InetSocketAddress( + InetAddress.getByAddress(it.getHostName() + "." + viaSuffix, + it.getInetSocketAddress().getAddress().getAddress()), it.getPort())); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/debug/client/MixinClientConnectionAccessor.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/debug/client/MixinClientConnectionAccessor.java new file mode 100644 index 0000000..7cabf80 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/debug/client/MixinClientConnectionAccessor.java @@ -0,0 +1,12 @@ +package com.viaversion.fabric.mc119.mixin.debug.client; + +import io.netty.channel.Channel; +import net.minecraft.network.ClientConnection; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ClientConnection.class) +public interface MixinClientConnectionAccessor { + @Accessor + Channel getChannel(); +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/debug/client/MixinDebugHud.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/debug/client/MixinDebugHud.java new file mode 100644 index 0000000..a47fc8d --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/debug/client/MixinDebugHud.java @@ -0,0 +1,37 @@ +package com.viaversion.fabric.mc119.mixin.debug.client; + +import com.viaversion.fabric.common.handler.CommonTransformer; +import com.viaversion.fabric.common.handler.FabricDecodeHandler; +import com.viaversion.viaversion.api.connection.ProtocolInfo; +import io.netty.channel.ChannelHandler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.DebugHud; +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 com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; + +import java.util.List; + +@Mixin(DebugHud.class) +public class MixinDebugHud { + @Inject(at = @At("RETURN"), method = "getLeftText") + protected void getLeftText(CallbackInfoReturnable> info) { + String line = "[ViaFabric] I: " + Via.getManager().getConnectionManager().getConnections().size() + " (F: " + + Via.getManager().getConnectionManager().getConnectedClients().size() + ")"; + @SuppressWarnings("ConstantConditions") ChannelHandler viaDecoder = ((MixinClientConnectionAccessor) MinecraftClient.getInstance().getNetworkHandler() + .getConnection()).getChannel().pipeline().get(CommonTransformer.HANDLER_DECODER_NAME); + if (viaDecoder instanceof FabricDecodeHandler) { + ProtocolInfo protocol = ((FabricDecodeHandler) viaDecoder).getInfo().getProtocolInfo(); + if (protocol != null) { + ProtocolVersion serverVer = ProtocolVersion.getProtocol(protocol.getServerProtocolVersion()); + ProtocolVersion clientVer = ProtocolVersion.getProtocol(protocol.getProtocolVersion()); + line += " / C: " + clientVer + " S: " + serverVer + " A: " + protocol.getUser().isActive(); + } + } + + info.getReturnValue().add(line); + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinMultiplayerServerListPingerListener.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinMultiplayerServerListPingerListener.java new file mode 100644 index 0000000..74cafae --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinMultiplayerServerListPingerListener.java @@ -0,0 +1,29 @@ +package com.viaversion.fabric.mc119.mixin.gui.client; + +import com.viaversion.fabric.common.gui.ViaServerInfo; +import com.viaversion.fabric.common.handler.FabricDecodeHandler; +import com.viaversion.fabric.mc119.mixin.debug.client.MixinClientConnectionAccessor; +import net.minecraft.client.network.ServerInfo; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.listener.ClientQueryPacketListener; +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(targets = "net.minecraft.client.network.MultiplayerServerListPinger$1") +public abstract class MixinMultiplayerServerListPingerListener implements ClientQueryPacketListener { + @Shadow + public abstract ClientConnection getConnection(); + + @Redirect(method = "onResponse(Lnet/minecraft/network/packet/s2c/query/QueryResponseS2CPacket;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerInfo;getIcon()Ljava/lang/String;")) + private String onResponseCaptureServerInfo(ServerInfo serverInfo) { + FabricDecodeHandler decoder = ((MixinClientConnectionAccessor) this.getConnection()).getChannel() + .pipeline().get(FabricDecodeHandler.class); + if (decoder != null) { + ((ViaServerInfo) serverInfo).setViaTranslating(decoder.getInfo().isActive()); + ((ViaServerInfo) serverInfo).setViaServerVer(decoder.getInfo().getProtocolInfo().getServerProtocolVersion()); + } + return serverInfo.getIcon(); + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinServerEntry.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinServerEntry.java new file mode 100644 index 0000000..62d96d8 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinServerEntry.java @@ -0,0 +1,46 @@ +package com.viaversion.fabric.mc119.mixin.gui.client; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.viaversion.fabric.common.gui.ViaServerInfo; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; +import net.minecraft.client.network.ServerInfo; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Identifier; +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.ArrayList; +import java.util.List; + +@Mixin(MultiplayerServerListWidget.ServerEntry.class) +public class MixinServerEntry { + @Shadow + @Final + private ServerInfo server; + + // todo fix this intermediary + @Redirect(method = "render", at = @At(value = "INVOKE", ordinal = 0, + target = "Lcom/mojang/blaze3d/systems/RenderSystem;setShaderTexture(ILnet/minecraft/class_2960;)V")) + private void redirectPingIcon(int i, Identifier identifier) { + if (identifier.equals(DrawableHelper.GUI_ICONS_TEXTURE) && ((ViaServerInfo) this.server).isViaTranslating()) { + RenderSystem.setShaderTexture(i, new Identifier("viafabric:textures/gui/icons.png")); + return; + } + RenderSystem.setShaderTexture(i, identifier); + } + + @Redirect(method = "render", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerScreen;setTooltip(Ljava/util/List;)V")) + private void addServerVer(MultiplayerScreen multiplayerScreen, List tooltipText) { + ProtocolVersion proto = ProtocolVersion.getProtocol(((ViaServerInfo) this.server).getViaServerVer()); + List lines = new ArrayList<>(tooltipText); + lines.add(new TranslatableText("gui.ping_version.translated", proto.getName())); + multiplayerScreen.setTooltip(lines); + } +} \ No newline at end of file diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinServerInfo.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinServerInfo.java new file mode 100644 index 0000000..49833cb --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/gui/client/MixinServerInfo.java @@ -0,0 +1,29 @@ +package com.viaversion.fabric.mc119.mixin.gui.client; + +import com.viaversion.fabric.common.gui.ViaServerInfo; +import net.minecraft.client.network.ServerInfo; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ServerInfo.class) +public class MixinServerInfo implements ViaServerInfo { + private boolean viaTranslating; + private int viaServerVer; + + public int getViaServerVer() { + return viaServerVer; + } + + public void setViaServerVer(int viaServerVer) { + this.viaServerVer = viaServerVer; + } + + @Override + public boolean isViaTranslating() { + return viaTranslating; + } + + @Override + public void setViaTranslating(boolean via) { + this.viaTranslating = via; + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/MixinClientConnection.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/MixinClientConnection.java new file mode 100644 index 0000000..f1ec1e9 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/MixinClientConnection.java @@ -0,0 +1,39 @@ +package com.viaversion.fabric.mc119.mixin.pipeline; + +import com.viaversion.fabric.common.handler.PipelineReorderEvent; +import io.netty.channel.Channel; +import net.minecraft.network.ClientConnection; +import org.slf4j.Logger; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(ClientConnection.class) +public class MixinClientConnection { + @Shadow + private Channel channel; + + @Redirect( + method = "exceptionCaught", + remap = false, + at = @At( + value = "INVOKE", + target = "Lorg/slf4j/Logger;debug(Ljava/lang/String;Ljava/lang/Throwable;)V" + )) + private void redirectDebug(Logger logger, String message, Throwable t) { + if ("Failed to sent packet".equals(message)) { + logger.info(message, t); + } else { + logger.debug(message, t); + } + } + + @Inject(method = "setCompressionThreshold", at = @At("RETURN")) + private void reorderCompression(int compressionThreshold, boolean rejectBad, CallbackInfo ci) { + channel.pipeline().fireUserEventTriggered(new PipelineReorderEvent()); + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/MixinServerNetworkIoChInit.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/MixinServerNetworkIoChInit.java new file mode 100644 index 0000000..7e27aee --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/MixinServerNetworkIoChInit.java @@ -0,0 +1,28 @@ +package com.viaversion.fabric.mc119.mixin.pipeline; + +import com.viaversion.fabric.common.handler.CommonTransformer; +import com.viaversion.fabric.common.handler.FabricDecodeHandler; +import com.viaversion.fabric.common.handler.FabricEncodeHandler; +import com.viaversion.viaversion.connection.UserConnectionImpl; +import com.viaversion.viaversion.protocol.ProtocolPipelineImpl; +import io.netty.channel.Channel; +import io.netty.channel.socket.SocketChannel; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.viaversion.viaversion.api.connection.UserConnection; + +@Mixin(targets = "net.minecraft.server.ServerNetworkIo$1") +public class MixinServerNetworkIoChInit { + @Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false) + private void onInitChannel(Channel channel, CallbackInfo ci) { + if (channel instanceof SocketChannel) { + UserConnection user = new UserConnectionImpl(channel); + new ProtocolPipelineImpl(user); + + channel.pipeline().addBefore("encoder", CommonTransformer.HANDLER_ENCODER_NAME, new FabricEncodeHandler(user)); + channel.pipeline().addBefore("decoder", CommonTransformer.HANDLER_DECODER_NAME, new FabricDecodeHandler(user)); + } + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/client/MixinClientConnection.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/client/MixinClientConnection.java new file mode 100644 index 0000000..5d58376 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/client/MixinClientConnection.java @@ -0,0 +1,26 @@ +package com.viaversion.fabric.mc119.mixin.pipeline.client; + +import com.viaversion.fabric.mc119.ViaFabric; +import com.viaversion.fabric.mc119.service.ProtocolAutoDetector; +import net.minecraft.network.ClientConnection; +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.net.InetSocketAddress; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +@Mixin(ClientConnection.class) +public class MixinClientConnection { + @Inject(method = "connect", at = @At("HEAD")) + private static void onConnect(InetSocketAddress address, boolean useEpoll, CallbackInfoReturnable cir) { + try { + if (!ViaFabric.config.isClientSideEnabled()) return; + ProtocolAutoDetector.detectVersion(address).get(10, TimeUnit.SECONDS); + } catch (Exception e) { + ViaFabric.JLOGGER.log(Level.WARNING, "Could not auto-detect protocol for " + address + " " + e); + } + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/client/MixinClientConnectionChInit.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/client/MixinClientConnectionChInit.java new file mode 100644 index 0000000..8fbd219 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/mixin/pipeline/client/MixinClientConnectionChInit.java @@ -0,0 +1,30 @@ +package com.viaversion.fabric.mc119.mixin.pipeline.client; + +import com.viaversion.fabric.common.handler.FabricDecodeHandler; +import com.viaversion.fabric.common.handler.FabricEncodeHandler; +import com.viaversion.fabric.common.handler.CommonTransformer; +import com.viaversion.fabric.common.protocol.HostnameParserProtocol; +import com.viaversion.viaversion.connection.UserConnectionImpl; +import com.viaversion.viaversion.protocol.ProtocolPipelineImpl; +import io.netty.channel.Channel; +import io.netty.channel.socket.SocketChannel; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.viaversion.viaversion.api.connection.UserConnection; + +@Mixin(targets = "net.minecraft.network.ClientConnection$1") +public class MixinClientConnectionChInit { + @Inject(method = "initChannel", at = @At(value = "TAIL"), remap = false) + private void onInitChannel(Channel channel, CallbackInfo ci) { + if (channel instanceof SocketChannel) { + UserConnection user = new UserConnectionImpl(channel, true); + new ProtocolPipelineImpl(user).add(HostnameParserProtocol.INSTANCE); + + channel.pipeline() + .addBefore("encoder", CommonTransformer.HANDLER_ENCODER_NAME, new FabricEncodeHandler(user)) + .addBefore("decoder", CommonTransformer.HANDLER_DECODER_NAME, new FabricDecodeHandler(user)); + } + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/FabricNativeVersionProvider.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/FabricNativeVersionProvider.java new file mode 100644 index 0000000..5855d5f --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/FabricNativeVersionProvider.java @@ -0,0 +1,11 @@ +package com.viaversion.fabric.mc119.platform; + +import com.viaversion.fabric.common.platform.NativeVersionProvider; +import net.minecraft.SharedConstants; + +public class FabricNativeVersionProvider implements NativeVersionProvider { + @Override + public int getNativeServerVersion() { + return SharedConstants.getGameVersion().getProtocolVersion(); + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/FabricPlatform.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/FabricPlatform.java new file mode 100644 index 0000000..8085b37 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/FabricPlatform.java @@ -0,0 +1,127 @@ +package com.viaversion.fabric.mc119.platform; + +import com.viaversion.fabric.common.commands.UserCommandSender; +import com.viaversion.fabric.common.platform.NativeVersionProvider; +import com.viaversion.fabric.common.provider.AbstractFabricPlatform; +import com.viaversion.fabric.common.util.FutureTaskId; +import com.viaversion.fabric.common.util.RemappingUtil; +import com.viaversion.fabric.mc119.ViaFabric; +import com.viaversion.fabric.mc119.commands.NMSCommandSender; +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.command.ViaCommandSender; +import io.netty.channel.EventLoop; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.function.Supplier; +import java.util.logging.Level; + +public class FabricPlatform extends AbstractFabricPlatform { + public static MinecraftServer getServer() { + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { + return getIntegratedServer(); + } + return (MinecraftServer) FabricLoader.getInstance().getGameInstance(); + } + + @Environment(EnvType.CLIENT) + private static MinecraftServer getIntegratedServer() { + return MinecraftClient.getInstance().getServer(); + } + + @Override + public FutureTaskId runSync(Runnable runnable) { + if (getServer() != null) { + return runServerSync(runnable); + } else { + return runEventLoop(runnable); + } + } + + private FutureTaskId runServerSync(Runnable runnable) { + // Kick task needs to be on main thread, it does already have error logger + return new FutureTaskId(CompletableFuture.runAsync(runnable, getServer())); + } + + @Override + public ViaCommandSender[] getOnlinePlayers() { + MinecraftServer server = getServer(); + if (server != null && server.isOnThread()) { + return getServerPlayers(); + } + return Via.getManager().getConnectionManager().getConnectedClients().values().stream() + .map(UserCommandSender::new) + .toArray(ViaCommandSender[]::new); + } + + private ViaCommandSender[] getServerPlayers() { + return getServer().getPlayerManager().getPlayerList().stream() + .map(Entity::getCommandSource) + .map(NMSCommandSender::new) + .toArray(ViaCommandSender[]::new); + } + + @Override + public void sendMessage(UUID uuid, String s) { + sendMessageServer(uuid, s); + } + + private void sendMessageServer(UUID uuid, String s) { + MinecraftServer server = getServer(); + if (server == null) return; + runServerSync(() -> { + ServerPlayerEntity player = server.getPlayerManager().getPlayer(uuid); + if (player == null) return; + player.sendMessage(Text.Serializer.fromJson( + RemappingUtil.legacyToJson(s) + ), false); + }); + } + + @Override + public boolean kickPlayer(UUID uuid, String s) { + return kickServer(uuid, s); + } + + private boolean kickServer(UUID uuid, String s) { + MinecraftServer server = getServer(); + if (server == null) return false; + Supplier kickTask = () -> { + ServerPlayerEntity player = server.getPlayerManager().getPlayer(uuid); + if (player == null) return false; + player.networkHandler.disconnect(Text.Serializer.fromJson(RemappingUtil.legacyToJson(s))); + return true; + }; + if (server.isOnThread()) { + return kickTask.get(); + } else { + ViaFabric.JLOGGER.log(Level.WARNING, "Weird!? Player kicking was called off-thread", new Throwable()); + runServerSync(kickTask::get); + } + return false; // Can't know if it worked + } + + @Override + protected void installNativeVersionProvider() { + Via.getManager().getProviders().use(NativeVersionProvider.class, new FabricNativeVersionProvider()); + } + + @Override + protected ExecutorService asyncService() { + return ViaFabric.ASYNC_EXECUTOR; + } + + @Override + protected EventLoop eventLoop() { + return ViaFabric.EVENT_LOOP; + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/VFLoader.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/VFLoader.java new file mode 100644 index 0000000..380bf18 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/platform/VFLoader.java @@ -0,0 +1,34 @@ +package com.viaversion.fabric.mc119.platform; + +import com.viaversion.fabric.mc119.providers.VRHandItemProvider; +import com.viaversion.fabric.mc119.providers.FabricVersionProvider; +import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.platform.ViaPlatformLoader; +import com.viaversion.viaversion.bungee.providers.BungeeMovementTransmitter; +import com.viaversion.viaversion.api.protocol.version.VersionProvider; +import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.HandItemProvider; +import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; + +public class VFLoader implements ViaPlatformLoader { + @Override + public void load() { + Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter()); + Via.getManager().getProviders().use(VersionProvider.class, new FabricVersionProvider()); + + if (Via.getPlatform().getConf().isItemCache()) { + VRHandItemProvider handProvider = new VRHandItemProvider(); + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { + handProvider.registerClientTick(); + } + handProvider.registerServerTick(); + Via.getManager().getProviders().use(HandItemProvider.class, handProvider); + } + } + + @Override + public void unload() { + // Nothing to do + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/providers/FabricVersionProvider.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/providers/FabricVersionProvider.java new file mode 100644 index 0000000..9cae868 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/providers/FabricVersionProvider.java @@ -0,0 +1,36 @@ +package com.viaversion.fabric.mc119.providers; + +import com.viaversion.fabric.common.config.VFConfig; +import com.viaversion.fabric.common.provider.AbstractFabricVersionProvider; +import com.viaversion.fabric.mc119.ViaFabric; +import com.viaversion.fabric.mc119.service.ProtocolAutoDetector; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import io.netty.channel.ChannelPipeline; +import net.minecraft.network.ClientConnection; + +import java.net.InetSocketAddress; +import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; + +public class FabricVersionProvider extends AbstractFabricVersionProvider { + @Override + protected Logger getLogger() { + return ViaFabric.JLOGGER; + } + + @Override + protected VFConfig getConfig() { + return ViaFabric.config; + } + + @Override + protected CompletableFuture detectVersion(InetSocketAddress address) { + return ProtocolAutoDetector.detectVersion(address); + } + + @Override + protected boolean isMulticonnectHandler(ChannelPipeline pipe) { + return pipe.get(ClientConnection.class).getPacketListener() + .getClass().getName().startsWith("net.earthcomputer.multiconnect"); + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/providers/VRHandItemProvider.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/providers/VRHandItemProvider.java new file mode 100644 index 0000000..0e564d6 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/providers/VRHandItemProvider.java @@ -0,0 +1,80 @@ +package com.viaversion.fabric.mc119.providers; + +import com.viaversion.fabric.common.util.RemappingUtil; +import com.viaversion.fabric.mc119.ViaFabric; +import com.viaversion.viaversion.api.connection.UserConnection; +import com.viaversion.viaversion.api.minecraft.item.DataItem; +import com.viaversion.viaversion.api.minecraft.item.Item; +import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.HandItemProvider; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class VRHandItemProvider extends HandItemProvider { + public Item clientItem = null; + public final Map serverPlayers = new ConcurrentHashMap<>(); + + @Override + public Item getHandItem(UserConnection info) { + Item serverItem; + if (info.isClientSide()) { + return getClientItem(); + } else if ((serverItem = serverPlayers.get(info.getProtocolInfo().getUuid())) != null) { + return new DataItem(serverItem); + } + return super.getHandItem(info); + } + + private Item getClientItem() { + if (clientItem == null) { + return new DataItem(0, (byte) 0, (short) 0, null); + } + return new DataItem(clientItem); + } + + @Environment(EnvType.CLIENT) + public void registerClientTick() { + try { + ClientTickEvents.END_WORLD_TICK.register(clientWorld -> tickClient()); + } catch (NoClassDefFoundError ignored) { + ViaFabric.JLOGGER.info("Fabric Lifecycle V1 isn't installed"); + } + } + + public void registerServerTick() { + try { + ServerTickEvents.END_WORLD_TICK.register(this::tickServer); + } catch (NoClassDefFoundError ignored) { + } + } + + private void tickClient() { + ClientPlayerEntity p = MinecraftClient.getInstance().player; + if (p != null) { + clientItem = fromNative(p.getInventory().getMainHandStack()); + } + } + + private void tickServer(World world) { + serverPlayers.clear(); + world.getPlayers().forEach(it -> serverPlayers + .put(it.getUuid(), fromNative(it.getInventory().getMainHandStack()))); + } + + private Item fromNative(ItemStack original) { + Identifier iid = Registry.ITEM.getId(original.getItem()); + int id = RemappingUtil.swordId(iid.toString()); + return new DataItem(id, (byte) original.getCount(), (short) original.getDamage(), null); + } +} diff --git a/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/service/ProtocolAutoDetector.java b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/service/ProtocolAutoDetector.java new file mode 100644 index 0000000..2080ae7 --- /dev/null +++ b/viafabric-mc119/src/main/java/com/viaversion/fabric/mc119/service/ProtocolAutoDetector.java @@ -0,0 +1,125 @@ +package com.viaversion.fabric.mc119.service; + +import com.viaversion.fabric.common.AddressParser; +import com.viaversion.fabric.mc119.ViaFabric; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.*; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.timeout.ReadTimeoutHandler; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.network.*; +import net.minecraft.network.listener.ClientQueryPacketListener; +import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket; +import net.minecraft.network.packet.c2s.query.QueryRequestC2SPacket; +import net.minecraft.network.packet.s2c.query.QueryPongS2CPacket; +import net.minecraft.network.packet.s2c.query.QueryResponseS2CPacket; +import net.minecraft.server.ServerMetadata; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +@Environment(EnvType.CLIENT) +public class ProtocolAutoDetector { + private static final LoadingCache> SERVER_VER = CacheBuilder.newBuilder() + .expireAfterWrite(30, TimeUnit.SECONDS) + .build(CacheLoader.from((address) -> { + CompletableFuture future = new CompletableFuture<>(); + + try { + final ClientConnection clientConnection = new ClientConnection(NetworkSide.CLIENTBOUND); + + ChannelFuture ch = new Bootstrap() + .group(ClientConnection.CLIENT_IO_GROUP.get()) + .channel(NioSocketChannel.class) + .handler(new ChannelInitializer() { + protected void initChannel(Channel channel) { + try { + channel.config().setOption(ChannelOption.TCP_NODELAY, true); + channel.config().setOption(ChannelOption.IP_TOS, 0x18); // Stolen from Velocity, low delay, high reliability + } catch (ChannelException ignored) { + } + + channel.pipeline() + .addLast("timeout", new ReadTimeoutHandler(30)) + .addLast("splitter", new SplitterHandler()) + .addLast("decoder", new DecoderHandler(NetworkSide.CLIENTBOUND)) + .addLast("prepender", new SizePrepender()) + .addLast("encoder", new PacketEncoder(NetworkSide.SERVERBOUND)) + .addLast("packet_handler", clientConnection); + } + }) + .connect(address); + + ch.addListener(future1 -> { + if (!future1.isSuccess()) { + future.completeExceptionally(future1.cause()); + } else { + ch.channel().eventLoop().execute(() -> { // needs to execute after channel init + clientConnection.setPacketListener(new ClientQueryPacketListener() { + @Override + public void onResponse(QueryResponseS2CPacket packet) { + ServerMetadata meta = packet.getServerMetadata(); + ServerMetadata.Version version; + if (meta != null && (version = meta.getVersion()) != null) { + ProtocolVersion ver = ProtocolVersion.getProtocol(version.getProtocolVersion()); + future.complete(ver); + ViaFabric.JLOGGER.info("Auto-detected " + ver + " for " + address); + } else { + future.completeExceptionally(new IllegalArgumentException("Null version in query response")); + } + clientConnection.disconnect(LiteralText.EMPTY); + } + + @Override + public void onPong(QueryPongS2CPacket packet) { + clientConnection.disconnect(new LiteralText("Pong not requested!")); + } + + @Override + public void onDisconnected(Text reason) { + future.completeExceptionally(new IllegalStateException(reason.asString())); + } + + @Override + public ClientConnection getConnection() { + return clientConnection; + } + }); + + clientConnection.send(new HandshakeC2SPacket(address.getHostString(), + address.getPort(), NetworkState.STATUS)); + clientConnection.send(new QueryRequestC2SPacket()); + }); + } + }); + } catch (Throwable throwable) { + future.completeExceptionally(throwable); + } + + return future; + })); + + public static CompletableFuture detectVersion(InetSocketAddress address) { + try { + InetSocketAddress real = new InetSocketAddress(InetAddress.getByAddress + (new AddressParser().parse(address.getHostString()).serverAddress, + address.getAddress().getAddress()), address.getPort()); + return SERVER_VER.get(real); + } catch (UnknownHostException | ExecutionException e) { + ViaFabric.JLOGGER.log(Level.WARNING, "Protocol auto detector error: ", e); + return CompletableFuture.completedFuture(null); + } + } +} diff --git a/viafabric-mc119/src/main/resources/fabric.mod.json b/viafabric-mc119/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..7f9da15 --- /dev/null +++ b/viafabric-mc119/src/main/resources/fabric.mod.json @@ -0,0 +1,60 @@ +{ + "schemaVersion": 1, + "id": "viafabric-mc119", + "name": "ViaFabric for 1.19", + "version": "${version}", + "description": "${description}", + "license": "GPL-3.0", + "contact": { + "homepage": "https://viaversion.com/fabric", + "issues": "https://github.com/ViaVersion/ViaFabric/issues", + "sources": "https://github.com/ViaVersion/ViaFabric" + }, + "environment": "*", + "authors": [ + { + "name": "creeper123123321", + "contact": { + "homepage": "https://creeper123123321.github.io/" + } + } + ], + "contributors": [ + { + "name": "GitHub contributors", + "contact": { + "homepage": "https://github.com/ViaVersion/ViaFabric/graphs/contributors" + } + } + ], + "entrypoints": { + "main": [ + "com.viaversion.fabric.mc119.ViaFabric" + ], + "client": [ + "com.viaversion.fabric.mc119.ViaFabricClient" + ], + "modmenu": [ + "com.viaversion.fabric.mc119.gui.ModMenuConfig" + ] + }, + "depends": { + "fabric-resource-loader-v0": "*", + "minecraft": "1.19.x", + "viafabric": "*" + }, + "recommends": { + "fabric-command-api-v1": "*" + }, + "mixins": [ + "mixins.viafabric119.address.json", + "mixins.viafabric119.gui.json", + "mixins.viafabric119.debug.json", + "mixins.viafabric119.pipeline.json" + ], + "custom": { + "modmenu": { + "parent": "viafabric" + } + } +} diff --git a/viafabric-mc119/src/main/resources/mixins.viafabric119.address.json b/viafabric-mc119/src/main/resources/mixins.viafabric119.address.json new file mode 100644 index 0000000..6d318f2 --- /dev/null +++ b/viafabric-mc119/src/main/resources/mixins.viafabric119.address.json @@ -0,0 +1,13 @@ +{ + "required": true, + "compatibilityLevel": "JAVA_16", + "package": "com.viaversion.fabric.mc119.mixin.address", + "mixins": [ + ], + "client": [ + "client.MixinAllowedAddressResolver" + ], + "injectors": { + "defaultRequire": 0 + } +} diff --git a/viafabric-mc119/src/main/resources/mixins.viafabric119.debug.json b/viafabric-mc119/src/main/resources/mixins.viafabric119.debug.json new file mode 100644 index 0000000..291e54c --- /dev/null +++ b/viafabric-mc119/src/main/resources/mixins.viafabric119.debug.json @@ -0,0 +1,14 @@ +{ + "required": true, + "compatibilityLevel": "JAVA_16", + "package": "com.viaversion.fabric.mc119.mixin.debug", + "mixins": [ + ], + "client": [ + "client.MixinClientConnectionAccessor", + "client.MixinDebugHud" + ], + "injectors": { + "defaultRequire": 0 + } +} diff --git a/viafabric-mc119/src/main/resources/mixins.viafabric119.gui.json b/viafabric-mc119/src/main/resources/mixins.viafabric119.gui.json new file mode 100644 index 0000000..f8ec42f --- /dev/null +++ b/viafabric-mc119/src/main/resources/mixins.viafabric119.gui.json @@ -0,0 +1,15 @@ +{ + "required": true, + "compatibilityLevel": "JAVA_16", + "package": "com.viaversion.fabric.mc119.mixin.gui", + "mixins": [ + ], + "client": [ + "client.MixinMultiplayerServerListPingerListener", + "client.MixinServerEntry", + "client.MixinServerInfo" + ], + "injectors": { + "defaultRequire": 0 + } +} diff --git a/viafabric-mc119/src/main/resources/mixins.viafabric119.pipeline.json b/viafabric-mc119/src/main/resources/mixins.viafabric119.pipeline.json new file mode 100644 index 0000000..0ed570d --- /dev/null +++ b/viafabric-mc119/src/main/resources/mixins.viafabric119.pipeline.json @@ -0,0 +1,16 @@ +{ + "required": true, + "compatibilityLevel": "JAVA_16", + "package": "com.viaversion.fabric.mc119.mixin.pipeline", + "mixins": [ + "MixinClientConnection", + "MixinServerNetworkIoChInit" + ], + "client": [ + "client.MixinClientConnection", + "client.MixinClientConnectionChInit" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/viafabric-mc18/src/main/java/com/viaversion/fabric/mc18/gui/ViaConfigScreen.java b/viafabric-mc18/src/main/java/com/viaversion/fabric/mc18/gui/ViaConfigScreen.java index de99d62..1d07d79 100644 --- a/viafabric-mc18/src/main/java/com/viaversion/fabric/mc18/gui/ViaConfigScreen.java +++ b/viafabric-mc18/src/main/java/com/viaversion/fabric/mc18/gui/ViaConfigScreen.java @@ -1,5 +1,6 @@ package com.viaversion.fabric.mc18.gui; +import com.viaversion.fabric.common.config.AbstractViaConfigScreen; import com.viaversion.fabric.mc18.ViaFabric; import com.viaversion.fabric.common.util.ProtocolUtils; import net.fabricmc.api.EnvType; @@ -15,7 +16,7 @@ import net.minecraft.text.TranslatableText; import java.util.concurrent.CompletableFuture; @Environment(EnvType.CLIENT) -public class ViaConfigScreen extends Screen { +public class ViaConfigScreen extends Screen implements AbstractViaConfigScreen { private static CompletableFuture latestProtocolSave; private final Screen parent; private TextFieldWidget protocolVersion; @@ -23,20 +24,10 @@ public class ViaConfigScreen extends Screen { public ViaConfigScreen(Screen parent) { super(); - title = new TranslatableText("gui.viafabric_config.title"); + title = new TranslatableText(TITLE_TRANSLATE_ID); this.parent = parent; } - private static int getProtocolTextColor(boolean valid, boolean supported) { - - if (!valid) { - return 0xff0000; // Red - } else if (!supported) { - return 0xFFA500; // Orange - } - return 0xE0E0E0; // Default - } - @Override public void init() { int entries = 0; @@ -58,7 +49,7 @@ public class ViaConfigScreen extends Screen { this.height / 6 + 24 * (entries >> 1), 150, 20); - protocolVersion.setText(new TranslatableText("gui.protocol_version_field.name").asString()); + protocolVersion.setText(new TranslatableText(VERSION_TRANSLATE_ID).asString()); entries++; protocolVersion.setTextPredicate(ProtocolUtils::isStartOfProtocolText);