From 46c7bacd0478b9f9752d3b74f66edc84062ef89d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Wed, 30 Sep 2026 22:12:50 +0200 Subject: [PATCH] Build for Minecraft 26.3 Adds 26.3 as a Stonecutter version, the last step of #39. Input: 26.3 replaces GLFW with SDL, which numbers keys (scancodes), modifiers and mouse buttons differently. Saturn keeps GLFW's numbers, which common uses and the config's keybinds store, so saved keybinds stay valid. The new Keys class converts at the boundary: key events, modifiers and mouse buttons coming into Saturn's screens, and key codes going to InputConstants. Its table pairs GLFW's codes with 26.3's InputConstants of the same name. Key names come from the game on 26.3, and version-specific code uses InputConstants' key constants rather than GLFW's. Rendering: Blaze3D's API moved to renderpearl, which Stonecutter replacements cover. PoseStack's quaternion mulPose became rotate, and TextureTarget takes a depth format instead of a flag. 26.3 compiles shaders through SPIR-V and reorders the transforms block, so glass.fsh takes explicit locations and the new order behind defines that GlassRenderer sets, and the unlit cosmetics pipeline declares its color target, which 26.3 requires. OptionsScreen no longer takes whether a world is open. Co-Authored-By: Claude Opus 5.5 --- README.MD | 2 +- VERSION_GUIDE.md | 8 +- settings.gradle.kts | 2 +- .../impl/cosmetics/CloakFeatureRenderer.java | 6 +- .../impl/cosmetics/obj/ObjModel.java | 19 +- .../impl/cosmetics/utils/ShaderUtils.java | 5 + .../impl/mixins/MinecraftClientMixin.java | 5 +- .../impl/provider/GLFWProviderImpl.java | 13 ++ .../org/saturnclient/impl/provider/Keys.java | 189 ++++++++++++++++++ .../saturnclient/impl/ui/GlassRenderer.java | 8 +- .../impl/ui/SaturnScreenFabric.java | 11 +- .../saturnclient/event/KeyInputHandler.java | 11 +- .../saturnclient/shaders/core/glass.fsh | 21 +- stonecutter.gradle.kts | 4 + versions/26.3/gradle.properties | 17 ++ 15 files changed, 299 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/saturnclient/impl/provider/Keys.java create mode 100644 versions/26.3/gradle.properties diff --git a/README.MD b/README.MD index 725631c..9e6f40d 100644 --- a/README.MD +++ b/README.MD @@ -18,7 +18,7 @@ Saturn Client is a free, open-source Minecraft client designed to enhance the gameplay experience while staying lightweight and customizable. Our goal is to build a clean, optimized client that the community can contribute to and improve together. -Saturn runs on Fabric and supports **Minecraft 1.21.4 to 1.21.11, 26.1 and 26.2**, with one build per version (the 26.1 build also runs on 26.1.1 and 26.1.2). If something doesn't work on your version, please open an issue. +Saturn runs on Fabric and supports **Minecraft 1.21.4 to 1.21.11 and 26.1 to 26.3**, with one build per version (the 26.1 build also runs on 26.1.1 and 26.1.2). If something doesn't work on your version, please open an issue. ## Features diff --git a/VERSION_GUIDE.md b/VERSION_GUIDE.md index e2d0624..8cec624 100644 --- a/VERSION_GUIDE.md +++ b/VERSION_GUIDE.md @@ -4,7 +4,7 @@ How Saturn Client supports several Minecraft versions, and how to change or add ## Layout -Every supported Minecraft version (1.21.4 to 1.21.11, 26.1 and 26.2) builds from one copy of the version-specific code with [Stonecutter](https://stonecutter.kikugie.dev/): +Every supported Minecraft version (1.21.4 to 1.21.11, and 26.1 to 26.3) builds from one copy of the version-specific code with [Stonecutter](https://stonecutter.kikugie.dev/): - `common/`: all version-independent code (mods, UI, cosmetics, the server client). It has no Minecraft dependency and reaches the game only through the interfaces in `org.saturnclient.common`. - `src/`: the version-specific code (providers, refs, mixins and the three mixin configs), one copy for every version. Where Minecraft's API differs between versions, the code goes behind version comments (see below). @@ -18,7 +18,11 @@ Minecraft is obfuscated up to 1.21.11 and ships with Mojang's names from 26.1. T Every version is built with Mojang's official names (`loom.officialMojangMappings()`), the names Minecraft itself ships from 26.1 on. Yarn isn't used any more: 1.21.11 has the last Yarn release. -Mojang renames things between versions. `src/` uses the active version's (1.21.11's) names, and `stonecutter.gradle.kts` lists replacements that swap in each version's name when Stonecutter processes it: for example `Identifier`, which was `ResourceLocation` before 1.21.11, `AvatarRenderState`, which was `PlayerRenderState` before 1.21.9, and `GuiGraphics`, which is `GuiGraphicsExtractor` from 26.1. Add a replacement there when a rename touches many lines. From 26.2 the open screen and overlay live on `Gui` rather than `Minecraft`, so code goes through `impl.ui.Screens` for them. A class that only moved package needs just a version comment on its import, and a renamed method a version comment where it's called. +Mojang renames things between versions. `src/` uses the active version's (1.21.11's) names, and `stonecutter.gradle.kts` lists replacements that swap in each version's name when Stonecutter processes it: for example `Identifier`, which was `ResourceLocation` before 1.21.11, `AvatarRenderState`, which was `PlayerRenderState` before 1.21.9, and `GuiGraphics`, which is `GuiGraphicsExtractor` from 26.1. Add a replacement there when a rename touches many lines, and only for a name that appears nowhere else in `src/`: replacements work both ways, so the new name is also turned back into the old one for older versions (a `mulPose`/`rotate` replacement would rename `MatrixStackRef.rotate` too). From 26.2 the open screen and overlay live on `Gui` rather than `Minecraft`, so code goes through `impl.ui.Screens` for them. + +From 26.3 Minecraft uses SDL instead of GLFW, with SDL's numbers for keys (scancodes), modifiers and mouse buttons. Saturn keeps GLFW's numbers, which `common` uses and the config's keybinds store, and `impl.provider.Keys` converts at the boundary: key events and mouse buttons coming in, and key codes going to the game. Use `InputConstants`' key constants rather than GLFW's in version-specific code. + +26.3 also compiles every shader through SPIR-V, so shader inputs and outputs need an explicit `layout(location = …)`. Saturn's `glass.fsh` is shared by every version from 1.21.6 and switches its layout with the defines `GlassRenderer` sets, as it already did for `HAS_LINE_WIDTH`. A class that only moved package needs just a version comment on its import, and a renamed method a version comment where it's called. Released 1.21.x jars run on intermediary names (`method_1234`), not Mojang's, and Loom renames everything that refers to Minecraft when it builds them. So a mixin can't implement one of `common`'s Ref interfaces by relying on a vanilla method that happens to have the same name: the vanilla method is renamed in the jar, and the interface method is left without an implementation (`AbstractMethodError`). Shadow the vanilla method and implement the Ref method explicitly, as `WindowMixin` does. For the same reason, Ref methods mustn't share a name and parameters with a method of the class they're mixed into, or the mixin replaces the vanilla method in development. diff --git a/settings.gradle.kts b/settings.gradle.kts index 2166843..c7ace8b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,7 +24,7 @@ include("common") // versions//gradle.properties holds its Minecraft, Fabric Loader and Fabric API versions. val stonecutterVersions = listOf( "1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10", "1.21.11", - "26.1", "26.2", + "26.1", "26.2", "26.3", ) stonecutter { diff --git a/src/main/java/org/saturnclient/impl/cosmetics/CloakFeatureRenderer.java b/src/main/java/org/saturnclient/impl/cosmetics/CloakFeatureRenderer.java index 59d6f5e..3ef1368 100644 --- a/src/main/java/org/saturnclient/impl/cosmetics/CloakFeatureRenderer.java +++ b/src/main/java/org/saturnclient/impl/cosmetics/CloakFeatureRenderer.java @@ -435,7 +435,11 @@ public class CloakFeatureRenderer extends RenderLayer=26.3 { + /*matrices.rotate(rotation); + *///?} else + matrices.mulPose(rotation); } // Shift array left and insert new value at the start diff --git a/src/main/java/org/saturnclient/impl/cosmetics/obj/ObjModel.java b/src/main/java/org/saturnclient/impl/cosmetics/obj/ObjModel.java index f290e4c..2d611c4 100644 --- a/src/main/java/org/saturnclient/impl/cosmetics/obj/ObjModel.java +++ b/src/main/java/org/saturnclient/impl/cosmetics/obj/ObjModel.java @@ -18,6 +18,7 @@ import net.minecraft.client.renderer.SubmitNodeCollector; //?} else //import net.minecraft.client.renderer.MultiBufferSource; import com.mojang.blaze3d.vertex.PoseStack; +import org.joml.Quaternionf; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.resources.Identifier; @@ -89,21 +90,29 @@ public class ObjModel { int light, int overlay) { matrices.pushPose(); - matrices.mulPose(com.mojang.math.Axis.XP.rotationDegrees(180.0f)); - matrices.mulPose(com.mojang.math.Axis.YP.rotationDegrees(180.0f)); + rotate(matrices, com.mojang.math.Axis.XP.rotationDegrees(180.0f)); + rotate(matrices, com.mojang.math.Axis.YP.rotationDegrees(180.0f)); if (this.config != null) { matrices.translate(config.transform.x, config.transform.y, config.transform.z); matrices.scale(config.scale.x, config.scale.y, config.scale.z); - matrices.mulPose(com.mojang.math.Axis.XP.rotationDegrees(config.rotation.x)); - matrices.mulPose(com.mojang.math.Axis.YP.rotationDegrees(config.rotation.y)); - matrices.mulPose(com.mojang.math.Axis.ZP.rotationDegrees(config.rotation.z)); + rotate(matrices, com.mojang.math.Axis.XP.rotationDegrees(config.rotation.x)); + rotate(matrices, com.mojang.math.Axis.YP.rotationDegrees(config.rotation.y)); + rotate(matrices, com.mojang.math.Axis.ZP.rotationDegrees(config.rotation.z)); } ObjRenderer.renderObj(this.obj, mtlMap, matrices, output, light, overlay); matrices.popPose(); } + + // 26.3 renamed PoseStack's quaternion mulPose to rotate. + private static void rotate(PoseStack matrices, Quaternionf rotation) { + //? if >=26.3 { + /*matrices.rotate(rotation); + *///?} else + matrices.mulPose(rotation); + } } diff --git a/src/main/java/org/saturnclient/impl/cosmetics/utils/ShaderUtils.java b/src/main/java/org/saturnclient/impl/cosmetics/utils/ShaderUtils.java index 40bab50..4079666 100644 --- a/src/main/java/org/saturnclient/impl/cosmetics/utils/ShaderUtils.java +++ b/src/main/java/org/saturnclient/impl/cosmetics/utils/ShaderUtils.java @@ -26,6 +26,8 @@ import net.minecraft.client.renderer.blockentity.AbstractEndPortalRenderer; import net.minecraft.client.renderer.blockentity.TheEndPortalRenderer; *///?} import net.minecraft.resources.Identifier; +//? if >=26.3 +//import com.mojang.renderpearl.api.pipeline.ColorTargetState; //? if >=26.1 { /*import java.util.HashMap; import java.util.Map; @@ -103,6 +105,9 @@ public class ShaderUtils { .withShaderDefine("NO_CARDINAL_LIGHTING") .withShaderDefine("NO_OVERLAY") .withCull(false) + // From 26.3 the snippet leaves the color target to each pipeline. + //? if >=26.3 + //.withColorTargetState(ColorTargetState.DEFAULT) .build()); private static final Map UNLIT_CUTOUT = new HashMap<>(); *///?} diff --git a/src/main/java/org/saturnclient/impl/mixins/MinecraftClientMixin.java b/src/main/java/org/saturnclient/impl/mixins/MinecraftClientMixin.java index 1d9017d..5225c90 100644 --- a/src/main/java/org/saturnclient/impl/mixins/MinecraftClientMixin.java +++ b/src/main/java/org/saturnclient/impl/mixins/MinecraftClientMixin.java @@ -88,7 +88,10 @@ public abstract class MinecraftClientMixin implements MinecraftClientRef { break; case Options: - //? if >=26.1 { + // Only 26.1 and 26.2 take whether a world is open. + //? if >=26.3 { + /*Screens.set(new OptionsScreen(exitTarget, this.options)); + *///?} else if >=26.1 { /*Screens.set(new OptionsScreen(exitTarget, this.options, ((Minecraft) (Object) this).level != null)); *///?} else Screens.set(new OptionsScreen(exitTarget, this.options)); diff --git a/src/main/java/org/saturnclient/impl/provider/GLFWProviderImpl.java b/src/main/java/org/saturnclient/impl/provider/GLFWProviderImpl.java index a2756ed..5be0f5a 100644 --- a/src/main/java/org/saturnclient/impl/provider/GLFWProviderImpl.java +++ b/src/main/java/org/saturnclient/impl/provider/GLFWProviderImpl.java @@ -1,5 +1,9 @@ package org.saturnclient.impl.provider; +// 26.3 uses SDL, not GLFW; Keys converts Saturn's GLFW key codes to its own. +//? if >=26.3 { +/*import com.mojang.blaze3d.platform.InputConstants; +*///?} else import org.lwjgl.glfw.GLFW; import org.saturnclient.common.provider.GLFWProvider; import org.saturnclient.impl.ui.Screens; @@ -8,16 +12,25 @@ import org.saturnclient.saturnclient.SaturnClient; public class GLFWProviderImpl implements GLFWProvider { @Override public boolean isKeyPressed(int key) { + //? if >=26.3 { + /*int gameKey = Keys.toGame(key); + return gameKey >= 0 && InputConstants.isKeyDown(gameKey) && Screens.current() == null; + *///?} else { //? if >=1.21.9 { long window = SaturnClient.client.getWindow().handle(); //?} else //long window = SaturnClient.client.getWindow().getWindow(); return GLFW.glfwGetKey(window, key) == GLFW.GLFW_PRESS && Screens.current() == null; + //?} } @Override public String getKeyName(int key) { + //? if >=26.3 { + /*int gameKey = Keys.toGame(key); + return gameKey < 0 ? null : InputConstants.Type.KEYBOARD.getOrCreate(gameKey).getDisplayName().getString(); + *///?} else return GLFW.glfwGetKeyName(key, GLFW.glfwGetKeyScancode(key)); } } diff --git a/src/main/java/org/saturnclient/impl/provider/Keys.java b/src/main/java/org/saturnclient/impl/provider/Keys.java new file mode 100644 index 0000000..f04ff88 --- /dev/null +++ b/src/main/java/org/saturnclient/impl/provider/Keys.java @@ -0,0 +1,189 @@ +package org.saturnclient.impl.provider; + +//? if >=26.3 { +/*import com.mojang.blaze3d.platform.InputConstants; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import org.saturnclient.common.provider.GLFWProvider; +*///?} + +/** + * Saturn's key codes are GLFW's, which the config's keybinds store. From 26.3 Minecraft uses SDL, + * whose keys (scancodes), modifiers and mouse buttons are numbered differently, so these convert + * between the two there. Before 26.3 Minecraft's numbers are GLFW's and pass through. + */ +public final class Keys { + private Keys() { + } + + //? if >=26.3 { + /*private static final Int2IntOpenHashMap TO_GAME = new Int2IntOpenHashMap(); + private static final Int2IntOpenHashMap TO_SATURN = new Int2IntOpenHashMap(); + + private static void key(int glfw, int game) { + TO_GAME.put(glfw, game); + TO_SATURN.put(game, glfw); + } + + // GLFW's key codes, and the same keys' constants in 26.3 + static { + TO_GAME.defaultReturnValue(-1); + TO_SATURN.defaultReturnValue(-1); + key(32, InputConstants.KEY_SPACE); + key(39, InputConstants.KEY_APOSTROPHE); + key(44, InputConstants.KEY_COMMA); + key(45, InputConstants.KEY_MINUS); + key(46, InputConstants.KEY_PERIOD); + key(47, InputConstants.KEY_SLASH); + key(48, InputConstants.KEY_0); + key(49, InputConstants.KEY_1); + key(50, InputConstants.KEY_2); + key(51, InputConstants.KEY_3); + key(52, InputConstants.KEY_4); + key(53, InputConstants.KEY_5); + key(54, InputConstants.KEY_6); + key(55, InputConstants.KEY_7); + key(56, InputConstants.KEY_8); + key(57, InputConstants.KEY_9); + key(59, InputConstants.KEY_SEMICOLON); + key(61, InputConstants.KEY_EQUALS); + key(65, InputConstants.KEY_A); + key(66, InputConstants.KEY_B); + key(67, InputConstants.KEY_C); + key(68, InputConstants.KEY_D); + key(69, InputConstants.KEY_E); + key(70, InputConstants.KEY_F); + key(71, InputConstants.KEY_G); + key(72, InputConstants.KEY_H); + key(73, InputConstants.KEY_I); + key(74, InputConstants.KEY_J); + key(75, InputConstants.KEY_K); + key(76, InputConstants.KEY_L); + key(77, InputConstants.KEY_M); + key(78, InputConstants.KEY_N); + key(79, InputConstants.KEY_O); + key(80, InputConstants.KEY_P); + key(81, InputConstants.KEY_Q); + key(82, InputConstants.KEY_R); + key(83, InputConstants.KEY_S); + key(84, InputConstants.KEY_T); + key(85, InputConstants.KEY_U); + key(86, InputConstants.KEY_V); + key(87, InputConstants.KEY_W); + key(88, InputConstants.KEY_X); + key(89, InputConstants.KEY_Y); + key(90, InputConstants.KEY_Z); + key(91, InputConstants.KEY_LBRACKET); + key(92, InputConstants.KEY_BACKSLASH); + key(93, InputConstants.KEY_RBRACKET); + key(96, InputConstants.KEY_GRAVE); + key(256, InputConstants.KEY_ESCAPE); + key(257, InputConstants.KEY_RETURN); + key(258, InputConstants.KEY_TAB); + key(259, InputConstants.KEY_BACKSPACE); + key(260, InputConstants.KEY_INSERT); + key(261, InputConstants.KEY_DELETE); + key(262, InputConstants.KEY_RIGHT); + key(263, InputConstants.KEY_LEFT); + key(264, InputConstants.KEY_DOWN); + key(265, InputConstants.KEY_UP); + key(266, InputConstants.KEY_PAGEUP); + key(267, InputConstants.KEY_PAGEDOWN); + key(268, InputConstants.KEY_HOME); + key(269, InputConstants.KEY_END); + key(280, InputConstants.KEY_CAPSLOCK); + key(281, InputConstants.KEY_SCROLLLOCK); + key(282, InputConstants.KEY_NUMLOCK); + key(283, InputConstants.KEY_PRINTSCREEN); + key(284, InputConstants.KEY_PAUSE); + key(290, InputConstants.KEY_F1); + key(291, InputConstants.KEY_F2); + key(292, InputConstants.KEY_F3); + key(293, InputConstants.KEY_F4); + key(294, InputConstants.KEY_F5); + key(295, InputConstants.KEY_F6); + key(296, InputConstants.KEY_F7); + key(297, InputConstants.KEY_F8); + key(298, InputConstants.KEY_F9); + key(299, InputConstants.KEY_F10); + key(300, InputConstants.KEY_F11); + key(301, InputConstants.KEY_F12); + key(302, InputConstants.KEY_F13); + key(303, InputConstants.KEY_F14); + key(304, InputConstants.KEY_F15); + key(305, InputConstants.KEY_F16); + key(306, InputConstants.KEY_F17); + key(307, InputConstants.KEY_F18); + key(308, InputConstants.KEY_F19); + key(309, InputConstants.KEY_F20); + key(310, InputConstants.KEY_F21); + key(311, InputConstants.KEY_F22); + key(312, InputConstants.KEY_F23); + key(313, InputConstants.KEY_F24); + key(320, InputConstants.KEY_NUMPAD0); + key(321, InputConstants.KEY_NUMPAD1); + key(322, InputConstants.KEY_NUMPAD2); + key(323, InputConstants.KEY_NUMPAD3); + key(324, InputConstants.KEY_NUMPAD4); + key(325, InputConstants.KEY_NUMPAD5); + key(326, InputConstants.KEY_NUMPAD6); + key(327, InputConstants.KEY_NUMPAD7); + key(328, InputConstants.KEY_NUMPAD8); + key(329, InputConstants.KEY_NUMPAD9); + key(330, InputConstants.KEY_NUMPADCOMMA); + key(332, InputConstants.KEY_MULTIPLY); + key(334, InputConstants.KEY_ADD); + key(335, InputConstants.KEY_NUMPADENTER); + key(336, InputConstants.KEY_NUMPADEQUALS); + key(340, InputConstants.KEY_LSHIFT); + key(341, InputConstants.KEY_LCONTROL); + key(342, InputConstants.KEY_LALT); + key(343, InputConstants.KEY_LGUI); + key(344, InputConstants.KEY_RSHIFT); + key(345, InputConstants.KEY_RCONTROL); + key(346, InputConstants.KEY_RALT); + key(347, InputConstants.KEY_RGUI); + } + *///?} + + /** A Saturn (GLFW) key code as the game's, or -1 */ + public static int toGame(int key) { + //? if >=26.3 { + /*return TO_GAME.get(key); + *///?} else + return key; + } + + /** A key code from the game as Saturn's (GLFW), or -1 */ + public static int toSaturn(int key) { + //? if >=26.3 { + /*return TO_SATURN.get(key); + *///?} else + return key; + } + + /** The game's modifier flags as GLFW's */ + public static int modifiersToSaturn(int modifiers) { + //? if >=26.3 { + /*int glfw = 0; + if ((modifiers & InputConstants.MOD_SHIFT) != 0) glfw |= GLFWProvider.GLFW_MOD_SHIFT; + if ((modifiers & InputConstants.MOD_CONTROL) != 0) glfw |= GLFWProvider.GLFW_MOD_CONTROL; + if ((modifiers & InputConstants.MOD_ALT) != 0) glfw |= GLFWProvider.GLFW_MOD_ALT; + if ((modifiers & InputConstants.MOD_SUPER) != 0) glfw |= GLFWProvider.GLFW_MOD_SUPER; + if ((modifiers & InputConstants.MOD_CAPS_LOCK) != 0) glfw |= GLFWProvider.GLFW_MOD_CAPS_LOCK; + if ((modifiers & InputConstants.MOD_NUM_LOCK) != 0) glfw |= GLFWProvider.GLFW_MOD_NUM_LOCK; + return glfw; + *///?} else + return modifiers; + } + + /** A mouse button from the game as GLFW's (left 0, right 1, middle 2, then the side buttons) */ + public static int mouseButtonToSaturn(int button) { + //? if >=26.3 { + /*if (button == InputConstants.MOUSE_BUTTON_LEFT) return 0; + if (button == InputConstants.MOUSE_BUTTON_RIGHT) return 1; + if (button == InputConstants.MOUSE_BUTTON_MIDDLE) return 2; + return button - 1; + *///?} else + return button; + } +} diff --git a/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java b/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java index d1264fd..0d64b66 100644 --- a/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java +++ b/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java @@ -66,6 +66,9 @@ public final class GlassRenderer { // The transforms block ends with LineWidth before 1.21.11 (see glass.fsh). //? if <1.21.11 //.withShaderDefine("HAS_LINE_WIDTH") + // 26.3 compiles through SPIR-V and moved TextureMat up the transforms block. + //? if >=26.3 + //.withShaderDefine("EXPLICIT_LOCATIONS").withShaderDefine("TEXTURE_MAT_SECOND") .build(); private static final Identifier BLUR = Identifier.withDefaultNamespace("post_effect/blur.json"); @@ -112,7 +115,10 @@ public final class GlassRenderer { TextureTarget backdrop = BACKDROPS.get(blur); if (backdrop == null) { - //? if >=26.2 { + // From 26.3 the depth format picks the depth buffer (none here); 26.2 takes a flag. + //? if >=26.3 { + /*backdrop = new TextureTarget("Saturn glass " + blur, width, height, GpuFormat.RGBA8_UNORM, null); + *///?} else if >=26.2 { /*backdrop = new TextureTarget("Saturn glass " + blur, width, height, false, GpuFormat.RGBA8_UNORM); *///?} else backdrop = new TextureTarget("Saturn glass " + blur, width, height, false); diff --git a/src/main/java/org/saturnclient/impl/ui/SaturnScreenFabric.java b/src/main/java/org/saturnclient/impl/ui/SaturnScreenFabric.java index 68d15a7..82edb5d 100644 --- a/src/main/java/org/saturnclient/impl/ui/SaturnScreenFabric.java +++ b/src/main/java/org/saturnclient/impl/ui/SaturnScreenFabric.java @@ -4,6 +4,7 @@ import java.time.Duration; import java.time.Instant; import org.saturnclient.config.Config; +import org.saturnclient.impl.provider.Keys; import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.SaturnScreen; import org.saturnclient.ui.SaturnScreen.ScreenProvider; @@ -176,7 +177,7 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider { //? if >=1.21.9 { @Override public boolean mouseClicked(MouseButtonEvent click, boolean doubled) { - if (screen.mouseClicked(click.x(), click.y(), click.button())) { + if (screen.mouseClicked(click.x(), click.y(), Keys.mouseButtonToSaturn(click.button()))) { return true; } @@ -186,7 +187,7 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider { @Override public boolean mouseDragged(MouseButtonEvent click, double offsetX, double offsetY) { // offsetX and offsetY are the drag deltas, as mouseDragged's deltaX and deltaY were before 1.21.9. - if (screen.mouseDragged(click.x(), click.y(), click.button(), offsetX, offsetY)) { + if (screen.mouseDragged(click.x(), click.y(), Keys.mouseButtonToSaturn(click.button()), offsetX, offsetY)) { return true; } @@ -195,7 +196,7 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider { @Override public boolean mouseReleased(MouseButtonEvent click) { - if (screen.mouseReleased(click.x(), click.y(), click.button())) { + if (screen.mouseReleased(click.x(), click.y(), Keys.mouseButtonToSaturn(click.button()))) { return true; } @@ -238,6 +239,10 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider { //? if >=1.21.9 { @Override public boolean keyPressed(KeyEvent input) { + // 26.3's key() is SDL's scancode; Saturn's key codes are GLFW's (see Keys). + //? if >=26.3 { + /*if (screen.keyPressed(Keys.toSaturn(input.key()), input.key(), Keys.modifiersToSaturn(input.modifiers()))) { + *///?} else if (screen.keyPressed(input.input(), input.scancode(), input.modifiers())) { return true; } diff --git a/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java b/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java index d304670..1098b15 100644 --- a/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java +++ b/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java @@ -20,7 +20,6 @@ import org.saturnclient.impl.ui.Screens; import org.saturnclient.ui.screens.EmoteWheel; import org.saturnclient.ui.screens.ShiftMenu; -import org.lwjgl.glfw.GLFW; /** * Handles keyboard input events for the Saturn Client. @@ -32,7 +31,7 @@ public class KeyInputHandler { //?} else //private static final String KEY_CATEGORY = "key.category.saturnclient"; private static final String MAIN_MENU_KEY_ID = "key.saturnclient.main_menu"; - private static final int DEFAULT_MENU_KEY = GLFW.GLFW_KEY_RIGHT_SHIFT; + private static final int DEFAULT_MENU_KEY = InputConstants.KEY_RSHIFT; private static KeyMapping mainMenuKeyBinding; public static void register() { @@ -66,10 +65,12 @@ public class KeyInputHandler { // from the screen's own key handling would reopen it on the next tick, since the key is // still down and no screen is open by then. if (Config.openEmoteWheel.wasKeyPressed() - //? if >=1.21.9 { - && !InputConstants.isKeyDown(client.getWindow(), GLFW.GLFW_KEY_F3)) { + //? if >=26.3 { + /*&& !InputConstants.isKeyDown(InputConstants.KEY_F3)) { + *///?} else if >=1.21.9 { + && !InputConstants.isKeyDown(client.getWindow(), InputConstants.KEY_F3)) { //?} else - //&& !InputConstants.isKeyDown(client.getWindow().getWindow(), GLFW.GLFW_KEY_F3)) { + //&& !InputConstants.isKeyDown(client.getWindow().getWindow(), InputConstants.KEY_F3)) { if (Screens.current() == null) { Providers.saturn.getClient().setScreen(new EmoteWheel()); } else if (Screens.current() instanceof SaturnScreenFabric saturnScreen diff --git a/src/main/resources/assets/saturnclient/shaders/core/glass.fsh b/src/main/resources/assets/saturnclient/shaders/core/glass.fsh index e58609c..4d5a0b3 100644 --- a/src/main/resources/assets/saturnclient/shaders/core/glass.fsh +++ b/src/main/resources/assets/saturnclient/shaders/core/glass.fsh @@ -1,16 +1,26 @@ #version 330 +// 26.3 compiles shaders through SPIR-V, which needs every input and output's location. +#ifdef EXPLICIT_LOCATIONS +#extension GL_ARB_separate_shader_objects : require +#endif // Saturn's glass: the blurred game behind the screen, cut to a panel's shape. For 1.21.6 and // later; glass_pre_1_21_6.fsh (with glass.json, the program 1.21.4 loads) is for older versions. // Vanilla's transforms, laid out as the version has them: 1.21.6 to 1.21.10 end with LineWidth, which -// 1.21.11 dropped (GlassRenderer defines HAS_LINE_WIDTH there). Not imported: the include only exists -// from 1.21.6, and 1.21.4 and 1.21.5 still read every shader's imports while loading resources. +// 1.21.11 dropped (GlassRenderer defines HAS_LINE_WIDTH there), and 26.3 moved TextureMat up +// (TEXTURE_MAT_SECOND). Not imported: the include only exists from 1.21.6, and 1.21.4 and 1.21.5 still +// read every shader's imports while loading resources. layout(std140) uniform DynamicTransforms { mat4 ModelViewMat; +#ifdef TEXTURE_MAT_SECOND + mat4 TextureMat; +#endif vec4 ColorModulator; vec3 ModelOffset; +#ifndef TEXTURE_MAT_SECOND mat4 TextureMat; +#endif #ifdef HAS_LINE_WIDTH float LineWidth; #endif @@ -21,10 +31,17 @@ uniform sampler2D Sampler0; // The game behind the screen, blurred, the size of the framebuffer uniform sampler2D Sampler1; +#ifdef EXPLICIT_LOCATIONS +layout(location = 0) in vec2 texCoord0; +layout(location = 1) in vec4 vertexColor; + +layout(location = 0) out vec4 fragColor; +#else in vec2 texCoord0; in vec4 vertexColor; out vec4 fragColor; +#endif void main() { float mask = texture(Sampler0, texCoord0).a * vertexColor.a; diff --git a/stonecutter.gradle.kts b/stonecutter.gradle.kts index f6092e1..2235272 100644 --- a/stonecutter.gradle.kts +++ b/stonecutter.gradle.kts @@ -20,6 +20,10 @@ stonecutter parameters { Triple("26.1", "submitText", "addText"), Triple("26.1", "submitItem", "addItem"), Triple("26.1", "submitPicturesInPictureState", "addPicturesInPictureState"), + // 26.3 moves Blaze3D's API to renderpearl + Triple("26.3", "com.mojang.blaze3d.GpuFormat", "com.mojang.renderpearl.api.GpuFormat"), + Triple("26.3", "com.mojang.blaze3d.pipeline.RenderPipeline", "com.mojang.renderpearl.api.pipeline.RenderPipeline"), + Triple("26.3", "com.mojang.blaze3d.textures", "com.mojang.renderpearl.api.textures"), )) { replacements.regex(eval(current.version, ">=$since")) { replace("\\b${Regex.escape(old)}\\b", new, "\\b${Regex.escape(new)}\\b", old) diff --git a/versions/26.3/gradle.properties b/versions/26.3/gradle.properties new file mode 100644 index 0000000..91f10fd --- /dev/null +++ b/versions/26.3/gradle.properties @@ -0,0 +1,17 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +org.gradle.parallel=true + +# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349 +org.gradle.configuration-cache=false + +# Fabric Properties +# check these on https://fabricmc.net/develop +minecraft_version=26.3 +loader_version=0.19.5 + +fabric_api_version=0.161.0+26.3 + +# Mod Properties +maven_group=org.saturnclient +archives_base_name=saturn-client