From 4d7a79f517e9bf97911bd35c311ea93ae6b4e76b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 7 Mar 2026 16:00:51 +0100 Subject: [PATCH] HudEditor moved to common --- .../saturnclient/client/ServiceClient.java | 205 ++++++++++++++++++ .../saturnclient/client/ServiceMethods.java | 113 ++++++++++ .../client/player/PlayerTracker.java | 52 +++++ .../org/saturnclient/client/player/Roles.java | 61 ++++++ .../client/player/SaturnPlayer.java | 54 +++++ .../common/minecraft/MinecraftProvider.java | 4 + .../org/saturnclient/ui/SaturnScreen.java | 3 + .../ui/components/SaturnModule.java | 4 +- .../saturnclient/ui/components/Sidebar.java | 10 +- .../saturnclient/ui/screens/HudEditor.java | 132 +++++++++++ .../saturnclient/event/KeyInputHandler.java | 5 +- .../saturnclient/ui/SaturnScreenFabric.java | 1 + 12 files changed, 635 insertions(+), 9 deletions(-) create mode 100644 common/src/main/java/org/saturnclient/client/ServiceClient.java create mode 100644 common/src/main/java/org/saturnclient/client/ServiceMethods.java create mode 100644 common/src/main/java/org/saturnclient/client/player/PlayerTracker.java create mode 100644 common/src/main/java/org/saturnclient/client/player/Roles.java create mode 100644 common/src/main/java/org/saturnclient/client/player/SaturnPlayer.java create mode 100644 common/src/main/java/org/saturnclient/ui/screens/HudEditor.java diff --git a/common/src/main/java/org/saturnclient/client/ServiceClient.java b/common/src/main/java/org/saturnclient/client/ServiceClient.java new file mode 100644 index 0000000..4102704 --- /dev/null +++ b/common/src/main/java/org/saturnclient/client/ServiceClient.java @@ -0,0 +1,205 @@ +package org.saturnclient.saturnclient.client; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.saturnclient.cosmetics.cloak.Cloaks; +import org.saturnclient.cosmetics.hat.Hats; +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; + +import dev.kosmx.playerAnim.api.layered.AnimationStack; +import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; +import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationRegistry; +import dev.selimaj.session.Session; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.util.Identifier; + +public class ServiceClient { + private static Session session; + public static UUID uuid; + + public static boolean connectTimeout() { + try { + session = Session.connect("wss://saturn-server.selimaj.dev", 10, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + return false; + } + } + + public static boolean authenticate() { + ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> { + if (session != null) + try { + session.close(); + } catch (Exception e) { + SaturnClient.LOGGER.error("Unable to close Saturn session"); + + } + }); + + try { + var mcSession = SaturnClient.client.getSession(); + if (mcSession == null) { + SaturnClient.LOGGER.error("No active Minecraft session found"); + return false; + } + + String accessToken = mcSession.getAccessToken(); + uuid = mcSession.getUuidOrNull(); + String username = mcSession.getUsername(); + + SaturnClient.LOGGER.info("Authenticating with UUID: " + uuid); + + if (!connectTimeout()) { + SaturnClient.LOGGER.error("Unable to authenticate: Session Server Timeout"); + return false; + } + + ServiceMethods.Types.Player response = session.request(ServiceMethods.Authenticate, accessToken) + .get(); + + for (String availableCloak : response.cloaks()) { + Cloaks.availableCloaks.add(availableCloak); + } + + for (String availableHat : response.hats()) { + Hats.availableHats.add(availableHat); + } + + eventHandlers(); + + SaturnPlayer.set(new SaturnPlayer(uuid, username, response.cloak(), response.hat())); + + Cloaks.loadCloak(uuid); + + return true; + } catch (Exception e) { + SaturnClient.LOGGER.error("Authentication failed", e); + return false; + } + } + + public static void setCloak(String itemId) { + try { + session.request(ServiceMethods.SetCloak, itemId).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + try { + session.request(ServiceMethods.SendPlayer, + new ServiceMethods.Types.SendPlayerRequest(SaturnPlayer.getExternalUUIDAsString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } catch (Exception e) { + SaturnClient.LOGGER.error("Failed to set cloak (service): ", e); + } + } + + public static void setHat(String itemId) { + try { + session.request(ServiceMethods.SetHat, itemId).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + try { + session.request(ServiceMethods.SendPlayer, + new ServiceMethods.Types.SendPlayerRequest(SaturnPlayer.getExternalUUIDAsString())); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } catch (Exception e) { + SaturnClient.LOGGER.error("Failed to set hat (service): ", e); + } + } + + public static void buyCloak(String itemId) { + try { + session.request(ServiceMethods.BuyCloak, itemId).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + Cloaks.availableCloaks.add(itemId); + } + }); + } catch (Exception e) { + SaturnClient.LOGGER.error("Failed to buy cloak (service): ", e); + } + } + + public static void buyHat(String itemId) { + try { + session.request(ServiceMethods.BuyHat, itemId).whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + Hats.availableHats.add(itemId); + } + }); + } catch (Exception e) { + SaturnClient.LOGGER.error("Failed to buy hat (service): ", e); + } + } + + public static void emote(String emote) { + try { + session.request(ServiceMethods.Emote, + new ServiceMethods.Types.EmoteRequest(emote, SaturnPlayer.getExternalUUIDAsString())) + .whenComplete((msg, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } + }); + } catch (Exception e) { + SaturnClient.LOGGER.error("Failed to emote (service): ", e); + } + } + + public static void eventHandlers() { + session.onNotification(ServiceMethods.EmoteEvent, (data) -> { + for (AbstractClientPlayerEntity player : SaturnClient.client.world.getPlayers()) { + if (player.getUuidAsString().equals(data.from())) { + AnimationStack animationStack = PlayerAnimationAccess.getPlayerAnimLayer(player); + if (data.emote() != null && !data.emote().isEmpty()) { + if (animationStack.isActive() && animationStack.getPriority() == 1000) { + animationStack.removeLayer(1000); + } + animationStack.addAnimLayer(1000, + PlayerAnimationRegistry + .getAnimation(Identifier.of("saturnclient", data.emote())) + .playAnimation()); + } else { + animationStack.removeLayer(1000); + } + } + } + }); + + session.onNotification(ServiceMethods.Player, (player) -> { + System.out.println(player); + SaturnPlayer.set(player.toSaturnPlayer()); + }); + } + + public static void player(UUID uuid, String name) { + try { + session.request(ServiceMethods.GetPlayer, uuid.toString()) + .whenComplete((user, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else if (user != null) { + SaturnPlayer.set(user.toSaturnPlayer(uuid, name)); + } + }); + } catch (Exception e) { + SaturnClient.LOGGER.error("Failed to get player", e); + } + } +} diff --git a/common/src/main/java/org/saturnclient/client/ServiceMethods.java b/common/src/main/java/org/saturnclient/client/ServiceMethods.java new file mode 100644 index 0000000..0a09c53 --- /dev/null +++ b/common/src/main/java/org/saturnclient/client/ServiceMethods.java @@ -0,0 +1,113 @@ +package org.saturnclient.saturnclient.client; + +import java.util.UUID; + +import org.saturnclient.saturnclient.client.ServiceMethods.Types.SendPlayerRequest; +import org.saturnclient.saturnclient.client.player.SaturnPlayer; + +import dev.selimaj.session.types.Method; + +public class ServiceMethods { + + // ========================= + // Types (Rust structs) + // ========================= + public static class Types { + + public record EmoteRequest(String emote, String[] targets) { + } + + public record EmoteEvent(String emote, String from) { + } + + public record Player( + String cloak, + String hat, + String[] cloaks, + String[] hats) { + public SaturnPlayer toSaturnPlayer(UUID uuid, String name) { + return new SaturnPlayer(uuid, name, cloak, hat); + } + } + + public record PlayerStream(Player player, String name, String uuid) { + public SaturnPlayer toSaturnPlayer() { + return new SaturnPlayer(UUID.fromString(uuid), name, this.player.cloak, this.player.hat); + } + } + + public record SendPlayerRequest(String[] targets) { + } + } + + // ========================= + // AUTH + // ========================= + public static final Method Authenticate = new Method<>("auth", + String.class, + Types.Player.class, + String.class); + + // ========================= + // EQUIP + // ========================= + public static final Method SetCloak = new Method<>("set_cloak", + String.class, + String.class, + String.class); + + public static final Method SetHat = new Method<>("set_hat", + String.class, + String.class, + String.class); + + // ========================= + // BUY + // ========================= + public static final Method BuyCloak = new Method<>("buy_cloak", + String.class, + String.class, + String.class); + + public static final Method BuyHat = new Method<>("buy_hat", + String.class, + String.class, + String.class); + + // ========================= + // EMOTE + // ========================= + public static final Method Emote = new Method<>("emote", + Types.EmoteRequest.class, + Void.class, + String.class); + + public static final Method EmoteEvent = new Method<>("emote_event", + Types.EmoteEvent.class, + Void.class, + Void.class); + + // ========================= + // GET PLAYER + // ========================= + public static final Method GetPlayer = new Method<>("get_player", + String.class, + Types.Player.class, + String.class); + + // ========================= + // PLAYER (Server Notification) + // ========================= + public static final Method Player = new Method<>("player", + Types.PlayerStream.class, + Void.class, + Void.class); + + // ========================= + // SEND PLAYER + // ========================= + public static final Method SendPlayer = new Method<>("send_player", + SendPlayerRequest.class, + Void.class, + String.class); +} \ No newline at end of file diff --git a/common/src/main/java/org/saturnclient/client/player/PlayerTracker.java b/common/src/main/java/org/saturnclient/client/player/PlayerTracker.java new file mode 100644 index 0000000..f43347f --- /dev/null +++ b/common/src/main/java/org/saturnclient/client/player/PlayerTracker.java @@ -0,0 +1,52 @@ +package org.saturnclient.saturnclient.client.player; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.client.ServiceClient; + +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.client.MinecraftClient; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import com.mojang.authlib.GameProfile; + +public class PlayerTracker { + private static Set trackedPlayers = new HashSet<>(); + + public static void initialize() { + // When client joins a server, reset tracked players + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { + trackedPlayers.clear(); + client.execute(() -> { + checkForNewPlayers(SaturnClient.client); + }); + }); + + // Check for new players every tick + ClientTickEvents.END_CLIENT_TICK.register(client -> checkForNewPlayers(client)); + } + + private static void checkForNewPlayers(MinecraftClient client) { + if (client.getNetworkHandler() == null) + return; + + for (PlayerListEntry player : client.getNetworkHandler().getPlayerList()) { + UUID playerUUID = player.getProfile().getId(); + + if (!trackedPlayers.contains(playerUUID)) { + // A new player has joined + onPlayerJoin(client, player); + trackedPlayers.add(playerUUID); + } + } + } + + private static void onPlayerJoin(MinecraftClient client, PlayerListEntry player) { + GameProfile profile = player.getProfile(); + ServiceClient.player(profile.getId(), profile.getName()); + } +} diff --git a/common/src/main/java/org/saturnclient/client/player/Roles.java b/common/src/main/java/org/saturnclient/client/player/Roles.java new file mode 100644 index 0000000..869b202 --- /dev/null +++ b/common/src/main/java/org/saturnclient/client/player/Roles.java @@ -0,0 +1,61 @@ +package org.saturnclient.saturnclient.client.player; + +import java.util.Map; +import java.util.UUID; + +import org.saturnclient.config.Config; + +import net.minecraft.util.Formatting; + +public class Roles { + static enum Role { + OWNER, + ADMIN, + PARTNER, + CONTRIBUTOR + } + + private static final Map ROLES = Map.of( + UUID.fromString("d362a042-28bd-49e1-a807-ae74dbe8aba9"), + Role.OWNER, + UUID.fromString("d8dc7023-179b-4460-bcf6-493fbf1289a6"), + Role.CONTRIBUTOR); + + /* + * Gets the icon color of a specific individual, here are the different colors + * + * - Owner: Dark Red + * - Admin: Red + * - Partners: Gold + * - Contributor: Aqua + * - Other/player: White + */ + public static Formatting getIconColor(UUID uuid) { + Role role = ROLES.get(uuid); + + if (role == null) { + return Formatting.WHITE; + } + + switch (role) { + case OWNER: + return Formatting.DARK_RED; + + case ADMIN: + return Formatting.RED; + + case PARTNER: + return Formatting.GOLD; + + case CONTRIBUTOR: + return Formatting.AQUA; + + default: + return Formatting.WHITE; + } + } + + public static String getSaturnIndicator() { + return Config.realisticLogo.value ? "" : ""; + } +} diff --git a/common/src/main/java/org/saturnclient/client/player/SaturnPlayer.java b/common/src/main/java/org/saturnclient/client/player/SaturnPlayer.java new file mode 100644 index 0000000..f4c935e --- /dev/null +++ b/common/src/main/java/org/saturnclient/client/player/SaturnPlayer.java @@ -0,0 +1,54 @@ +package org.saturnclient.saturnclient.client.player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.jetbrains.annotations.Nullable; +import org.saturnclient.saturnclient.client.ServiceClient; + +public class SaturnPlayer { + private static Map PLAYERS = new HashMap<>(); + private static Map PLAYER_NAMES = new HashMap<>(); + + public String cloak = ""; + public String hat = ""; + public final UUID uuid; + public final String name; + + public SaturnPlayer(UUID uuid, String name, String cloak, String hat) { + this.cloak = cloak; + this.hat = hat; + this.uuid = uuid; + this.name = name; + } + + @Nullable + public static SaturnPlayer get() { + return PLAYERS.get(ServiceClient.uuid); + } + + @Nullable + public static SaturnPlayer get(UUID uuid) { + return PLAYERS.get(uuid); + } + + @Nullable + public static SaturnPlayer get(String name) { + UUID uuid = PLAYER_NAMES.get(name); + if (uuid == null) + return null; + return PLAYERS.get(uuid); + } + + public static void set(SaturnPlayer player) { + PLAYER_NAMES.put(player.name, player.uuid); + PLAYERS.put(player.uuid, player); + } + + public static String[] getExternalUUIDAsString() { + return PLAYERS.keySet().stream().filter(id -> !id.equals(ServiceClient.uuid)).map(UUID::toString) + .toArray(String[]::new); + } + +} diff --git a/common/src/main/java/org/saturnclient/common/minecraft/MinecraftProvider.java b/common/src/main/java/org/saturnclient/common/minecraft/MinecraftProvider.java index b8d0998..942c9a0 100644 --- a/common/src/main/java/org/saturnclient/common/minecraft/MinecraftProvider.java +++ b/common/src/main/java/org/saturnclient/common/minecraft/MinecraftProvider.java @@ -1,6 +1,8 @@ package org.saturnclient.common.minecraft; import org.saturnclient.common.minecraft.bindings.SaturnIdentifier; +import org.saturnclient.ui.SaturnScreen; + import java.awt.image.BufferedImage; public abstract class MinecraftProvider { @@ -8,6 +10,8 @@ public abstract class MinecraftProvider { public abstract IMinecraftClient getClient(); + public abstract IMinecraftClient setScreen(SaturnScreen screen); + public abstract Object createIdentifier(String namespace, String path); public abstract boolean isKeyPressed(int key); diff --git a/common/src/main/java/org/saturnclient/ui/SaturnScreen.java b/common/src/main/java/org/saturnclient/ui/SaturnScreen.java index a3cb4bf..fe47578 100644 --- a/common/src/main/java/org/saturnclient/ui/SaturnScreen.java +++ b/common/src/main/java/org/saturnclient/ui/SaturnScreen.java @@ -111,4 +111,7 @@ public abstract class SaturnScreen { public boolean shouldPause() { return true; } + + public void onClose() { + } } diff --git a/common/src/main/java/org/saturnclient/ui/components/SaturnModule.java b/common/src/main/java/org/saturnclient/ui/components/SaturnModule.java index 140b57b..4ce7864 100644 --- a/common/src/main/java/org/saturnclient/ui/components/SaturnModule.java +++ b/common/src/main/java/org/saturnclient/ui/components/SaturnModule.java @@ -1,7 +1,7 @@ package org.saturnclient.ui.components; import org.saturnclient.modules.Module; -import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.common.minecraft.MinecraftProvider; import org.saturnclient.config.Theme; import org.saturnclient.ui.Element; import org.saturnclient.ui.ElementContext; @@ -141,7 +141,7 @@ public class SaturnModule extends Element { 1.0f); if (settingsHover) { - SaturnClient.client.setScreen(new ConfigEditor(mod.getConfig())); + MinecraftProvider.PROVIDER.setScreen(new ConfigEditor(mod.getConfig())); } else { mod.setEnabled(!mod.isEnabled()); } diff --git a/common/src/main/java/org/saturnclient/ui/components/Sidebar.java b/common/src/main/java/org/saturnclient/ui/components/Sidebar.java index 8c4ef45..9a781ce 100644 --- a/common/src/main/java/org/saturnclient/ui/components/Sidebar.java +++ b/common/src/main/java/org/saturnclient/ui/components/Sidebar.java @@ -1,6 +1,6 @@ package org.saturnclient.ui.components; -import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.common.minecraft.MinecraftProvider; import org.saturnclient.common.minecraft.bindings.SaturnIdentifier; import org.saturnclient.config.Config; import org.saturnclient.config.Theme; @@ -30,14 +30,14 @@ public class Sidebar extends Element { Runnable onClose; SidebarComponent[] components = { new Sidebar.SidebarComponent(Textures.MODS_TAB, () -> { - SaturnClient.client.setScreen(new ModMenu()); + MinecraftProvider.PROVIDER.setScreen(new ModMenu()); }, false), new Sidebar.SidebarComponent(Textures.SETTINGS, () -> { - SaturnClient.client.setScreen(new ConfigEditor(Config.config)); + MinecraftProvider.PROVIDER.setScreen(new ConfigEditor(Config.config)); }, false), new Sidebar.SidebarComponent(Textures.SHIRT, () -> { - SaturnClient.client.setScreen(new CloakMenu()); + MinecraftProvider.PROVIDER.setScreen(new CloakMenu()); }, false), new Sidebar.SidebarComponent(Textures.CLOSE, () -> { @@ -45,7 +45,7 @@ public class Sidebar extends Element { }, true), new Sidebar.SidebarComponent(Textures.STORE, () -> { - SaturnClient.client.setScreen(new CloakStore()); + MinecraftProvider.PROVIDER.setScreen(new CloakStore()); }, true), }; int active = 0; diff --git a/common/src/main/java/org/saturnclient/ui/screens/HudEditor.java b/common/src/main/java/org/saturnclient/ui/screens/HudEditor.java new file mode 100644 index 0000000..178d068 --- /dev/null +++ b/common/src/main/java/org/saturnclient/ui/screens/HudEditor.java @@ -0,0 +1,132 @@ +package org.saturnclient.ui.screens; + +import org.saturnclient.modules.HudMod; +import org.saturnclient.modules.ModDimensions; +import org.saturnclient.modules.ModManager; +import org.saturnclient.modules.Module; +import org.saturnclient.common.minecraft.render.IMatrixStack; +import org.saturnclient.config.manager.ConfigManager; +import org.saturnclient.ui.RenderScope; +import org.saturnclient.ui.SaturnScreen; + +import java.util.ArrayList; +import java.util.List; + +public class HudEditor extends SaturnScreen { + private final List hudMods = new ArrayList<>(); + private HudMod draggingMod = null; + private boolean resizing = false; + private int offsetX, offsetY; + private static final int RESIZE_MARGIN = 3; + + public HudEditor() { + super("HUD Editor"); + for (Module m : ModManager.ENABLED_MODS) { + if (m.isEnabled() && m instanceof HudMod) { + hudMods.add((HudMod) m); + } + } + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (button == 0) { + for (int m = hudMods.size() - 1; m >= 0; m--) { + HudMod mod = hudMods.get(m); + ModDimensions dim = mod.getDimensions(); + + // Check if clicking the corner for resizing + if (isCorner(mouseX, mouseY, dim)) { + draggingMod = mod; + resizing = true; + offsetX = (int) (mouseX - (dim.x.value + dim.width * dim.scale.value)); + offsetY = (int) (mouseY - (dim.y.value + dim.height * dim.scale.value)); + return true; + } + + // Check if clicking inside the mod + if (isInside(mouseX, mouseY, dim)) { + draggingMod = mod; + resizing = false; + offsetX = (int) (mouseX - dim.x.value); + offsetY = (int) (mouseY - dim.y.value); + return true; + } + } + } + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + if (button == 0) { + draggingMod = null; + resizing = false; + } + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (draggingMod != null) { + ModDimensions dim = draggingMod.getDimensions(); + + if (resizing) { + // Scale based on cursor movement + float newScale = Math.max(0.5f, ((float) (mouseX - dim.x.value) / dim.width)); + dim.scale.value = newScale; + } else { + // Move the mod + dim.x.value = (int) mouseX - offsetX; + dim.y.value = (int) mouseY - offsetY; + } + } + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + @Override + public void ui() { + } + + @Override + public void render(RenderScope renderScope, int mouseX, int mouseY, float delta, long elapsed) { + for (HudMod mod : hudMods) { + ModDimensions dim = mod.getDimensions(); + IMatrixStack matrices = renderScope.getMatrixStack(); + matrices.push(); + + matrices.translate(dim.x.value, dim.y.value, 0); + matrices.scale(dim.scale.value, dim.scale.value, 1.0f); + + // Render the mod + mod.renderDummy(renderScope); + + matrices.pop(); + + // Draw border around mod + int borderX = dim.x.value; + int borderY = dim.y.value; + int borderW = (int) (dim.width * dim.scale.value); + int borderH = (int) (dim.height * dim.scale.value); + + renderScope.drawBorder(borderX, borderY, borderW, borderH, 0xFFFFFFFF); // White border + } + } + + private boolean isInside(double mouseX, double mouseY, ModDimensions dim) { + return mouseX >= dim.x.value && mouseX <= dim.x.value + (dim.width * dim.scale.value) && + mouseY >= dim.y.value && mouseY <= dim.y.value + (dim.height * dim.scale.value); + } + + private boolean isCorner(double mouseX, double mouseY, ModDimensions dim) { + float rightX = dim.x.value + dim.width * dim.scale.value; + float bottomY = dim.y.value + dim.height * dim.scale.value; + + return Math.abs(mouseX - rightX) < RESIZE_MARGIN && Math.abs(mouseY - bottomY) < RESIZE_MARGIN; + } + + @Override + public void onClose() { + ConfigManager.save(); + } +} diff --git a/versions/1.21.4/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java b/versions/1.21.4/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java index 1f58ae2..a3f285b 100644 --- a/versions/1.21.4/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java +++ b/versions/1.21.4/src/main/java/org/saturnclient/saturnclient/event/KeyInputHandler.java @@ -7,6 +7,7 @@ import net.minecraft.client.util.InputUtil; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.client.ServiceClient; +import org.saturnclient.common.minecraft.MinecraftProvider; import org.saturnclient.config.Config; import org.saturnclient.ui.screens.EmoteWheel; import org.saturnclient.ui.screens.ShiftMenu; @@ -36,12 +37,12 @@ public class KeyInputHandler { // Register the event handler for the main menu key ClientTickEvents.END_CLIENT_TICK.register(client -> { if (mainMenuKeyBinding.wasPressed()) { - client.setScreen(new ShiftMenu()); + MinecraftProvider.PROVIDER.setScreen(new ShiftMenu()); } if (Config.openEmoteWheel.wasKeyPressed() && client.currentScreen == null && !InputUtil.isKeyPressed(client.getWindow().getHandle(), GLFW.GLFW_KEY_F3)) { - client.setScreen(new EmoteWheel()); + MinecraftProvider.PROVIDER.setScreen(new EmoteWheel()); } if (SaturnClient.client.player != null && SaturnClient.client.player.isSneaking()) { diff --git a/versions/1.21.4/src/main/java/org/saturnclient/ui/SaturnScreenFabric.java b/versions/1.21.4/src/main/java/org/saturnclient/ui/SaturnScreenFabric.java index f1d7fbb..631300c 100644 --- a/versions/1.21.4/src/main/java/org/saturnclient/ui/SaturnScreenFabric.java +++ b/versions/1.21.4/src/main/java/org/saturnclient/ui/SaturnScreenFabric.java @@ -128,6 +128,7 @@ public abstract class SaturnScreenFabric extends Screen implements ScreenProvide @Override public void close() { + this.screen.onClose(); super.close(); } }