diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0f922fa956b..42b965e1970 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,9 +1,9 @@ [versions] # Fabric (https://fabricmc.net/develop) jdk = "25" -minecraft = "26.3-pre-1" -fabric-loader = "0.19.3" -fabric-api = "0.159.1+26.3" +minecraft = "26.3" +fabric-loader = "0.19.5" +fabric-api = "0.161.0+26.3" # Plugins # Loom (https://github.com/FabricMC/fabric-loom) @@ -13,13 +13,13 @@ loom = "1.17-SNAPSHOT" # Baritone (https://github.com/MeteorDevelopment/baritone) baritone = "26.1-SNAPSHOT" # Sodium (https://github.com/CaffeineMC/sodium-fabric) -sodium = "mc26.2-0.9.1-fabric" +sodium = "mc26.3-0.9.2-fabric" # Lithium (https://github.com/CaffeineMC/lithium-fabric) -lithium = "mc26.2-0.25.2-fabric" +lithium = "mc26.3-0.26.1-fabric" # Iris (https://github.com/IrisShaders/Iris) -iris = "1.11.2+26.2-fabric" +iris = "1.11.6+26.3-fabric" # ModMenu (https://github.com/TerraformersMC/ModMenu) -modmenu = "20.0.1" +modmenu = "21.0.0" # Orbit (https://github.com/MeteorDevelopment/orbit) orbit = "0.2.4" # Starscript (https://github.com/MeteorDevelopment/starscript) diff --git a/src/main/java/meteordevelopment/meteorclient/commands/commands/NotebotCommand.java b/src/main/java/meteordevelopment/meteorclient/commands/commands/NotebotCommand.java index 6f3bb0350b3..cc13cedf45f 100644 --- a/src/main/java/meteordevelopment/meteorclient/commands/commands/NotebotCommand.java +++ b/src/main/java/meteordevelopment/meteorclient/commands/commands/NotebotCommand.java @@ -5,6 +5,7 @@ package meteordevelopment.meteorclient.commands.commands; +import com.mojang.blaze3d.Blaze3D; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; @@ -24,11 +25,11 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundSoundPacket; import net.minecraft.sounds.SoundEvent; -import net.minecraft.util.Util; import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import java.io.FileWriter; import java.io.IOException; +import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -48,7 +49,7 @@ public NotebotCommand() { @Override public void build(LiteralArgumentBuilder builder) { builder.then(literal("help").executes(_ -> { - Util.getPlatform().openUri("https://github.com/MeteorDevelopment/meteor-client/wiki/Notebot-Guide"); + Blaze3D.openUri(URI.create("https://github.com/MeteorDevelopment/meteor-client/wiki/Notebot-Guide")); return SINGLE_SUCCESS; })); diff --git a/src/main/java/meteordevelopment/meteorclient/gui/screens/CommitsScreen.java b/src/main/java/meteordevelopment/meteorclient/gui/screens/CommitsScreen.java index b045d95641a..c0c6243a6ca 100644 --- a/src/main/java/meteordevelopment/meteorclient/gui/screens/CommitsScreen.java +++ b/src/main/java/meteordevelopment/meteorclient/gui/screens/CommitsScreen.java @@ -5,6 +5,7 @@ package meteordevelopment.meteorclient.gui.screens; +import com.mojang.blaze3d.Blaze3D; import meteordevelopment.meteorclient.addons.GithubRepo; import meteordevelopment.meteorclient.addons.MeteorAddon; import meteordevelopment.meteorclient.gui.GuiTheme; @@ -13,8 +14,8 @@ import meteordevelopment.meteorclient.gui.widgets.containers.WTable; import meteordevelopment.meteorclient.utils.network.Http; import meteordevelopment.meteorclient.utils.network.MeteorExecutor; -import net.minecraft.util.Util; +import java.net.URI; import java.net.http.HttpResponse; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; @@ -66,11 +67,11 @@ private void populateHeader(String headerMessage) { l.add(theme.label(headerMessage)).expandX(); String website = addon.getWebsite(); - if (website != null) l.add(theme.button("Website")).widget().action = () -> Util.getPlatform().openUri(website); + if (website != null) l.add(theme.button("Website")).widget().action = () -> Blaze3D.openUri(URI.create(website)); l.add(theme.button("GitHub")).widget().action = () -> { GithubRepo repo = addon.getRepo(); - Util.getPlatform().openUri(String.format("https://github.com/%s/tree/%s", repo.getOwnerName(), repo.branch())); + Blaze3D.openUri(URI.create(String.format("https://github.com/%s/tree/%s", repo.getOwnerName(), repo.branch()))); }; } @@ -91,7 +92,7 @@ private void populateError() { l.add(theme.label("Consider using an authentication token: ")).expandX(); l.add(theme.button("Authorization Guide")).widget().action = () -> { - Util.getPlatform().openUri("https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens"); + Blaze3D.openUri(URI.create("https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens")); }; } @@ -115,7 +116,7 @@ private void populateCommits() { String date = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(commit.commit.committer.date)); t.add(theme.label(date)).top().right().widget().color = theme.textSecondaryColor(); - t.add(theme.label(getMessage(commit))).widget().action = () -> Util.getPlatform().openUri(String.format("https://github.com/%s/commit/%s", addon.getRepo().getOwnerName(), commit.sha)); + t.add(theme.label(getMessage(commit))).widget().action = () -> Blaze3D.openUri(URI.create(String.format("https://github.com/%s/commit/%s", addon.getRepo().getOwnerName(), commit.sha))); t.row(); } } diff --git a/src/main/java/meteordevelopment/meteorclient/gui/widgets/input/WTextBox.java b/src/main/java/meteordevelopment/meteorclient/gui/widgets/input/WTextBox.java index 0f10db85ffb..91a674d6980 100644 --- a/src/main/java/meteordevelopment/meteorclient/gui/widgets/input/WTextBox.java +++ b/src/main/java/meteordevelopment/meteorclient/gui/widgets/input/WTextBox.java @@ -716,6 +716,9 @@ public void setFocused(boolean focused) { this.focused = focused; + // SDL only delivers typed characters while text input is enabled + mc.textInputManager().onTextInputFocusChange(this, focused); + resetSelection(); if (wasJustFocused) onCursorChanged(); diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ClientLevelMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ClientLevelMixin.java index 9f0135be996..f779a7e8374 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ClientLevelMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ClientLevelMixin.java @@ -64,8 +64,8 @@ private void onAddDestroyBlockEffect(BlockPos pos, BlockState blockState, Callba if (Modules.get().get(NoRender.class).noParticle(ParticleTypes.BLOCK)) ci.cancel(); } - @Inject(method = "addBreakingBlockEffect", at = @At("HEAD"), cancellable = true) - private void onAddBlockBreakingParticles(BlockPos pos, Direction direction, CallbackInfo ci) { + @Inject(method = "addBreakingParticles", at = @At("HEAD"), cancellable = true) + private void onAddBlockBreakingParticles(BlockPos pos, Direction direction, BlockState state, CallbackInfo ci) { if (Modules.get().get(NoRender.class).noParticle(ParticleTypes.BLOCK)) ci.cancel(); } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/GuiGraphicsExtractorMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/GuiGraphicsExtractorMixin.java index d5c7469ec0c..f2c8c76eec9 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/GuiGraphicsExtractorMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/GuiGraphicsExtractorMixin.java @@ -8,18 +8,11 @@ import com.llamalad7.mixinextras.injector.ModifyReceiver; import com.llamalad7.mixinextras.sugar.Local; import meteordevelopment.meteorclient.utils.tooltip.MeteorTooltipData; -import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; -import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; -import net.minecraft.resources.Identifier; -import net.minecraft.util.FormattedCharSequence; import net.minecraft.world.inventory.tooltip.TooltipComponent; -import org.jspecify.annotations.Nullable; 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 java.util.List; import java.util.Optional; @@ -27,15 +20,18 @@ @Mixin(value = GuiGraphicsExtractor.class) public abstract class GuiGraphicsExtractorMixin { - @Inject(method = "setTooltipForNextFrame(Lnet/minecraft/client/gui/Font;Ljava/util/List;Ljava/util/Optional;Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;IIZLnet/minecraft/resources/Identifier;)V", at = @At(value = "INVOKE", target = "Ljava/util/Optional;ifPresent(Ljava/util/function/Consumer;)V", shift = At.Shift.BEFORE)) - private void onDrawTooltip(Font font, List tooltip, Optional component, ClientTooltipPositioner positioner, int xo, int yo, boolean replaceExisting, @Nullable Identifier style, CallbackInfo ci, @Local(name = "components") List components) { - if (component.isPresent() && component.get() instanceof MeteorTooltipData meteorTooltipData) + // Both overloads convert the tooltip image with ClientTooltipComponent.create(), which returns null for MeteorTooltipData, + // so add Meteor's own component instead and skip the vanilla conversion + @ModifyReceiver(method = { + "setTooltipForNextFrame(Lnet/minecraft/client/gui/Font;Ljava/util/List;Ljava/util/Optional;Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;IIZLnet/minecraft/resources/Identifier;)V", + "setTooltipForNextFrame(Lnet/minecraft/client/gui/Font;Ljava/util/List;Ljava/util/Optional;IILnet/minecraft/resources/Identifier;Z)V" + }, at = @At(value = "INVOKE", target = "Ljava/util/Optional;ifPresent(Ljava/util/function/Consumer;)V")) + private Optional onDrawTooltip(Optional data, Consumer action, @Local(name = "components") List components) { + if (data.isPresent() && data.get() instanceof MeteorTooltipData meteorTooltipData) { components.add(meteorTooltipData.getComponent()); - } + return Optional.empty(); + } - @ModifyReceiver(method = "setTooltipForNextFrame(Lnet/minecraft/client/gui/Font;Ljava/util/List;Ljava/util/Optional;Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;IIZLnet/minecraft/resources/Identifier;)V", at = @At(value = "INVOKE", target = "Ljava/util/Optional;ifPresent(Ljava/util/function/Consumer;)V")) - private Optional onDrawTooltip_modifyIfPresentReceiver(Optional data, Consumer action) { - if (data.isPresent() && data.get() instanceof MeteorTooltipData) return Optional.empty(); return data; } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java index d48a6a501e9..81a87334234 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/LevelRendererMixin.java @@ -9,8 +9,10 @@ import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.resource.GraphicsResourceAllocator; import com.mojang.blaze3d.resource.ResourceHandle; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.renderpearl.api.buffers.GpuBufferSlice; +import com.mojang.renderpearl.api.commands.RenderPass; import it.unimi.dsi.fastutil.Stack; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import meteordevelopment.meteorclient.mixininterface.IEntityRenderState; @@ -33,12 +35,15 @@ import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.world.entity.Entity; import org.joml.Vector4f; +import org.joml.Vector4fc; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Optional; +import java.util.OptionalDouble; import java.util.function.Function; import static meteordevelopment.meteorclient.MeteorClient.mc; @@ -124,7 +129,7 @@ private void draw(LevelRenderState worldState, PoseStack matrices, EntityShader meteor$pushEntityOutlineFramebuffer(shader.framebuffer); try { try (var frame = renderDispatcher.prepareFrame(outlineRenderCommandQueue)) { - executeOutline(frame); + meteor$executeOutline(frame); } } finally { outlineRenderCommandQueue.submitsPerOrder.clear(); @@ -132,6 +137,17 @@ private void draw(LevelRenderState worldState, PoseStack matrices, EntityShader } } + // Same as executeOutline(), but without going through it, since other mods inject into it expecting to be inside the main pass + @Unique + private void meteor$executeOutline(FeatureRenderDispatcher.PreparedFrame frame) { + if (!currentFrameRendersEntityOutline) return; + + try (RenderPass pass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(() -> "Meteor entity outline", entityOutlineTarget.getColorTextureView(), Optional.of(ZERO_CLEAR_COLOR), null, OptionalDouble.empty())) { + RenderSystem.bindDefaultUniforms(pass); + frame.executeOutline(pass); + } + } + @Inject(method = "lambda$addMainPass$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;executeOutline(Lnet/minecraft/client/renderer/feature/FeatureRenderDispatcher$PreparedFrame;)V", shift = At.Shift.AFTER)) private void addMainPass$submitEntityVertices(CallbackInfo ci) { PostProcessShaders.submitEntityVertices(); @@ -161,7 +177,11 @@ private void onResize(int width, int height, CallbackInfo ci) { private RenderBuffers renderBuffers; @Shadow - protected abstract void executeOutline(FeatureRenderDispatcher.PreparedFrame featureFrame); + private boolean currentFrameRendersEntityOutline; + + @Shadow + @Final + private static Vector4fc ZERO_CLEAR_COLOR; @Unique private Stack framebufferStack; diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java index dd8385b0d85..5e5127110ca 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java @@ -61,7 +61,8 @@ private static void onDefaultHandleClickEvent(ClickEvent event, Minecraft minecr @Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true) private void onKeyPressed(KeyEvent event, CallbackInfoReturnable cir) { - if ((Object) (this) instanceof ChatScreen) return; + // Input events are pumped while the game is still starting, before Meteor has initialized + if ((Object) (this) instanceof ChatScreen || Modules.get() == null) return; GUIMove guiMove = Modules.get().get(GUIMove.class); if ((guiMove.disableArrows() && meteor$isArray(event.key())) || (guiMove.disableSpace() && event.key() == KEY_SPACE)) { cir.setReturnValue(true); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/accounts/MicrosoftLogin.java b/src/main/java/meteordevelopment/meteorclient/systems/accounts/MicrosoftLogin.java index e32fe1e561b..3e5254e09eb 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/accounts/MicrosoftLogin.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/accounts/MicrosoftLogin.java @@ -5,9 +5,9 @@ package meteordevelopment.meteorclient.systems.accounts; +import com.mojang.blaze3d.Blaze3D; import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.utils.network.MeteorExecutor; -import net.minecraft.util.Util; import net.raphimc.minecraftauth.MinecraftAuth; import net.raphimc.minecraftauth.java.JavaAuthManager; import net.raphimc.minecraftauth.java.model.MinecraftProfile; @@ -19,6 +19,7 @@ import net.raphimc.minecraftauth.msa.service.impl.DeviceCodeMsaAuthService; import org.jspecify.annotations.Nullable; +import java.net.URI; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -54,7 +55,7 @@ public static String getRefreshToken(Consumer callback) { .login(DeviceCodeMsaAuthService::new, (Consumer) deviceCode -> { String urlString = deviceCode.getDirectVerificationUri(); urlFuture.complete(urlString); - Util.getPlatform().openUri(urlString); + Blaze3D.openUri(URI.create(urlString)); }); MsaToken msaToken = authManager.getMsaToken().getUpToDate(); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/DiscordPresence.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/DiscordPresence.java index a8dda6dab0d..01de40a4f28 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/DiscordPresence.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/DiscordPresence.java @@ -7,6 +7,7 @@ //Created by squidoodly +import com.mojang.blaze3d.Blaze3D; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import meteordevelopment.discordipc.DiscordIPC; import meteordevelopment.discordipc.RichPresence; @@ -34,9 +35,9 @@ import net.minecraft.client.gui.screens.worldselection.EditWorldScreen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen; import net.minecraft.realms.RealmsScreen; -import net.minecraft.util.Util; import org.meteordev.starscript.Script; +import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -288,7 +289,7 @@ private void onOpenScreen(OpenScreenEvent event) { @Override public WWidget getWidget(GuiTheme theme) { WButton help = theme.button("Open documentation."); - help.action = () -> Util.getPlatform().openUri("https://github.com/MeteorDevelopment/meteor-client/wiki/Starscript"); + help.action = () -> Blaze3D.openUri(URI.create("https://github.com/MeteorDevelopment/meteor-client/wiki/Starscript")); return help; } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/swarm/Swarm.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/swarm/Swarm.java index c3c5317c5f3..ef06a936e79 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/swarm/Swarm.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/swarm/Swarm.java @@ -5,6 +5,7 @@ package meteordevelopment.meteorclient.systems.modules.misc.swarm; +import com.mojang.blaze3d.Blaze3D; import meteordevelopment.meteorclient.events.game.GameJoinedEvent; import meteordevelopment.meteorclient.events.game.GameLeftEvent; import meteordevelopment.meteorclient.events.world.TickEvent; @@ -17,7 +18,8 @@ import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.orbit.EventHandler; -import net.minecraft.util.Util; + +import java.net.URI; public class Swarm extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); @@ -72,7 +74,7 @@ public WWidget getWidget(GuiTheme theme) { stop.action = this::close; WButton guide = list.add(theme.button("Guide")).expandX().widget(); - guide.action = () -> Util.getPlatform().openUri("https://github.com/MeteorDevelopment/meteor-client/wiki/Swarm-Guide"); + guide.action = () -> Blaze3D.openUri(URI.create("https://github.com/MeteorDevelopment/meteor-client/wiki/Swarm-Guide")); return list; } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/misc/Keybind.java b/src/main/java/meteordevelopment/meteorclient/utils/misc/Keybind.java index 61fa056d20c..05cfa022e81 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/misc/Keybind.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/misc/Keybind.java @@ -251,17 +251,105 @@ public Keybind fromTag(CompoundTag tag) { } catch (IllegalArgumentException ignored) {} } } else { - // Legacy format: raw ints (GLFW) + // Legacy format: raw GLFW key codes, mouse buttons and modifier bits. + // Input is SDL based now, so translate them through the key names, which stayed the same. boolean isKey = tag.getBooleanOr("isKey", true); - int value = tag.getIntOr("value", InputConstants.UNKNOWN.getValue()); + int value = tag.getIntOr("value", -1); int mods = tag.getIntOr("modifiers", 0); - set(isKey ? keyboard(value) : mouse(value), isKey ? Modifier.fromRawValue(mods) : Set.of()); + set(isKey ? legacyKeyboard(value) : legacyMouse(value), isKey ? legacyModifiers(mods) : Set.of()); } return this; } + private static InputConstants.Key legacyKeyboard(int glfwKey) { + String name = switch (glfwKey) { + case 32 -> "space"; + case 39 -> "apostrophe"; + case 44 -> "comma"; + case 45 -> "minus"; + case 46 -> "period"; + case 47 -> "slash"; + case 59 -> "semicolon"; + case 61 -> "equal"; + case 91 -> "left.bracket"; + case 92 -> "backslash"; + case 93 -> "right.bracket"; + case 96 -> "grave.accent"; + case 161 -> "world.1"; + case 162 -> "world.2"; + case 256 -> "escape"; + case 257 -> "enter"; + case 258 -> "tab"; + case 259 -> "backspace"; + case 260 -> "insert"; + case 261 -> "delete"; + case 262 -> "right"; + case 263 -> "left"; + case 264 -> "down"; + case 265 -> "up"; + case 266 -> "page.up"; + case 267 -> "page.down"; + case 268 -> "home"; + case 269 -> "end"; + case 280 -> "caps.lock"; + case 281 -> "scroll.lock"; + case 282 -> "num.lock"; + case 283 -> "print.screen"; + case 284 -> "pause"; + case 330 -> "keypad.decimal"; + case 331 -> "keypad.divide"; + case 332 -> "keypad.multiply"; + case 333 -> "keypad.subtract"; + case 334 -> "keypad.add"; + case 335 -> "keypad.enter"; + case 336 -> "keypad.equal"; + case 340 -> "left.shift"; + case 341 -> "left.control"; + case 342 -> "left.alt"; + case 343 -> "left.win"; + case 344 -> "right.shift"; + case 345 -> "right.control"; + case 346 -> "right.alt"; + case 347 -> "right.win"; + case 348 -> "menu"; + default -> { + if (glfwKey >= 48 && glfwKey <= 57) yield String.valueOf((char) glfwKey); // 0-9 + if (glfwKey >= 65 && glfwKey <= 90) yield String.valueOf((char) (glfwKey + 32)); // a-z + if (glfwKey >= 290 && glfwKey <= 313) yield "f" + (glfwKey - 289); // F1-F24 + if (glfwKey >= 320 && glfwKey <= 329) yield "keypad." + (glfwKey - 320); // keypad 0-9 + yield null; + } + }; + + return name == null ? InputConstants.UNKNOWN : InputConstants.getKey("key.keyboard." + name); + } + + private static InputConstants.Key legacyMouse(int glfwButton) { + String name = switch (glfwButton) { + case 0 -> "left"; + case 1 -> "right"; + case 2 -> "middle"; + default -> String.valueOf(glfwButton + 1); + }; + + return glfwButton < 0 ? InputConstants.UNKNOWN : InputConstants.getKey("key.mouse." + name); + } + + private static Set legacyModifiers(int glfwMods) { + Set result = EnumSet.noneOf(Modifier.class); + + if ((glfwMods & 0x01) != 0) result.add(Modifier.SHIFT); + if ((glfwMods & 0x02) != 0) result.add(Modifier.CONTROL); + if ((glfwMods & 0x04) != 0) result.add(Modifier.ALT); + if ((glfwMods & 0x08) != 0) result.add(Modifier.SUPER); + if ((glfwMods & 0x10) != 0) result.add(Modifier.CAPS_LOCK); + if ((glfwMods & 0x20) != 0) result.add(Modifier.NUM_LOCK); + + return result; + } + private static InputConstants.Key keyboard(int key) { return InputConstants.Type.KEYBOARD.getOrCreate(key); }