From e52ac66f52c65910926b3f01d6cf6216214110f8 Mon Sep 17 00:00:00 2001 From: elv1n200 Date: Thu, 16 Jul 2026 23:09:41 +0200 Subject: [PATCH 1/2] Port to Minecraft 26.x (Mojmap, unobfuscated era) 26.x ships unobfuscated, so there is no Yarn: everything is compiled directly against Mojang names. The GUI also moved from immediate-mode rendering to render-state extraction, so screens no longer override render(DrawContext) but extractRenderState(GuiGraphicsExtractor), and widgets render themselves once added. Build: - Loom 1.17 plain plugin (no -remap), no mappings dependency, Gradle 9.5.1 - Java 25, fabric-loader 0.19.3, fabric-api 0.154.2+26.1.2 API migration highlights: - Session -> User (getUser/getName/getProfileId) - Text -> Component, Formatting -> ChatFormatting, .formatted -> .withStyle - ButtonWidget -> Button (.dimensions -> .bounds), TextFieldWidget -> EditBox - MultiplayerScreen -> JoinMultiplayerScreen, this.client -> this.minecraft - ClientCommandManager -> ClientCommands - KeyBindingHelper -> KeyMappingHelper (fabric-key-mapping-api-v1) - TelemetryManager -> ClientTelemetryManager (TelemetryEventSender.DISABLED) - KeyInput -> KeyEvent (input.key()) Scoped out of the 26.x port (cosmetic, restorable): - DownloaderMixin: redirected an intermediary-only method with no Mojmap equivalent; its "isolate pack cache" toggle is hidden accordingly - SkinCache head textures: the NativeImage upload pipeline changed; rows fall back to placeholder avatars - In-world HUD alt indicator and ModMenu integration --- build.gradle | 31 +- gradle.properties | 13 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../elv1n200/sessionlogin/SessionLogin.java | 7 +- .../sessionlogin/SessionLoginClient.java | 43 +-- .../command/SessionLoginCommand.java | 58 ++-- .../mixin/ClientBrandRetrieverMixin.java | 2 +- .../sessionlogin/mixin/DownloaderMixin.java | 45 --- .../mixin/MinecraftClientMixin.java | 33 +- .../mixin/MultiplayerScreenMixin.java | 66 ++-- .../mixin/TelemetryManagerMixin.java | 14 +- .../modmenu/ModMenuIntegration.java | 20 -- .../screen/AccountManagerScreen.java | 314 ++++++++---------- .../screen/AddOfflineAccountScreen.java | 73 ++-- .../sessionlogin/screen/BulkImportScreen.java | 50 +-- .../screen/EditAccountScreen.java | 154 ++++----- .../sessionlogin/screen/EditEntryScreen.java | 85 ++--- .../screen/ImportExportScreen.java | 63 ++-- .../sessionlogin/screen/LoginScreen.java | 179 +++++----- .../screen/SetPasswordScreen.java | 100 +++--- .../sessionlogin/screen/SettingsScreen.java | 61 ++-- .../screen/TamperWarningScreen.java | 70 ++-- .../sessionlogin/screen/UnlockScreen.java | 74 ++--- .../elv1n200/sessionlogin/util/ApiUtils.java | 8 +- .../sessionlogin/util/FormattingUtils.java | 12 +- .../elv1n200/sessionlogin/util/Notifier.java | 25 +- .../sessionlogin/util/SessionUtils.java | 20 +- .../elv1n200/sessionlogin/util/SkinCache.java | 90 +---- src/main/resources/fabric.mod.json | 9 +- src/main/resources/sessionlogin.mixins.json | 3 +- 30 files changed, 718 insertions(+), 1006 deletions(-) delete mode 100644 src/main/java/dev/elv1n200/sessionlogin/mixin/DownloaderMixin.java delete mode 100644 src/main/java/dev/elv1n200/sessionlogin/modmenu/ModMenuIntegration.java diff --git a/build.gradle b/build.gradle index a154622..107ac2a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,7 @@ plugins { - id 'net.fabricmc.fabric-loom-remap' version "${loom_version}" + // 26.x is unobfuscated: no remapping and no mappings dependency, so the + // plain loom plugin (not -remap) is the right one here. + id 'net.fabricmc.fabric-loom' version "${loom_version}" id 'maven-publish' } @@ -15,20 +17,15 @@ repositories { dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" - - // Optional ModMenu integration: present at compile, not bundled. If the - // player has ModMenu installed the entrypoint hooks; otherwise the class - // is simply never loaded. - modCompileOnly "com.terraformersmc:modmenu:17.0.0" + // 26.x ships unobfuscated → the game already has Mojang names, so Loom + // needs no mappings dependency (and rejects one). + implementation "net.fabricmc:fabric-loader:${project.loader_version}" + implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" // Bundled inside the mod jar (Jar-in-Jar) so reading Modrinth App's - // SQLite account DB works out of the box. Without `include` the - // dependency would only be on the dev classpath and the class would - // be missing in a real install. - include implementation("org.xerial:sqlite-jdbc:3.46.1.3") + // SQLite account DB works out of the box. + include "org.xerial:sqlite-jdbc:3.46.1.3" + implementation "org.xerial:sqlite-jdbc:3.46.1.3" } processResources { @@ -41,14 +38,14 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 25 } java { withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } jar { @@ -56,7 +53,7 @@ jar { inputs.property "projectName", projectName from("LICENSE") { - rename { "${it}_$projectName"} + rename { "${it}_$projectName" } } } diff --git a/gradle.properties b/gradle.properties index 033dcf0..dade560 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,18 @@ # Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G +org.gradle.jvmargs=-Xmx2G org.gradle.parallel=true org.gradle.configuration-cache=false -# Fabric Properties +# Fabric Properties (26.x — unobfuscated, Mojang mappings; no Yarn) # check these on https://fabricmc.net/develop -minecraft_version=1.21.11 -yarn_mappings=1.21.11+build.5 -loader_version=0.19.2 -loom_version=1.16-SNAPSHOT +minecraft_version=26.1.2 +loader_version=0.19.3 +loom_version=1.17-SNAPSHOT # Mod Properties mod_version=1.3.5 maven_group=dev.elv1n200 # Dependencies -fabric_api_version=0.141.3+1.21.11 +fabric_api_version=0.154.2+26.1.2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c61a118..5dd3c01 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/dev/elv1n200/sessionlogin/SessionLogin.java b/src/main/java/dev/elv1n200/sessionlogin/SessionLogin.java index 0cbb4f8..ebe2232 100644 --- a/src/main/java/dev/elv1n200/sessionlogin/SessionLogin.java +++ b/src/main/java/dev/elv1n200/sessionlogin/SessionLogin.java @@ -8,8 +8,7 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.session.Session; +import net.minecraft.client.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,10 +19,10 @@ public class SessionLogin implements ModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); /** The real session Minecraft started with. Never modified. */ - public static Session originalSession; + public static User originalSession; /** The session currently exposed to the game (may be swapped). */ - public static Session currentSession; + public static User currentSession; /** When false, the mixin returns the vanilla session untouched. */ public static boolean overrideSession = false; diff --git a/src/main/java/dev/elv1n200/sessionlogin/SessionLoginClient.java b/src/main/java/dev/elv1n200/sessionlogin/SessionLoginClient.java index 7fc5beb..6dba75f 100644 --- a/src/main/java/dev/elv1n200/sessionlogin/SessionLoginClient.java +++ b/src/main/java/dev/elv1n200/sessionlogin/SessionLoginClient.java @@ -1,42 +1,38 @@ package dev.elv1n200.sessionlogin; +import com.mojang.blaze3d.platform.InputConstants; import dev.elv1n200.sessionlogin.command.SessionLoginCommand; import dev.elv1n200.sessionlogin.screen.AccountManagerScreen; import dev.elv1n200.sessionlogin.screen.TamperWarningScreen; import dev.elv1n200.sessionlogin.screen.UnlockScreen; import dev.elv1n200.sessionlogin.util.IntegrityCheck; -import dev.elv1n200.sessionlogin.util.SessionUtils; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; import org.lwjgl.glfw.GLFW; public class SessionLoginClient implements ClientModInitializer { - private KeyBinding openManagerKey; + private KeyMapping openManagerKey; @Override public void onInitializeClient() { SessionLoginCommand.register(); - openManagerKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( + openManagerKey = KeyMappingHelper.registerKeyMapping(new KeyMapping( "key.sessionlogin.manager", - InputUtil.Type.KEYSYM, + InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - KeyBinding.Category.MISC)); + KeyMapping.Category.MISC)); ClientTickEvents.END_CLIENT_TICK.register(new ClientTickEvents.EndTick() { private boolean tamperShown = false; @Override - public void onEndTick(MinecraftClient client) { - while (openManagerKey.wasPressed()) { + public void onEndTick(Minecraft client) { + while (openManagerKey.consumeClick()) { if (SessionLogin.accountStore.isLocked()) { client.setScreen(new UnlockScreen()); } else { @@ -45,26 +41,15 @@ public void onEndTick(MinecraftClient client) { } if (!tamperShown && IntegrityCheck.status() == IntegrityCheck.Status.MISMATCH - && client.currentScreen instanceof net.minecraft.client.gui.screen.TitleScreen) { + && client.screen instanceof net.minecraft.client.gui.screens.TitleScreen) { tamperShown = true; client.setScreen(new TamperWarningScreen()); } } }); - HudRenderCallback.EVENT.register((context, tickCounter) -> { - MinecraftClient mc = MinecraftClient.getInstance(); - if (mc.world == null || mc.currentScreen != null) { - return; - } - if (SessionUtils.isOriginalActive()) { - return; - } - Text label = Text.literal("⚠ Alt: ") - .formatted(Formatting.GOLD) - .append(Text.literal(SessionUtils.getUsername()) - .formatted(Formatting.WHITE)); - context.drawTextWithShadow(mc.textRenderer, label, 4, 4, 0xFFFFFF); - }); + // NOTE: the in-world "⚠ Alt: " HUD overlay is omitted on 26.x — + // Fabric's HUD callback moved to the new render-state pipeline. The + // swapped-account indicator on the multiplayer screen still shows it. } } diff --git a/src/main/java/dev/elv1n200/sessionlogin/command/SessionLoginCommand.java b/src/main/java/dev/elv1n200/sessionlogin/command/SessionLoginCommand.java index c06fcab..a189e2a 100644 --- a/src/main/java/dev/elv1n200/sessionlogin/command/SessionLoginCommand.java +++ b/src/main/java/dev/elv1n200/sessionlogin/command/SessionLoginCommand.java @@ -7,11 +7,11 @@ import dev.elv1n200.sessionlogin.util.Notifier; import dev.elv1n200.sessionlogin.util.SessionUtils; import dev.elv1n200.sessionlogin.util.TokenUtils; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; /** * Client-side {@code /sl} command for quick session control without opening @@ -32,28 +32,28 @@ public static void register() { return builder.buildFuture(); }; - dispatcher.register(ClientCommandManager.literal("sl") + dispatcher.register(ClientCommands.literal("sl") .executes(ctx -> { help(ctx.getSource()); return 1; }) - .then(ClientCommandManager.literal("list").executes(ctx -> { + .then(ClientCommands.literal("list").executes(ctx -> { list(ctx.getSource()); return 1; })) - .then(ClientCommandManager.literal("current").executes(ctx -> { + .then(ClientCommands.literal("current").executes(ctx -> { current(ctx.getSource()); return 1; })) - .then(ClientCommandManager.literal("restore").executes(ctx -> { + .then(ClientCommands.literal("restore").executes(ctx -> { SessionUtils.restoreSession(); send(ctx.getSource(), - Text.literal("Restored original session") - .formatted(Formatting.GREEN)); + Component.literal("Restored original session") + .withStyle(ChatFormatting.GREEN)); return 1; })) - .then(ClientCommandManager.literal("switch").then( - ClientCommandManager.argument( + .then(ClientCommands.literal("switch").then( + ClientCommands.argument( "label", StringArgumentType.greedyString()) .suggests(labelSuggestions) .executes(ctx -> { @@ -65,31 +65,31 @@ public static void register() { } private static void help(FabricClientCommandSource src) { - send(src, Text.literal("/sl list | current | switch